diff options
Diffstat (limited to 'arch')
702 files changed, 10413 insertions, 9022 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 60cde53d266c..8bb936226dee 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -51,7 +51,7 @@ config GENERIC_CMOS_UPDATE def_bool y config GENERIC_GPIO - def_bool y + bool config ZONE_DMA bool diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h index 1b71ca70c9f6..6d9e805f18a7 100644 --- a/arch/alpha/include/asm/fcntl.h +++ b/arch/alpha/include/asm/fcntl.h @@ -51,8 +51,6 @@ #define F_EXLCK 16 /* or 3 */ #define F_SHLCK 32 /* or 4 */ -#define F_INPROGRESS 64 - #include <asm-generic/fcntl.h> #endif diff --git a/arch/alpha/include/asm/sysinfo.h b/arch/alpha/include/asm/sysinfo.h index 086aba284df2..e77d77cd07b8 100644 --- a/arch/alpha/include/asm/sysinfo.h +++ b/arch/alpha/include/asm/sysinfo.h @@ -27,13 +27,4 @@ #define UAC_NOFIX 2 #define UAC_SIGBUS 4 - -#ifdef __KERNEL__ - -/* This is the shift that is applied to the UAC bits as stored in the - per-thread flags. See thread_info.h. */ -#define UAC_SHIFT 6 - -#endif - #endif /* __ASM_ALPHA_SYSINFO_H */ diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h index 6f32f9c84a2d..ff73db022342 100644 --- a/arch/alpha/include/asm/thread_info.h +++ b/arch/alpha/include/asm/thread_info.h @@ -74,9 +74,9 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_POLLING_NRFLAG 8 /* poll_idle is polling NEED_RESCHED */ #define TIF_DIE_IF_KERNEL 9 /* dik recursion lock */ -#define TIF_UAC_NOPRINT 10 /* see sysinfo.h */ -#define TIF_UAC_NOFIX 11 -#define TIF_UAC_SIGBUS 12 +#define TIF_UAC_NOPRINT 10 /* ! Preserve sequence of following */ +#define TIF_UAC_NOFIX 11 /* ! flags as they match */ +#define TIF_UAC_SIGBUS 12 /* ! userspace part of 'osf_sysinfo' */ #define TIF_MEMDIE 13 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 14 /* restore signal mask in do_signal */ #define TIF_FREEZE 16 /* is freezing for suspend */ @@ -97,7 +97,7 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \ | _TIF_SYSCALL_TRACE) -#define ALPHA_UAC_SHIFT 10 +#define ALPHA_UAC_SHIFT TIF_UAC_NOPRINT #define ALPHA_UAC_MASK (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \ 1 << TIF_UAC_SIGBUS) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 326f0a2d56e5..01e8715e26d9 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -42,6 +42,7 @@ #include <asm/uaccess.h> #include <asm/system.h> #include <asm/sysinfo.h> +#include <asm/thread_info.h> #include <asm/hwrpb.h> #include <asm/processor.h> @@ -633,9 +634,10 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, case GSI_UACPROC: if (nbytes < sizeof(unsigned int)) return -EINVAL; - w = (current_thread_info()->flags >> UAC_SHIFT) & UAC_BITMASK; - if (put_user(w, (unsigned int __user *)buffer)) - return -EFAULT; + w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) & + UAC_BITMASK; + if (put_user(w, (unsigned int __user *)buffer)) + return -EFAULT; return 1; case GSI_PROC_TYPE: @@ -756,8 +758,8 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer, case SSIN_UACPROC: again: old = current_thread_info()->flags; - new = old & ~(UAC_BITMASK << UAC_SHIFT); - new = new | (w & UAC_BITMASK) << UAC_SHIFT; + new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT); + new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT; if (cmpxchg(¤t_thread_info()->flags, old, new) != old) goto again; diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index f0df3fbd8402..b9fc6c309d2e 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -4,9 +4,8 @@ * * (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de> * - * This driver is at all a modified version of Erik Mouw's - * Documentation/DocBook/procfs_example.c, so: thank - * you, Erik! He can be reached via email at + * This driver is a modified version of Erik Mouw's example proc + * interface, so: thank you, Erik! He can be reached via email at * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They * included a patch like this as well. Thanks for idea! diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index b9c28f3f1956..6acea1f96de3 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -360,7 +360,7 @@ sys_call_table: .quad sys_newuname .quad sys_nanosleep /* 340 */ .quad sys_mremap - .quad sys_nfsservctl + .quad sys_ni_syscall /* old nfsservctl */ .quad sys_setresuid .quad sys_getresuid .quad sys_pciconfig_read /* 345 */ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5ebc5d922ea1..8090cad0dd52 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -3,7 +3,7 @@ config ARM default y select HAVE_AOUT select HAVE_DMA_API_DEBUG - select HAVE_IDE + select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION @@ -195,7 +195,8 @@ config VECTORS_BASE The base address of exception vectors. config ARM_PATCH_PHYS_VIRT - bool "Patch physical to virtual translations at runtime" + bool "Patch physical to virtual translations at runtime" if EMBEDDED + default y depends on !XIP_KERNEL && MMU depends on !ARCH_REALVIEW || !SPARSEMEM help @@ -204,16 +205,16 @@ config ARM_PATCH_PHYS_VIRT kernel in system memory. This can only be used with non-XIP MMU kernels where the base - of physical memory is at a 16MB boundary, or theoretically 64K - for the MSM machine class. + of physical memory is at a 16MB boundary. + + Only disable this option if you know that you do not require + this feature (eg, building a kernel for a single machine) and + you need to shrink the kernel to the minimal size. -config ARM_PATCH_PHYS_VIRT_16BIT + +config GENERIC_BUG def_bool y - depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM - help - This option extends the physical to virtual translation patching - to allow physical memory down to a theoretical minimum of 64K - boundaries. + depends on BUG source "init/Kconfig" @@ -301,7 +302,6 @@ config ARCH_AT91 select ARCH_REQUIRE_GPIOLIB select HAVE_CLK select CLKDEV_LOOKUP - select ARM_PATCH_PHYS_VIRT if MMU help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. @@ -346,7 +346,6 @@ config ARCH_GEMINI config ARCH_PRIMA2 bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform" select CPU_V7 - select GENERIC_TIME select NO_IOPORT select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP @@ -385,6 +384,7 @@ config ARCH_FOOTBRIDGE select CPU_SA110 select FOOTBRIDGE select GENERIC_CLOCKEVENTS + select HAVE_IDE help Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. @@ -519,7 +519,6 @@ config ARCH_LPC32XX select ARM_AMBA select USB_ARCH_HAS_OHCI select CLKDEV_LOOKUP - select GENERIC_TIME select GENERIC_CLOCKEVENTS help Support for the NXP LPC32XX family of processors @@ -598,7 +597,6 @@ config ARCH_TEGRA bool "NVIDIA Tegra" select CLKDEV_LOOKUP select CLKSRC_MMIO - select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK @@ -631,6 +629,8 @@ config ARCH_PXA select SPARSE_IRQ select AUTO_ZRELADDR select MULTI_IRQ_HANDLER + select ARM_CPU_SUSPEND if PM + select HAVE_IDE help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. @@ -671,6 +671,7 @@ config ARCH_RPC select NO_IOPORT select ARCH_SPARSEMEM_ENABLE select ARCH_USES_GETTIMEOFFSET + select HAVE_IDE help On the Acorn Risc-PC, Linux can support the internal IDE disk and CD-ROM interface, serial and parallel port, and the floppy drive. @@ -689,6 +690,7 @@ config ARCH_SA1100 select HAVE_SCHED_CLOCK select TICK_ONESHOT select ARCH_REQUIRE_GPIOLIB + select HAVE_IDE help Support for StrongARM 11x0 based boards. @@ -722,7 +724,6 @@ config ARCH_S3C64XX select ARCH_REQUIRE_GPIOLIB select SAMSUNG_CLKSRC select SAMSUNG_IRQ_VIC_TIMER - select SAMSUNG_IRQ_UART select S3C_GPIO_TRACK select S3C_GPIO_PULL_UPDOWN select S3C_GPIO_CFG_S3C24XX @@ -910,7 +911,6 @@ config ARCH_VT8500 config ARCH_ZYNQ bool "Xilinx Zynq ARM Cortex A9 Platform" select CPU_V7 - select GENERIC_TIME select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP select ARM_GIC @@ -1271,6 +1271,32 @@ config ARM_ERRATA_754327 This workaround defines cpu_relax() as smp_mb(), preventing correctly written polling loops from denying visibility of updates to memory. +config ARM_ERRATA_364296 + bool "ARM errata: Possible cache data corruption with hit-under-miss enabled" + depends on CPU_V6 && !SMP + help + This options enables the workaround for the 364296 ARM1136 + r0p2 erratum (possible cache data corruption with + hit-under-miss enabled). It sets the undocumented bit 31 in + the auxiliary control register and the FI bit in the control + register, thus disabling hit-under-miss without putting the + processor into full low interrupt latency mode. ARM11MPCore + is not affected. + +config ARM_ERRATA_764369 + bool "ARM errata: Data cache line maintenance operation by MVA may not succeed" + depends on CPU_V7 && SMP + help + This option enables the workaround for erratum 764369 + affecting Cortex-A9 MPCore with two or more processors (all + current revisions). Under certain timing circumstances, a data + cache line maintenance operation by MVA targeting an Inner + Shareable memory region may fail to proceed up to either the + Point of Coherency or to the Point of Unification of the + system. This workaround adds a DSB instruction before the + relevant cache maintenance functions and sets a specific bit + in the diagnostic control register of the SCU. + endmenu source "arch/arm/common/Kconfig" @@ -1349,6 +1375,7 @@ config SMP MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE + depends on MMU select USE_GENERIC_SMP_HELPERS select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP help @@ -1362,7 +1389,7 @@ config SMP processor machines. On a single processor machine, the kernel will run faster if you say N here. - See also <file:Documentation/i386/IO-APIC.txt>, + See also <file:Documentation/x86/i386/IO-APIC.txt>, <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at <http://tldp.org/HOWTO/SMP-HOWTO.html>. @@ -1381,6 +1408,31 @@ config SMP_ON_UP If you don't know what to do here, say Y. +config ARM_CPU_TOPOLOGY + bool "Support cpu topology definition" + depends on SMP && CPU_V7 + default y + help + Support ARM cpu topology definition. The MPIDR register defines + affinity between processors which is then used to describe the cpu + topology of an ARM System. + +config SCHED_MC + bool "Multi-core scheduler support" + depends on ARM_CPU_TOPOLOGY + help + Multi-core scheduler support improves the CPU scheduler's decision + making when dealing with multi-core CPU chips at a cost of slightly + increased overhead in some places. If unsure say N here. + +config SCHED_SMT + bool "SMT scheduler support" + depends on ARM_CPU_TOPOLOGY + help + Improves the CPU scheduler's decision making when dealing with + MultiThreading at a cost of slightly increased overhead in some + places. If unsure say N here. + config HAVE_ARM_SCU bool help @@ -1456,6 +1508,7 @@ config THUMB2_KERNEL depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL select AEABI select ARM_ASM_UNIFIED + select ARM_UNWIND help By enabling this option, the kernel will be compiled in Thumb-2 mode. A compiler/assembler that understand the unified @@ -2075,6 +2128,9 @@ config ARCH_SUSPEND_POSSIBLE CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE def_bool y +config ARM_CPU_SUSPEND + def_bool PM_SLEEP + endmenu source "net/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 81cbe40c159c..df3eb3ccd769 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -65,13 +65,71 @@ config DEBUG_USER # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL - bool "Kernel low-level debugging functions" + bool "Kernel low-level debugging functions (read help!)" depends on DEBUG_KERNEL help Say Y here to include definitions of printascii, printch, printhex in the kernel. This is helpful if you are debugging code that executes before the console is initialized. + Note that selecting this option will limit the kernel to a single + UART definition, as specified below. Attempting to boot the kernel + image on a different platform *will not work*, so this option should + not be enabled for kernels that are intended to be portable. + +choice + prompt "Kernel low-level debugging port" + depends on DEBUG_LL + + config DEBUG_LL_UART_NONE + bool "No low-level debugging UART" + help + Say Y here if your platform doesn't provide a UART option + below. This relies on your platform choosing the right UART + definition internally in order for low-level debugging to + work. + + config DEBUG_ICEDCC + bool "Kernel low-level debugging via EmbeddedICE DCC channel" + help + Say Y here if you want the debug print routines to direct + their output to the EmbeddedICE macrocell's DCC channel using + co-processor 14. This is known to work on the ARM9 style ICE + channel and on the XScale with the PEEDI. + + Note that the system will appear to hang during boot if there + is nothing connected to read from the DCC. + + config DEBUG_FOOTBRIDGE_COM1 + bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the 8250 at PCI COM1. + + config DEBUG_DC21285_PORT + bool "Kernel low-level debugging messages via footbridge serial port" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the serial port in the DC21285 (Footbridge). + + config DEBUG_CLPS711X_UART1 + bool "Kernel low-level debugging messages via UART1" + depends on ARCH_CLPS711X + help + Say Y here if you want the debug print routines to direct + their output to the first serial port on these devices. + + config DEBUG_CLPS711X_UART2 + bool "Kernel low-level debugging messages via UART2" + depends on ARCH_CLPS711X + help + Say Y here if you want the debug print routines to direct + their output to the second serial port on these devices. + +endchoice + config EARLY_PRINTK bool "Early printk" depends on DEBUG_LL @@ -80,43 +138,14 @@ config EARLY_PRINTK kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console. -config DEBUG_ICEDCC - bool "Kernel low-level debugging via EmbeddedICE DCC channel" - depends on DEBUG_LL - help - Say Y here if you want the debug print routines to direct their - output to the EmbeddedICE macrocell's DCC channel using - co-processor 14. This is known to work on the ARM9 style ICE - channel and on the XScale with the PEEDI. - - It does include a timeout to ensure that the system does not - totally freeze when there is nothing connected to read. - config OC_ETM bool "On-chip ETM and ETB" - select ARM_AMBA + depends on ARM_AMBA help Enables the on-chip embedded trace macrocell and embedded trace buffer driver that will allow you to collect traces of the kernel code. -config DEBUG_DC21285_PORT - bool "Kernel low-level debugging messages via footbridge serial port" - depends on DEBUG_LL && FOOTBRIDGE - help - Say Y here if you want the debug print routines to direct their - output to the serial port in the DC21285 (Footbridge). Saying N - will cause the debug messages to appear on the first 16550 - serial port. - -config DEBUG_CLPS711X_UART2 - bool "Kernel low-level debugging messages via UART2" - depends on DEBUG_LL && ARCH_CLPS711X - help - Say Y here if you want the debug print routines to direct their - output to the second serial port on these devices. Saying N will - cause the debug messages to appear on the first serial port. - config DEBUG_S3C_UART depends on PLAT_SAMSUNG int "S3C UART to use for low-level debug" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 70c424eaf7b0..5665c2a3b652 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -128,6 +128,9 @@ textofs-$(CONFIG_PM_H1940) := 0x00108000 ifeq ($(CONFIG_ARCH_SA1100),y) textofs-$(CONFIG_SA1111) := 0x00208000 endif +textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000 +textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 +textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 # Machine directory name. This list is sorted alphanumerically # by CONFIG_* macro name. diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index a1edfd5a129a..176062ac7f07 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -78,7 +78,16 @@ endif $(obj)/uImage: STARTADDR=$(LOADADDR) +check_for_multiple_loadaddr = \ +if [ $(words $(LOADADDR)) -gt 1 ]; then \ + echo 'multiple load addresses: $(LOADADDR)'; \ + echo 'This is incompatible with uImages'; \ + echo 'Specify LOADADDR on the commandline to build an uImage'; \ + false; \ +fi + $(obj)/uImage: $(obj)/zImage FORCE + @$(check_for_multiple_loadaddr) $(call if_changed,uimage) @echo ' Image $@ is ready' diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0c74a6fab952..a6b30b35ca65 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -139,8 +139,16 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ ( echo "following symbols must have non local/private scope:" >&2; \ echo "$$bad_syms" >&2; rm -f $@; false ) +check_for_multiple_zreladdr = \ +if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ + echo 'multiple zreladdrs: $(ZRELADDR)'; \ + echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \ + false; \ +fi + $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE + @$(check_for_multiple_zreladdr) $(call if_changed,ld) @$(check_for_bad_syms) diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c index b6f61d9a5a1b..672ae95db5c3 100644 --- a/arch/arm/boot/compressed/mmcif-sh7372.c +++ b/arch/arm/boot/compressed/mmcif-sh7372.c @@ -82,7 +82,7 @@ asmlinkage void mmc_loader(unsigned char *buf, unsigned long len) /* Disable clock to MMC hardware block */ - __raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3); + __raw_writel(__raw_readl(SMSTPCR3) | (1 << 12), SMSTPCR3); mmc_update_progress(MMC_PROGRESS_DONE); } diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c index d403a8b24d7f..d279294f2381 100644 --- a/arch/arm/boot/compressed/sdhi-sh7372.c +++ b/arch/arm/boot/compressed/sdhi-sh7372.c @@ -85,7 +85,7 @@ asmlinkage void mmc_loader(unsigned short *buf, unsigned long len) goto err; /* Disable clock to SDHI1 hardware block */ - __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3); + __raw_writel(__raw_readl(SMSTPCR3) | (1 << 13), SMSTPCR3); mmc_update_progress(MMC_PROGRESS_DONE); diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 4c053340ce33..e5818668d091 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -57,14 +57,14 @@ }; sdhci@c8000200 { - gpios = <&gpio 69 0>, /* cd, gpio PI5 */ - <&gpio 57 0>, /* wp, gpio PH1 */ - <&gpio 155 0>; /* power, gpio PT3 */ + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 155 0>; /* gpio PT3 */ }; sdhci@c8000600 { - gpios = <&gpio 58 0>, /* cd, gpio PH2 */ - <&gpio 59 0>, /* wp, gpio PH3 */ - <&gpio 70 0>; /* power, gpio PI6 */ + cd-gpios = <&gpio 58 0>; /* gpio PH2 */ + wp-gpios = <&gpio 59 0>; /* gpio PH3 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ }; }; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index 1940cae00748..64cedca6fc79 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -21,8 +21,8 @@ }; sdhci@c8000400 { - gpios = <&gpio 69 0>, /* cd, gpio PI5 */ - <&gpio 57 0>, /* wp, gpio PH1 */ - <&gpio 70 0>; /* power, gpio PI6 */ + cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ }; }; diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 3227ca952a12..bdbb3f74f0fe 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -33,7 +33,7 @@ #include <asm/mach/irq.h> #include <asm/hardware/gic.h> -static DEFINE_SPINLOCK(irq_controller_lock); +static DEFINE_RAW_SPINLOCK(irq_controller_lock); /* Address of GIC 0 CPU interface */ void __iomem *gic_cpu_base_addr __read_mostly; @@ -82,30 +82,30 @@ static void gic_mask_irq(struct irq_data *d) { u32 mask = 1 << (d->irq % 32); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); if (gic_arch_extn.irq_mask) gic_arch_extn.irq_mask(d); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } static void gic_unmask_irq(struct irq_data *d) { u32 mask = 1 << (d->irq % 32); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); if (gic_arch_extn.irq_unmask) gic_arch_extn.irq_unmask(d); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } static void gic_eoi_irq(struct irq_data *d) { if (gic_arch_extn.irq_eoi) { - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); gic_arch_extn.irq_eoi(d); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); } writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); @@ -129,7 +129,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) return -EINVAL; - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); if (gic_arch_extn.irq_set_type) gic_arch_extn.irq_set_type(d, type); @@ -154,7 +154,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (enabled) writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); return 0; } @@ -180,12 +180,12 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, return -EINVAL; mask = 0xff << shift; - bit = 1 << (cpu + shift); + bit = 1 << (cpu_logical_map(cpu) + shift); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); val = readl_relaxed(reg) & ~mask; writel_relaxed(val | bit, reg); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); return IRQ_SET_MASK_OK; } @@ -215,9 +215,9 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); - spin_lock(&irq_controller_lock); + raw_spin_lock(&irq_controller_lock); status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK); - spin_unlock(&irq_controller_lock); + raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); if (gic_irq == 1023) @@ -259,9 +259,15 @@ static void __init gic_dist_init(struct gic_chip_data *gic, unsigned int irq_start) { unsigned int gic_irqs, irq_limit, i; + u32 cpumask; void __iomem *base = gic->dist_base; - u32 cpumask = 1 << smp_processor_id(); + u32 cpu = 0; +#ifdef CONFIG_SMP + cpu = cpu_logical_map(smp_processor_id()); +#endif + + cpumask = 1 << cpu; cpumask |= cpumask << 8; cpumask |= cpumask << 16; @@ -382,7 +388,12 @@ void __cpuinit gic_enable_ppi(unsigned int irq) #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { - unsigned long map = *cpus_addr(*mask); + int cpu; + unsigned long map = 0; + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + map |= 1 << cpu_logical_map(cpu); /* * Ensure that stores to Normal memory are visible to the diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index 97912fa48782..7129cfbdacd6 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -1546,7 +1546,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op) /* Start the next */ case PL330_OP_START: - if (!_start(thrd)) + if (!_thrd_active(thrd) && !_start(thrd)) ret = -EIO; break; diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 7aa4262ada7a..01f18a421b17 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -259,7 +259,6 @@ static void __init vic_disable(void __iomem *base) writel(0, base + VIC_INT_SELECT); writel(0, base + VIC_INT_ENABLE); writel(~0, base + VIC_INT_ENABLE_CLEAR); - writel(0, base + VIC_IRQ_STATUS); writel(0, base + VIC_ITCR); writel(~0, base + VIC_INT_SOFT_CLEAR); } @@ -347,7 +346,8 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, /* Identify which VIC cell this one is, by reading the ID */ for (i = 0; i < 4; i++) { - u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4); + void __iomem *addr; + addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4); cellid |= (readl(addr) & 0xff) << (8 * i); } vendor = (cellid >> 12) & 0xff; diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 7196ade07e27..1103f62a1964 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -1,5 +1,6 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_TINY_RCU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -8,20 +9,29 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_INTEGRATOR=y CONFIG_ARCH_INTEGRATOR_AP=y +CONFIG_ARCH_INTEGRATOR_CP=y CONFIG_CPU_ARM720T=y CONFIG_CPU_ARM920T=y +CONFIG_CPU_ARM922T=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_ARM1020=y +CONFIG_CPU_ARM1022=y +CONFIG_CPU_ARM1026=y CONFIG_PCI=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y CONFIG_LEDS=y CONFIG_LEDS_CPU=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M" +CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp" CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_FPE_NWFPE=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -32,7 +42,6 @@ CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IPV6 is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_AFS_PARTS=y CONFIG_MTD_CHAR=y @@ -40,6 +49,7 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_PHYSMAP=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 @@ -56,6 +66,8 @@ CONFIG_FB_MODE_HELPERS=y CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL030=y CONFIG_EXT2_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y @@ -68,4 +80,3 @@ CONFIG_NFSD_V3=y CONFIG_PARTITION_ADVANCED=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_ERRORS=y diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 6550db3aa5c7..960abceb8e14 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -1,3 +1,20 @@ include include/asm-generic/Kbuild.asm header-y += hwcap.h + +generic-y += auxvec.h +generic-y += bitsperlong.h +generic-y += cputime.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += ioctl.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += local.h +generic-y += local64.h +generic-y += percpu.h +generic-y += poll.h +generic-y += resource.h +generic-y += sections.h +generic-y += siginfo.h +generic-y += sizes.h diff --git a/arch/arm/include/asm/auxvec.h b/arch/arm/include/asm/auxvec.h deleted file mode 100644 index c0536f6b29a7..000000000000 --- a/arch/arm/include/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ASMARM_AUXVEC_H -#define __ASMARM_AUXVEC_H - -#endif diff --git a/arch/arm/include/asm/bitsperlong.h b/arch/arm/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b2..000000000000 --- a/arch/arm/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/bitsperlong.h> diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h index 4d88425a4169..9abe7a07d5ac 100644 --- a/arch/arm/include/asm/bug.h +++ b/arch/arm/include/asm/bug.h @@ -3,21 +3,58 @@ #ifdef CONFIG_BUG -#ifdef CONFIG_DEBUG_BUGVERBOSE -extern void __bug(const char *file, int line) __attribute__((noreturn)); - -/* give file/line information */ -#define BUG() __bug(__FILE__, __LINE__) +/* + * Use a suitable undefined instruction to use for ARM/Thumb2 bug handling. + * We need to be careful not to conflict with those used by other modules and + * the register_undef_hook() system. + */ +#ifdef CONFIG_THUMB2_KERNEL +#define BUG_INSTR_VALUE 0xde02 +#define BUG_INSTR_TYPE ".hword " #else +#define BUG_INSTR_VALUE 0xe7f001f2 +#define BUG_INSTR_TYPE ".word " +#endif -/* this just causes an oops */ -#define BUG() do { *(int *)0 = 0; } while (1) -#endif +#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE) +#define _BUG(file, line, value) __BUG(file, line, value) + +#ifdef CONFIG_DEBUG_BUGVERBOSE + +/* + * The extra indirection is to ensure that the __FILE__ string comes through + * OK. Many version of gcc do not support the asm %c parameter which would be + * preferable to this unpleasantness. We use mergeable string sections to + * avoid multiple copies of the string appearing in the kernel image. + */ + +#define __BUG(__file, __line, __value) \ +do { \ + BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ + asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ + ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ + "2:\t.asciz " #__file "\n" \ + ".popsection\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "3:\t.word 1b, 2b\n" \ + "\t.hword " #__line ", 0\n" \ + ".popsection"); \ + unreachable(); \ +} while (0) + +#else /* not CONFIG_DEBUG_BUGVERBOSE */ + +#define __BUG(__file, __line, __value) \ +do { \ + asm volatile(BUG_INSTR_TYPE #__value); \ + unreachable(); \ +} while (0) +#endif /* CONFIG_DEBUG_BUGVERBOSE */ #define HAVE_ARCH_BUG -#endif +#endif /* CONFIG_BUG */ #include <asm-generic/bug.h> diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h index c023db09fcc1..7ea78144ae22 100644 --- a/arch/arm/include/asm/cachetype.h +++ b/arch/arm/include/asm/cachetype.h @@ -7,6 +7,7 @@ #define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING) #define CACHEID_ASID_TAGGED (1 << 3) #define CACHEID_VIPT_I_ALIASING (1 << 4) +#define CACHEID_PIPT (1 << 5) extern unsigned int cacheid; @@ -16,6 +17,7 @@ extern unsigned int cacheid; #define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING) #define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED) #define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING) +#define icache_is_pipt() cacheid_is(CACHEID_PIPT) /* * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture @@ -26,7 +28,8 @@ extern unsigned int cacheid; #if __LINUX_ARM_ARCH__ >= 7 #define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\ CACHEID_ASID_TAGGED |\ - CACHEID_VIPT_I_ALIASING) + CACHEID_VIPT_I_ALIASING |\ + CACHEID_PIPT) #elif __LINUX_ARM_ARCH__ >= 6 #define __CACHEID_ARCH_MIN (~CACHEID_VIVT) #else diff --git a/arch/arm/include/asm/cputime.h b/arch/arm/include/asm/cputime.h deleted file mode 100644 index 3a8002a5fec7..000000000000 --- a/arch/arm/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARM_CPUTIME_H -#define __ARM_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* __ARM_CPUTIME_H */ diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index cd4458f64171..cb47d28cbe1f 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -8,6 +8,7 @@ #define CPUID_CACHETYPE 1 #define CPUID_TCM 2 #define CPUID_TLBTYPE 3 +#define CPUID_MPIDR 5 #define CPUID_EXT_PFR0 "c1, 0" #define CPUID_EXT_PFR1 "c1, 1" @@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void) return read_cpuid(CPUID_TCM); } +static inline unsigned int __attribute_const__ read_cpuid_mpidr(void) +{ + return read_cpuid(CPUID_MPIDR); +} + /* * Intel's XScale3 core supports some v6 features (supersections, L2) * but advertises itself as v5 as it does not support the v6 ISA. For diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index 9f390ce335cb..6615f03f56a5 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -10,6 +10,9 @@ struct dev_archdata { #ifdef CONFIG_DMABOUNCE struct dmabounce_device_info *dmabounce; #endif +#ifdef CONFIG_IOMMU_API + void *iommu; /* private IOMMU data */ +#endif }; struct pdev_archdata { diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 7a21d0bf7134..28b7ee8d7398 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -32,7 +32,7 @@ static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) { - return (void *)__bus_to_virt(addr); + return (void *)__bus_to_virt((unsigned long)addr); } static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index 628670e9d7c9..69a5b0b6455c 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -34,18 +34,18 @@ #define DMA_MODE_CASCADE 0xc0 #define DMA_AUTOINIT 0x10 -extern spinlock_t dma_spin_lock; +extern raw_spinlock_t dma_spin_lock; static inline unsigned long claim_dma_lock(void) { unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); + raw_spin_lock_irqsave(&dma_spin_lock, flags); return flags; } static inline void release_dma_lock(unsigned long flags) { - spin_unlock_irqrestore(&dma_spin_lock, flags); + raw_spin_unlock_irqrestore(&dma_spin_lock, flags); } /* Clear the 'DMA Pointer Flip Flop'. diff --git a/arch/arm/include/asm/ecard.h b/arch/arm/include/asm/ecard.h index 29f2610efc70..eaea14676d57 100644 --- a/arch/arm/include/asm/ecard.h +++ b/arch/arm/include/asm/ecard.h @@ -161,7 +161,6 @@ struct expansion_card { /* Private internal data */ const char *card_desc; /* Card description */ - CONST unsigned int podaddr; /* Base Linux address for card */ CONST loader_t loader; /* loader program */ u64 dma_mask; }; diff --git a/arch/arm/include/asm/emergency-restart.h b/arch/arm/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42e..000000000000 --- a/arch/arm/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include <asm-generic/emergency-restart.h> - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/arm/include/asm/errno.h b/arch/arm/include/asm/errno.h deleted file mode 100644 index 6e60f0612bb6..000000000000 --- a/arch/arm/include/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ARM_ERRNO_H -#define _ARM_ERRNO_H - -#include <asm-generic/errno.h> - -#endif diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h new file mode 100644 index 000000000000..5abaf5bbd985 --- /dev/null +++ b/arch/arm/include/asm/exception.h @@ -0,0 +1,19 @@ +/* + * Annotations for marking C functions as exception handlers. + * + * These should only be used for C functions that are called from the low + * level exception entry code and not any intervening C code. + */ +#ifndef __ASM_ARM_EXCEPTION_H +#define __ASM_ARM_EXCEPTION_H + +#include <linux/ftrace.h> + +#define __exception __attribute__((section(".exception.text"))) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#define __exception_irq_entry __irq_entry +#else +#define __exception_irq_entry __exception +#endif + +#endif /* __ASM_ARM_EXCEPTION_H */ diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 8c73900da9ed..253cc86318bf 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -25,17 +25,17 @@ #ifdef CONFIG_SMP -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \ smp_mb(); \ __asm__ __volatile__( \ - "1: ldrex %1, [%2]\n" \ + "1: ldrex %1, [%3]\n" \ " " insn "\n" \ - "2: strex %1, %0, [%2]\n" \ - " teq %1, #0\n" \ + "2: strex %2, %0, [%3]\n" \ + " teq %2, #0\n" \ " bne 1b\n" \ " mov %0, #0\n" \ - __futex_atomic_ex_table("%4") \ - : "=&r" (ret), "=&r" (oldval) \ + __futex_atomic_ex_table("%5") \ + : "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \ : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \ : "cc", "memory") @@ -73,14 +73,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, #include <linux/preempt.h> #include <asm/domain.h> -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \ __asm__ __volatile__( \ - "1: " T(ldr) " %1, [%2]\n" \ + "1: " T(ldr) " %1, [%3]\n" \ " " insn "\n" \ - "2: " T(str) " %0, [%2]\n" \ + "2: " T(str) " %0, [%3]\n" \ " mov %0, #0\n" \ - __futex_atomic_ex_table("%4") \ - : "=&r" (ret), "=&r" (oldval) \ + __futex_atomic_ex_table("%5") \ + : "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \ : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \ : "cc", "memory") @@ -117,7 +117,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; + int oldval = 0, ret, tmp; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; @@ -129,19 +129,19 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) switch (op) { case FUTEX_OP_SET: - __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg); + __futex_atomic_op("mov %0, %4", ret, oldval, tmp, uaddr, oparg); break; case FUTEX_OP_ADD: - __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg); + __futex_atomic_op("add %0, %1, %4", ret, oldval, tmp, uaddr, oparg); break; case FUTEX_OP_OR: - __futex_atomic_op("orr %0, %1, %3", ret, oldval, uaddr, oparg); + __futex_atomic_op("orr %0, %1, %4", ret, oldval, tmp, uaddr, oparg); break; case FUTEX_OP_ANDN: - __futex_atomic_op("and %0, %1, %3", ret, oldval, uaddr, ~oparg); + __futex_atomic_op("and %0, %1, %4", ret, oldval, tmp, uaddr, ~oparg); break; case FUTEX_OP_XOR: - __futex_atomic_op("eor %0, %1, %3", ret, oldval, uaddr, oparg); + __futex_atomic_op("eor %0, %1, %4", ret, oldval, tmp, uaddr, oparg); break; default: ret = -ENOSYS; diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 16bd48031583..434edccdf7f3 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -45,8 +45,15 @@ #define L2X0_CLEAN_INV_LINE_PA 0x7F0 #define L2X0_CLEAN_INV_LINE_IDX 0x7F8 #define L2X0_CLEAN_INV_WAY 0x7FC -#define L2X0_LOCKDOWN_WAY_D 0x900 -#define L2X0_LOCKDOWN_WAY_I 0x904 +/* + * The lockdown registers repeat 8 times for L310, the L210 has only one + * D and one I lockdown register at 0x0900 and 0x0904. + */ +#define L2X0_LOCKDOWN_WAY_D_BASE 0x900 +#define L2X0_LOCKDOWN_WAY_I_BASE 0x904 +#define L2X0_LOCKDOWN_STRIDE 0x08 +#define L2X0_ADDR_FILTER_START 0xC00 +#define L2X0_ADDR_FILTER_END 0xC04 #define L2X0_TEST_OPERATION 0xF00 #define L2X0_LINE_DATA 0xF10 #define L2X0_LINE_TAG 0xF30 @@ -60,11 +67,26 @@ #define L2X0_CACHE_ID_PART_MASK (0xf << 6) #define L2X0_CACHE_ID_PART_L210 (1 << 6) #define L2X0_CACHE_ID_PART_L310 (3 << 6) +#define L2X0_CACHE_ID_RTL_MASK 0x3f +#define L2X0_CACHE_ID_RTL_R0P0 0x0 +#define L2X0_CACHE_ID_RTL_R1P0 0x2 +#define L2X0_CACHE_ID_RTL_R2P0 0x4 +#define L2X0_CACHE_ID_RTL_R3P0 0x5 +#define L2X0_CACHE_ID_RTL_R3P1 0x6 +#define L2X0_CACHE_ID_RTL_R3P2 0x8 #define L2X0_AUX_CTRL_MASK 0xc0000fff +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) +#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) +#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) #define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 #define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 -#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x3 << 17) +#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) #define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22 #define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26 #define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27 @@ -72,8 +94,33 @@ #define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 #define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 +#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 +#define L2X0_LATENCY_CTRL_RD_SHIFT 4 +#define L2X0_LATENCY_CTRL_WR_SHIFT 8 + +#define L2X0_ADDR_FILTER_EN 1 + #ifndef __ASSEMBLY__ extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); +extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask); + +struct l2x0_regs { + unsigned long phy_base; + unsigned long aux_ctrl; + /* + * Whether the following registers need to be saved/restored + * depends on platform + */ + unsigned long tag_latency; + unsigned long data_latency; + unsigned long filter_start; + unsigned long filter_end; + unsigned long prefetch_ctrl; + unsigned long pwr_ctrl; +}; + +extern struct l2x0_regs l2x0_saved_regs; + #endif #endif diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d66605dea55a..065d100fa63e 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -80,6 +80,7 @@ extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int, extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int); +extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached); extern void __iounmap(volatile void __iomem *addr); /* @@ -110,6 +111,27 @@ static inline void __iomem *__typesafe_io(unsigned long addr) #include <mach/io.h> /* + * This is the limit of PC card/PCI/ISA IO space, which is by default + * 64K if we have PC card, PCI or ISA support. Otherwise, default to + * zero to prevent ISA/PCI drivers claiming IO space (and potentially + * oopsing.) + * + * Only set this larger if you really need inb() et.al. to operate over + * a larger address space. Note that SOC_COMMON ioremaps each sockets + * IO space area, and so inb() et.al. must be defined to operate as per + * readb() et.al. on such platforms. + */ +#ifndef IO_SPACE_LIMIT +#if defined(CONFIG_PCMCIA_SOC_COMMON) || defined(CONFIG_PCMCIA_SOC_COMMON_MODULE) +#define IO_SPACE_LIMIT ((resource_size_t)0xffffffff) +#elif defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(CONFIG_PCCARD) +#define IO_SPACE_LIMIT ((resource_size_t)0xffff) +#else +#define IO_SPACE_LIMIT ((resource_size_t)0) +#endif +#endif + +/* * IO port access primitives * ------------------------- * @@ -189,11 +211,11 @@ extern void _memset_io(volatile void __iomem *, int, size_t); * IO port primitives for more information. */ #ifdef __mem_pci -#define readb_relaxed(c) ({ u8 __v = __raw_readb(__mem_pci(c)); __v; }) -#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__mem_pci(c))); __v; }) -#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__mem_pci(c))); __v; }) +#define readb_relaxed(c) ({ u8 __r = __raw_readb(__mem_pci(c)); __r; }) +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ + __raw_readw(__mem_pci(c))); __r; }) +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl(__mem_pci(c))); __r; }) #define writeb_relaxed(v,c) ((void)__raw_writeb(v,__mem_pci(c))) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \ @@ -238,7 +260,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t); * ioremap and friends. * * ioremap takes a PCI memory address, as specified in - * Documentation/IO-mapping.txt. + * Documentation/io-mapping.txt. * */ #ifndef __arch_ioremap @@ -260,10 +282,16 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; }) #define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; }) +#define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) +#define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) + #define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); }) #define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); }) #define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); }) +#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); }) +#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); }) + #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) #define ioread32_rep(p,d,c) __raw_readsl(p,d,c) diff --git a/arch/arm/include/asm/ioctl.h b/arch/arm/include/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5..000000000000 --- a/arch/arm/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ioctl.h> diff --git a/arch/arm/include/asm/irq_regs.h b/arch/arm/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b70270..000000000000 --- a/arch/arm/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/arm/include/asm/kdebug.h b/arch/arm/include/asm/kdebug.h deleted file mode 100644 index 6ece1b037665..000000000000 --- a/arch/arm/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kdebug.h> diff --git a/arch/arm/include/asm/local.h b/arch/arm/include/asm/local.h deleted file mode 100644 index c11c530f74d0..000000000000 --- a/arch/arm/include/asm/local.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local.h> diff --git a/arch/arm/include/asm/local64.h b/arch/arm/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239..000000000000 --- a/arch/arm/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index 080d74f8128d..6fd955d34c65 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h @@ -10,6 +10,8 @@ #ifndef __ASM_ARM_LOCALTIMER_H #define __ASM_ARM_LOCALTIMER_H +#include <linux/errno.h> + struct clock_event_device; /* @@ -22,6 +24,10 @@ void percpu_timer_setup(void); */ asmlinkage void do_local_timer(struct pt_regs *); +/* + * Called from C code + */ +void handle_local_timer(struct pt_regs *); #ifdef CONFIG_LOCAL_TIMERS diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 217aa1911dd7..c5699987fa98 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -34,8 +34,7 @@ struct machine_desc { unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ unsigned int soft_reboot :1; /* soft reboot */ - void (*fixup)(struct machine_desc *, - struct tag *, char **, + void (*fixup)(struct tag *, char **, struct meminfo *); void (*reserve)(void);/* reserve mem blocks */ void (*map_io)(void);/* IO mapping function */ diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index b8de516e600e..441fc4fe8263 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -160,7 +160,6 @@ * so that all we need to do is modify the 8-bit constant field. */ #define __PV_BITS_31_24 0x81000000 -#define __PV_BITS_23_16 0x00810000 extern unsigned long __pv_phys_offset; #define PHYS_OFFSET __pv_phys_offset @@ -178,9 +177,6 @@ static inline unsigned long __virt_to_phys(unsigned long x) { unsigned long t; __pv_stub(x, t, "add", __PV_BITS_31_24); -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - __pv_stub(t, t, "add", __PV_BITS_23_16); -#endif return t; } @@ -188,9 +184,6 @@ static inline unsigned long __phys_to_virt(unsigned long x) { unsigned long t; __pv_stub(x, t, "sub", __PV_BITS_31_24); -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - __pv_stub(t, t, "sub", __PV_BITS_23_16); -#endif return t; } #else diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index b4ffe9d5b526..14965658a923 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -6,7 +6,7 @@ typedef struct { #ifdef CONFIG_CPU_HAS_ASID unsigned int id; - spinlock_t id_lock; + raw_spinlock_t id_lock; #endif unsigned int kvm_seq; } mm_context_t; @@ -16,7 +16,7 @@ typedef struct { /* init_mm.context.id_lock should be initialized. */ #define INIT_MM_CONTEXT(name) \ - .context.id_lock = __SPIN_LOCK_UNLOCKED(name.context.id_lock), + .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock), #else #define ASID(mm) (0) #endif diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 543b44916d2c..6c6809f982f1 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -31,11 +31,7 @@ struct mod_arch_specific { /* Add __virt_to_phys patching state as well */ #ifdef CONFIG_ARM_PATCH_PHYS_VIRT -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT -#define MODULE_ARCH_VERMAGIC_P2V "p2v16 " -#else #define MODULE_ARCH_VERMAGIC_P2V "p2v8 " -#endif #else #define MODULE_ARCH_VERMAGIC_P2V "" #endif diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index d8387437ec5a..53426c66352a 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -34,6 +34,7 @@ struct outer_cache_fns { void (*sync)(void); #endif void (*set_debug)(unsigned long); + void (*resume)(void); }; #ifdef CONFIG_OUTER_CACHE @@ -74,6 +75,12 @@ static inline void outer_disable(void) outer_cache.disable(); } +static inline void outer_resume(void) +{ + if (outer_cache.resume) + outer_cache.resume(); +} + #else static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index ac75d0848889..ca94653f1ecb 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -151,47 +151,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from, #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) extern void copy_page(void *to, const void *from); -typedef unsigned long pteval_t; - -#undef STRICT_MM_TYPECHECKS - -#ifdef STRICT_MM_TYPECHECKS -/* - * These are used to make use of C type-checking.. - */ -typedef struct { pteval_t pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pgd[2]; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd[0]) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else -/* - * .. while these make it easier on the compiler - */ -typedef pteval_t pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pgd_t[2]; -typedef unsigned long pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) ((x)[0]) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgprot(x) (x) - -#endif /* STRICT_MM_TYPECHECKS */ +#include <asm/pgtable-2level-types.h> #endif /* CONFIG_MMU */ diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h deleted file mode 100644 index b4e32d8ec072..000000000000 --- a/arch/arm/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ARM_PERCPU -#define __ARM_PERCPU - -#include <asm-generic/percpu.h> - -#endif diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 22de005f159c..3e08fd3fbb6b 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -105,9 +105,9 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte) } static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, - unsigned long prot) + pmdval_t prot) { - unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot; + pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; pmdp[0] = __pmd(pmdval); pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); flush_pmd_entry(pmdp); diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h new file mode 100644 index 000000000000..5cfba15cb401 --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h @@ -0,0 +1,93 @@ +/* + * arch/arm/include/asm/pgtable-2level-hwdef.h + * + * Copyright (C) 1995-2002 Russell King + * + * 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. + */ +#ifndef _ASM_PGTABLE_2LEVEL_HWDEF_H +#define _ASM_PGTABLE_2LEVEL_HWDEF_H + +/* + * Hardware page table definitions. + * + * + Level 1 descriptor (PMD) + * - common + */ +#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) +#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) +#define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) +#define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) +#define PMD_BIT4 (_AT(pmdval_t, 1) << 4) +#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) +#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ +/* + * - section + */ +#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) +#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) +#define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ +#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 1) << 10) +#define PMD_SECT_AP_READ (_AT(pmdval_t, 1) << 11) +#define PMD_SECT_TEX(x) (_AT(pmdval_t, (x)) << 12) /* v5 */ +#define PMD_SECT_APX (_AT(pmdval_t, 1) << 15) /* v6 */ +#define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */ +#define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */ +#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */ +#define PMD_SECT_AF (_AT(pmdval_t, 0)) + +#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0)) +#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) +#define PMD_SECT_WT (PMD_SECT_CACHEABLE) +#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) +#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) + +/* + * - coarse table (not used) + */ + +/* + * + Level 2 descriptor (PTE) + * - common + */ +#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) +#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) +#define PTE_TYPE_LARGE (_AT(pteval_t, 1) << 0) +#define PTE_TYPE_SMALL (_AT(pteval_t, 2) << 0) +#define PTE_TYPE_EXT (_AT(pteval_t, 3) << 0) /* v5 */ +#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) +#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) + +/* + * - extended small page/tiny page + */ +#define PTE_EXT_XN (_AT(pteval_t, 1) << 0) /* v6 */ +#define PTE_EXT_AP_MASK (_AT(pteval_t, 3) << 4) +#define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4) +#define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4) +#define PTE_EXT_AP_UNO_SRO (_AT(pteval_t, 0) << 4) +#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) +#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) +#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) +#define PTE_EXT_TEX(x) (_AT(pteval_t, (x)) << 6) /* v5 */ +#define PTE_EXT_APX (_AT(pteval_t, 1) << 9) /* v6 */ +#define PTE_EXT_COHERENT (_AT(pteval_t, 1) << 9) /* XScale3 */ +#define PTE_EXT_SHARED (_AT(pteval_t, 1) << 10) /* v6 */ +#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* v6 */ + +/* + * - small page + */ +#define PTE_SMALL_AP_MASK (_AT(pteval_t, 0xff) << 4) +#define PTE_SMALL_AP_UNO_SRO (_AT(pteval_t, 0x00) << 4) +#define PTE_SMALL_AP_UNO_SRW (_AT(pteval_t, 0x55) << 4) +#define PTE_SMALL_AP_URO_SRW (_AT(pteval_t, 0xaa) << 4) +#define PTE_SMALL_AP_URW_SRW (_AT(pteval_t, 0xff) << 4) + +#define PHYS_MASK (~0UL) + +#endif diff --git a/arch/arm/include/asm/pgtable-2level-types.h b/arch/arm/include/asm/pgtable-2level-types.h new file mode 100644 index 000000000000..66cb5b0e89c5 --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level-types.h @@ -0,0 +1,67 @@ +/* + * arch/arm/include/asm/pgtable-2level-types.h + * + * Copyright (C) 1995-2003 Russell King + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ASM_PGTABLE_2LEVEL_TYPES_H +#define _ASM_PGTABLE_2LEVEL_TYPES_H + +#include <asm/types.h> + +typedef u32 pteval_t; +typedef u32 pmdval_t; + +#undef STRICT_MM_TYPECHECKS + +#ifdef STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { pteval_t pte; } pte_t; +typedef struct { pmdval_t pmd; } pmd_t; +typedef struct { pmdval_t pgd[2]; } pgd_t; +typedef struct { pteval_t pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd[0]) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef pteval_t pte_t; +typedef pmdval_t pmd_t; +typedef pmdval_t pgd_t[2]; +typedef pteval_t pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) ((x)[0]) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgprot(x) (x) + +#endif /* STRICT_MM_TYPECHECKS */ + +#endif /* _ASM_PGTABLE_2LEVEL_TYPES_H */ diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h new file mode 100644 index 000000000000..470457e1cfc5 --- /dev/null +++ b/arch/arm/include/asm/pgtable-2level.h @@ -0,0 +1,143 @@ +/* + * arch/arm/include/asm/pgtable-2level.h + * + * Copyright (C) 1995-2002 Russell King + * + * 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. + */ +#ifndef _ASM_PGTABLE_2LEVEL_H +#define _ASM_PGTABLE_2LEVEL_H + +/* + * Hardware-wise, we have a two level page table structure, where the first + * level has 4096 entries, and the second level has 256 entries. Each entry + * is one 32-bit word. Most of the bits in the second level entry are used + * by hardware, and there aren't any "accessed" and "dirty" bits. + * + * Linux on the other hand has a three level page table structure, which can + * be wrapped to fit a two level page table structure easily - using the PGD + * and PTE only. However, Linux also expects one "PTE" table per page, and + * at least a "dirty" bit. + * + * Therefore, we tweak the implementation slightly - we tell Linux that we + * have 2048 entries in the first level, each of which is 8 bytes (iow, two + * hardware pointers to the second level.) The second level contains two + * hardware PTE tables arranged contiguously, preceded by Linux versions + * which contain the state information Linux needs. We, therefore, end up + * with 512 entries in the "PTE" level. + * + * This leads to the page tables having the following layout: + * + * pgd pte + * | | + * +--------+ + * | | +------------+ +0 + * +- - - - + | Linux pt 0 | + * | | +------------+ +1024 + * +--------+ +0 | Linux pt 1 | + * | |-----> +------------+ +2048 + * +- - - - + +4 | h/w pt 0 | + * | |-----> +------------+ +3072 + * +--------+ +8 | h/w pt 1 | + * | | +------------+ +4096 + * + * See L_PTE_xxx below for definitions of bits in the "Linux pt", and + * PTE_xxx for definitions of bits appearing in the "h/w pt". + * + * PMD_xxx definitions refer to bits in the first level page table. + * + * The "dirty" bit is emulated by only granting hardware write permission + * iff the page is marked "writable" and "dirty" in the Linux PTE. This + * means that a write to a clean page will cause a permission fault, and + * the Linux MM layer will mark the page dirty via handle_pte_fault(). + * For the hardware to notice the permission change, the TLB entry must + * be flushed, and ptep_set_access_flags() does that for us. + * + * The "accessed" or "young" bit is emulated by a similar method; we only + * allow accesses to the page if the "young" bit is set. Accesses to the + * page will cause a fault, and handle_pte_fault() will set the young bit + * for us as long as the page is marked present in the corresponding Linux + * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is + * up to date. + * + * However, when the "young" bit is cleared, we deny access to the page + * by clearing the hardware PTE. Currently Linux does not flush the TLB + * for us in this case, which means the TLB will retain the transation + * until either the TLB entry is evicted under pressure, or a context + * switch which changes the user space mapping occurs. + */ +#define PTRS_PER_PTE 512 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 2048 + +#define PTE_HWTABLE_PTRS (PTRS_PER_PTE) +#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) +#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) + +/* + * PMD_SHIFT determines the size of the area a second-level page table can map + * PGDIR_SHIFT determines what a third-level page table entry can map + */ +#define PMD_SHIFT 21 +#define PGDIR_SHIFT 21 + +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * section address mask and size definitions. + */ +#define SECTION_SHIFT 20 +#define SECTION_SIZE (1UL << SECTION_SHIFT) +#define SECTION_MASK (~(SECTION_SIZE-1)) + +/* + * ARMv6 supersection address mask and size definitions. + */ +#define SUPERSECTION_SHIFT 24 +#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT) +#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1)) + +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) + +/* + * "Linux" PTE definitions. + * + * We keep two sets of PTEs - the hardware and the linux version. + * This allows greater flexibility in the way we map the Linux bits + * onto the hardware tables, and allows us to have YOUNG and DIRTY + * bits. + * + * The PTE table pointer refers to the hardware entries; the "Linux" + * entries are stored 1024 bytes below. + */ +#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) +#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) +#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ +#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) +#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) +#define L_PTE_USER (_AT(pteval_t, 1) << 8) +#define L_PTE_XN (_AT(pteval_t, 1) << 9) +#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ + +/* + * These are the memory types, defined to be compatible with + * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB + */ +#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ +#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ +#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ +#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ +#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ +#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ +#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ +#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ +#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ +#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ +#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) + +#endif /* _ASM_PGTABLE_2LEVEL_H */ diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h index fd1521d5cb9d..183111164ce9 100644 --- a/arch/arm/include/asm/pgtable-hwdef.h +++ b/arch/arm/include/asm/pgtable-hwdef.h @@ -10,81 +10,6 @@ #ifndef _ASMARM_PGTABLE_HWDEF_H #define _ASMARM_PGTABLE_HWDEF_H -/* - * Hardware page table definitions. - * - * + Level 1 descriptor (PMD) - * - common - */ -#define PMD_TYPE_MASK (3 << 0) -#define PMD_TYPE_FAULT (0 << 0) -#define PMD_TYPE_TABLE (1 << 0) -#define PMD_TYPE_SECT (2 << 0) -#define PMD_BIT4 (1 << 4) -#define PMD_DOMAIN(x) ((x) << 5) -#define PMD_PROTECTION (1 << 9) /* v5 */ -/* - * - section - */ -#define PMD_SECT_BUFFERABLE (1 << 2) -#define PMD_SECT_CACHEABLE (1 << 3) -#define PMD_SECT_XN (1 << 4) /* v6 */ -#define PMD_SECT_AP_WRITE (1 << 10) -#define PMD_SECT_AP_READ (1 << 11) -#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ -#define PMD_SECT_APX (1 << 15) /* v6 */ -#define PMD_SECT_S (1 << 16) /* v6 */ -#define PMD_SECT_nG (1 << 17) /* v6 */ -#define PMD_SECT_SUPER (1 << 18) /* v6 */ - -#define PMD_SECT_UNCACHED (0) -#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) -#define PMD_SECT_WT (PMD_SECT_CACHEABLE) -#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) -#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) -#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) -#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) - -/* - * - coarse table (not used) - */ - -/* - * + Level 2 descriptor (PTE) - * - common - */ -#define PTE_TYPE_MASK (3 << 0) -#define PTE_TYPE_FAULT (0 << 0) -#define PTE_TYPE_LARGE (1 << 0) -#define PTE_TYPE_SMALL (2 << 0) -#define PTE_TYPE_EXT (3 << 0) /* v5 */ -#define PTE_BUFFERABLE (1 << 2) -#define PTE_CACHEABLE (1 << 3) - -/* - * - extended small page/tiny page - */ -#define PTE_EXT_XN (1 << 0) /* v6 */ -#define PTE_EXT_AP_MASK (3 << 4) -#define PTE_EXT_AP0 (1 << 4) -#define PTE_EXT_AP1 (2 << 4) -#define PTE_EXT_AP_UNO_SRO (0 << 4) -#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) -#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) -#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) -#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ -#define PTE_EXT_APX (1 << 9) /* v6 */ -#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */ -#define PTE_EXT_SHARED (1 << 10) /* v6 */ -#define PTE_EXT_NG (1 << 11) /* v6 */ - -/* - * - small page - */ -#define PTE_SMALL_AP_MASK (0xff << 4) -#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) -#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) -#define PTE_SMALL_AP_URO_SRW (0xaa << 4) -#define PTE_SMALL_AP_URW_SRW (0xff << 4) +#include <asm/pgtable-2level-hwdef.h> #endif diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 5750704e0271..8ade1840c6f2 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -24,6 +24,8 @@ #include <mach/vmalloc.h> #include <asm/pgtable-hwdef.h> +#include <asm/pgtable-2level.h> + /* * Just any arbitrary offset to the start of the vmalloc VM area: the * current 8MB value just means that there will be a 8MB "hole" after the @@ -41,79 +43,6 @@ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #endif -/* - * Hardware-wise, we have a two level page table structure, where the first - * level has 4096 entries, and the second level has 256 entries. Each entry - * is one 32-bit word. Most of the bits in the second level entry are used - * by hardware, and there aren't any "accessed" and "dirty" bits. - * - * Linux on the other hand has a three level page table structure, which can - * be wrapped to fit a two level page table structure easily - using the PGD - * and PTE only. However, Linux also expects one "PTE" table per page, and - * at least a "dirty" bit. - * - * Therefore, we tweak the implementation slightly - we tell Linux that we - * have 2048 entries in the first level, each of which is 8 bytes (iow, two - * hardware pointers to the second level.) The second level contains two - * hardware PTE tables arranged contiguously, preceded by Linux versions - * which contain the state information Linux needs. We, therefore, end up - * with 512 entries in the "PTE" level. - * - * This leads to the page tables having the following layout: - * - * pgd pte - * | | - * +--------+ - * | | +------------+ +0 - * +- - - - + | Linux pt 0 | - * | | +------------+ +1024 - * +--------+ +0 | Linux pt 1 | - * | |-----> +------------+ +2048 - * +- - - - + +4 | h/w pt 0 | - * | |-----> +------------+ +3072 - * +--------+ +8 | h/w pt 1 | - * | | +------------+ +4096 - * - * See L_PTE_xxx below for definitions of bits in the "Linux pt", and - * PTE_xxx for definitions of bits appearing in the "h/w pt". - * - * PMD_xxx definitions refer to bits in the first level page table. - * - * The "dirty" bit is emulated by only granting hardware write permission - * iff the page is marked "writable" and "dirty" in the Linux PTE. This - * means that a write to a clean page will cause a permission fault, and - * the Linux MM layer will mark the page dirty via handle_pte_fault(). - * For the hardware to notice the permission change, the TLB entry must - * be flushed, and ptep_set_access_flags() does that for us. - * - * The "accessed" or "young" bit is emulated by a similar method; we only - * allow accesses to the page if the "young" bit is set. Accesses to the - * page will cause a fault, and handle_pte_fault() will set the young bit - * for us as long as the page is marked present in the corresponding Linux - * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is - * up to date. - * - * However, when the "young" bit is cleared, we deny access to the page - * by clearing the hardware PTE. Currently Linux does not flush the TLB - * for us in this case, which means the TLB will retain the transation - * until either the TLB entry is evicted under pressure, or a context - * switch which changes the user space mapping occurs. - */ -#define PTRS_PER_PTE 512 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 2048 - -#define PTE_HWTABLE_PTRS (PTRS_PER_PTE) -#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) -#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) - -/* - * PMD_SHIFT determines the size of the area a second-level page table can map - * PGDIR_SHIFT determines what a third-level page table entry can map - */ -#define PMD_SHIFT 21 -#define PGDIR_SHIFT 21 - #define LIBRARY_TEXT_START 0x0c000000 #ifndef __ASSEMBLY__ @@ -124,12 +53,6 @@ extern void __pgd_error(const char *file, int line, pgd_t); #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte) #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) -#endif /* !__ASSEMBLY__ */ - -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) /* * This is the lowest virtual address we can permit any user space @@ -138,60 +61,6 @@ extern void __pgd_error(const char *file, int line, pgd_t); */ #define FIRST_USER_ADDRESS PAGE_SIZE -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) - -/* - * section address mask and size definitions. - */ -#define SECTION_SHIFT 20 -#define SECTION_SIZE (1UL << SECTION_SHIFT) -#define SECTION_MASK (~(SECTION_SIZE-1)) - -/* - * ARMv6 supersection address mask and size definitions. - */ -#define SUPERSECTION_SHIFT 24 -#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT) -#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1)) - -/* - * "Linux" PTE definitions. - * - * We keep two sets of PTEs - the hardware and the linux version. - * This allows greater flexibility in the way we map the Linux bits - * onto the hardware tables, and allows us to have YOUNG and DIRTY - * bits. - * - * The PTE table pointer refers to the hardware entries; the "Linux" - * entries are stored 1024 bytes below. - */ -#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) -#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) -#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ -#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) -#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) -#define L_PTE_USER (_AT(pteval_t, 1) << 8) -#define L_PTE_XN (_AT(pteval_t, 1) << 9) -#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ - -/* - * These are the memory types, defined to be compatible with - * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB - */ -#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ -#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ -#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ -#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ -#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ -#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ -#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ -#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ -#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ -#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ -#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) - -#ifndef __ASSEMBLY__ - /* * The pgprot_* and protection_map entries will be fixed up in runtime * to include the cachable and bufferable bits based on memory policy, @@ -327,10 +196,10 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; static inline pte_t *pmd_page_vaddr(pmd_t pmd) { - return __va(pmd_val(pmd) & PAGE_MASK); + return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); } -#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) +#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) /* we don't need complex calculations here as the pmd is folded into the pgd */ #define pmd_addr_end(addr,end) (end) @@ -351,7 +220,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_offset_map(pmd,addr) (__pte_map(pmd) + pte_index(addr)) #define pte_unmap(pte) __pte_unmap(pte) -#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) +#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) #define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot)) #define pte_page(pte) pfn_to_page(pte_pfn(pte)) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 67c70a31a1be..b7e82c4aced6 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -41,7 +41,7 @@ struct arm_pmu_platdata { * encoded error on failure. */ extern struct platform_device * -reserve_pmu(enum arm_pmu_type device); +reserve_pmu(enum arm_pmu_type type); /** * release_pmu() - Relinquish control of the performance counters @@ -62,26 +62,26 @@ release_pmu(enum arm_pmu_type type); * the actual hardware initialisation. */ extern int -init_pmu(enum arm_pmu_type device); +init_pmu(enum arm_pmu_type type); #else /* CONFIG_CPU_HAS_PMU */ #include <linux/err.h> static inline struct platform_device * -reserve_pmu(enum arm_pmu_type device) +reserve_pmu(enum arm_pmu_type type) { return ERR_PTR(-ENODEV); } static inline int -release_pmu(struct platform_device *pdev) +release_pmu(enum arm_pmu_type type) { return -ENODEV; } static inline int -init_pmu(enum arm_pmu_type device) +init_pmu(enum arm_pmu_type type) { return -ENODEV; } diff --git a/arch/arm/include/asm/poll.h b/arch/arm/include/asm/poll.h deleted file mode 100644 index c98509d3149e..000000000000 --- a/arch/arm/include/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/poll.h> diff --git a/arch/arm/include/asm/resource.h b/arch/arm/include/asm/resource.h deleted file mode 100644 index 734b581b5b6a..000000000000 --- a/arch/arm/include/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ARM_RESOURCE_H -#define _ARM_RESOURCE_H - -#include <asm-generic/resource.h> - -#endif diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h deleted file mode 100644 index 2b8c5160388f..000000000000 --- a/arch/arm/include/asm/sections.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/sections.h> diff --git a/arch/arm/include/asm/siginfo.h b/arch/arm/include/asm/siginfo.h deleted file mode 100644 index 5e21852e6039..000000000000 --- a/arch/arm/include/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASMARM_SIGINFO_H -#define _ASMARM_SIGINFO_H - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h deleted file mode 100644 index 154b89b81d3e..000000000000 --- a/arch/arm/include/asm/sizes.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 - */ -/* Size definitions - * Copyright (C) ARM Limited 1998. All rights reserved. - */ -#include <asm-generic/sizes.h> - -#define SZ_48M (SZ_32M + SZ_16M) diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index e42d96a45d3e..0a17b62538c2 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -33,6 +33,11 @@ extern void show_ipi_list(struct seq_file *, int); asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); /* + * Called from C code, this handles an IPI. + */ +void handle_IPI(int ipinr, struct pt_regs *regs); + +/* * Setup the set of possible CPUs (via set_cpu_possible) */ extern void smp_init_cpus(void); @@ -66,6 +71,12 @@ extern void platform_secondary_init(unsigned int cpu); extern void platform_smp_prepare_cpus(unsigned int); /* + * Logical CPU mapping. + */ +extern int __cpu_logical_map[NR_CPUS]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] + +/* * Initial data for bringing up a secondary CPU. */ struct secondary_data { diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 832888d0c20c..984014b92647 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -57,18 +57,12 @@ #ifndef __ASSEMBLY__ +#include <linux/compiler.h> #include <linux/linkage.h> #include <linux/irqflags.h> #include <asm/outercache.h> -#define __exception __attribute__((section(".exception.text"))) -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -#define __exception_irq_entry __irq_entry -#else -#define __exception_irq_entry __exception -#endif - struct thread_info; struct task_struct; @@ -97,14 +91,13 @@ void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) -extern asmlinkage void __backtrace(void); extern asmlinkage void c_backtrace(unsigned long fp, int pmode); struct mm_struct; extern void show_pte(struct mm_struct *mm, unsigned long addr); extern void __show_regs(struct pt_regs *); -extern int cpu_architecture(void); +extern int __pure cpu_architecture(void); extern void cpu_init(void); void arm_machine_restart(char mode, const char *cmd); diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index 8077145698ff..02b2f8203982 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -471,7 +471,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) * these operations. This is typically used when we are removing * PMD entries. */ -static inline void flush_pmd_entry(pmd_t *pmd) +static inline void flush_pmd_entry(void *pmd) { const unsigned int __tlb_flag = __cpu_tlb_flags; @@ -487,7 +487,7 @@ static inline void flush_pmd_entry(pmd_t *pmd) dsb(); } -static inline void clean_pmd_entry(pmd_t *pmd) +static inline void clean_pmd_entry(void *pmd) { const unsigned int __tlb_flag = __cpu_tlb_flags; diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index accbd7cad9b5..a7e457ed27c3 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -1,6 +1,39 @@ #ifndef _ASM_ARM_TOPOLOGY_H #define _ASM_ARM_TOPOLOGY_H +#ifdef CONFIG_ARM_CPU_TOPOLOGY + +#include <linux/cpumask.h> + +struct cputopo_arm { + int thread_id; + int core_id; + int socket_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; +}; + +extern struct cputopo_arm cpu_topology[NR_CPUS]; + +#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) +#define topology_core_id(cpu) (cpu_topology[cpu].core_id) +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) +#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) + +#define mc_capable() (cpu_topology[0].socket_id != -1) +#define smt_capable() (cpu_topology[0].thread_id != -1) + +void init_cpu_topology(void); +void store_cpu_topology(unsigned int cpuid); +const struct cpumask *cpu_coregroup_mask(unsigned int cpu); + +#else + +static inline void init_cpu_topology(void) { } +static inline void store_cpu_topology(unsigned int cpuid) { } + +#endif + #include <asm-generic/topology.h> #endif /* _ASM_ARM_TOPOLOGY_H */ diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 2c04ed5efeb5..c60a2944f95b 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -478,8 +478,8 @@ /* * Unimplemented (or alternatively implemented) syscalls */ -#define __IGNORE_fadvise64_64 1 -#define __IGNORE_migrate_pages 1 +#define __IGNORE_fadvise64_64 +#define __IGNORE_migrate_pages #endif /* __KERNEL__ */ #endif /* __ASM_ARM_UNISTD_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f7887dc53c1f..68036eece340 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o -obj-$(CONFIG_PM_SLEEP) += sleep.o +obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o @@ -66,6 +66,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o obj-$(CONFIG_CPU_HAS_PMU) += pmu.o obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt +obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o ifneq ($(CONFIG_ARCH_EBSA110),y) obj-y += io.o diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index aeef960ff795..8e3c6f11b0a1 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); - -EXPORT_SYMBOL(__backtrace); - /* platform dependent support */ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__const_udelay); diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 16baba2e4369..1429d8989fb9 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -20,6 +20,7 @@ #include <asm/thread_info.h> #include <asm/memory.h> #include <asm/procinfo.h> +#include <asm/hardware/cache-l2x0.h> #include <linux/kbuild.h> /* @@ -92,6 +93,17 @@ int main(void) DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); BLANK(); +#ifdef CONFIG_CACHE_L2X0 + DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); + DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); + DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency)); + DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency)); + DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start)); + DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end)); + DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl)); + DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl)); + BLANK(); +#endif #ifdef CONFIG_CPU_HAS_ASID DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); BLANK(); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index d6df359408f0..c0d9203fc75e 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *bus) printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_fixup_bus); +#endif /* * Convert from Linux-centric to bus-centric addresses for bridge devices. @@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->start = res->start - offset; region->end = res->end - offset; } +EXPORT_SYMBOL(pcibios_resource_to_bus); void __devinit pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, @@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, res->start = region->start + offset; res->end = region->end + offset; } - -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pcibios_fixup_bus); -EXPORT_SYMBOL(pcibios_resource_to_bus); EXPORT_SYMBOL(pcibios_bus_to_resource); -#endif /* * Swizzle the device pin each time we cross a bridge. diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 80f7896cc016..9943e9e74a1b 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -178,7 +178,7 @@ CALL(sys_ni_syscall) /* vm86 */ CALL(sys_ni_syscall) /* was sys_query_module */ CALL(sys_poll) - CALL(sys_nfsservctl) + CALL(sys_ni_syscall) /* was nfsservctl */ /* 170 */ CALL(sys_setresgid16) CALL(sys_getresgid16) CALL(sys_prctl) diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index bcd66e00bdbe..0f852d082fcf 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -151,6 +151,8 @@ printhex: adr r2, hexbuf b printascii ENDPROC(printhex2) +hexbuf: .space 16 + .ltorg ENTRY(printascii) @@ -175,5 +177,3 @@ ENTRY(printch) mov r0, #0 b 1b ENDPROC(printch) - -hexbuf: .space 16 diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 2c4a185f92cd..7b829d9663b1 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -23,7 +23,7 @@ #include <asm/mach/dma.h> -DEFINE_SPINLOCK(dma_spin_lock); +DEFINE_RAW_SPINLOCK(dma_spin_lock); EXPORT_SYMBOL(dma_spin_lock); static dma_t *dma_chan[MAX_DMA_CHANNELS]; diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index d16500110ee9..4dd0edab6a65 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); - src_pgd = pgd_offset(mm, EASI_BASE); + src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE); dst_pgd = pgd_offset(mm, EASI_START); memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); @@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void) #define ecard_probeirqhw() (0) #endif -#ifndef IO_EC_MEMC8_BASE -#define IO_EC_MEMC8_BASE 0 -#endif - -static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) +static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) { - unsigned long address = 0; + void __iomem *address = NULL; int slot = ec->slot_no; if (ec->slot_no == 8) - return IO_EC_MEMC8_BASE; + return ECARD_MEMC8_BASE; ectcr &= ~(1 << slot); switch (type) { case ECARD_MEMC: if (slot < 4) - address = IO_EC_MEMC_BASE + (slot << 12); + address = ECARD_MEMC_BASE + (slot << 14); break; case ECARD_IOC: if (slot < 4) - address = IO_EC_IOC_BASE + (slot << 12); -#ifdef IO_EC_IOC4_BASE + address = ECARD_IOC_BASE + (slot << 14); else - address = IO_EC_IOC4_BASE + ((slot - 4) << 12); -#endif + address = ECARD_IOC4_BASE + ((slot - 4) << 14); if (address) - address += speed << 17; + address += speed << 19; break; -#ifdef IO_EC_EASI_BASE case ECARD_EASI: - address = IO_EC_EASI_BASE + (slot << 22); + address = ECARD_EASI_BASE + (slot << 24); if (speed == ECARD_FAST) ectcr |= 1 << slot; break; -#endif + default: break; } @@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type) ecard_t **ecp; ecard_t *ec; struct ex_ecid cid; + void __iomem *addr; int i, rc; ec = ecard_alloc_card(type, slot); @@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type) } rc = -ENODEV; - if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0) + if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL) goto nodev; cid.r_zero = 1; @@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type) ec->cid.fiqmask = cid.r_fiqmask; ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); ec->fiqaddr = - ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr); + ec->irqaddr = addr; if (ec->cid.is) { ec->irqmask = ec->cid.irqmask; @@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type) set_irq_flags(ec->irq, IRQF_VALID); } -#ifdef IO_EC_MEMC8_BASE if (slot == 8) ec->irq = 11; -#endif #ifdef CONFIG_ARCH_RPC /* On RiscPC, only first two slots have DMA capability */ if (slot < 2) @@ -1097,9 +1089,7 @@ static int __init ecard_init(void) ecard_probe(slot, ECARD_IOC); } -#ifdef IO_EC_MEMC8_BASE ecard_probe(8, ECARD_IOC); -#endif irqhw = ecard_probeirqhw(); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a87cbf889ff4..9ad50c4208ae 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -24,6 +24,7 @@ #include <asm/unwind.h> #include <asm/unistd.h> #include <asm/tls.h> +#include <asm/system.h> #include "entry-header.S" #include <asm/entry-macro-multi.S> @@ -262,8 +263,7 @@ __und_svc: ldr r0, [r4, #-4] #else ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 - and r9, r0, #0xf800 - cmp r9, #0xe800 @ 32-bit instruction if xx >= 0 + cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 ldrhhs r9, [r4] @ bottom 16 bits orrhs r0, r9, r0, lsl #16 #endif @@ -440,18 +440,46 @@ __und_usr: #endif beq call_fpe @ Thumb instruction -#if __LINUX_ARM_ARCH__ >= 7 +#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 +/* + * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms + * can never be supported in a single kernel, this code is not applicable at + * all when __LINUX_ARM_ARCH__ < 6. This allows simplifying assumptions to be + * made about .arch directives. + */ +#if __LINUX_ARM_ARCH__ < 7 +/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */ +#define NEED_CPU_ARCHITECTURE + ldr r5, .LCcpu_architecture + ldr r5, [r5] + cmp r5, #CPU_ARCH_ARMv7 + blo __und_usr_unknown +/* + * The following code won't get run unless the running CPU really is v7, so + * coding round the lack of ldrht on older arches is pointless. Temporarily + * override the assembler target arch with the minimum required instead: + */ + .arch armv6t2 +#endif 2: ARM( ldrht r5, [r4], #2 ) THUMB( ldrht r5, [r4] ) THUMB( add r4, r4, #2 ) - and r0, r5, #0xf800 @ mask bits 111x x... .... .... - cmp r0, #0xe800 @ 32bit instruction if xx != 0 + cmp r5, #0xe800 @ 32bit instruction if xx != 0 blo __und_usr_unknown 3: ldrht r0, [r4] add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 orr r0, r0, r5, lsl #16 + +#if __LINUX_ARM_ARCH__ < 7 +/* If the target arch was overridden, change it back: */ +#ifdef CONFIG_CPU_32v6K + .arch armv6k #else + .arch armv6 +#endif +#endif /* __LINUX_ARM_ARCH__ < 7 */ +#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ b __und_usr_unknown #endif UNWIND(.fnend ) @@ -578,6 +606,12 @@ call_fpe: movw_pc lr @ CP#14 (Debug) movw_pc lr @ CP#15 (Control) +#ifdef NEED_CPU_ARCHITECTURE + .align 2 +.LCcpu_architecture: + .word __cpu_architecture +#endif + #ifdef CONFIG_NEON .align 6 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 742b6108a001..239703dbdf4f 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -21,6 +21,7 @@ #include <asm/memory.h> #include <asm/thread_info.h> #include <asm/system.h> +#include <asm/pgtable.h> #ifdef CONFIG_DEBUG_LL #include <mach/debug-macro.S> @@ -38,11 +39,14 @@ #error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif +#define PG_DIR_SIZE 0x4000 +#define PMD_ORDER 2 + .globl swapper_pg_dir - .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 + .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE .macro pgtbl, rd, phys - add \rd, \phys, #TEXT_OFFSET - 0x4000 + add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE .endm #ifdef CONFIG_XIP_KERNEL @@ -148,11 +152,11 @@ __create_page_tables: pgtbl r4, r8 @ page table address /* - * Clear the 16K level 1 swapper page table + * Clear the swapper page table */ mov r0, r4 mov r3, #0 - add r6, r0, #0x4000 + add r6, r0, #PG_DIR_SIZE 1: str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 @@ -171,30 +175,30 @@ __create_page_tables: sub r0, r0, r3 @ virt->phys offset add r5, r5, r0 @ phys __enable_mmu add r6, r6, r0 @ phys __enable_mmu_end - mov r5, r5, lsr #20 - mov r6, r6, lsr #20 + mov r5, r5, lsr #SECTION_SHIFT + mov r6, r6, lsr #SECTION_SHIFT -1: orr r3, r7, r5, lsl #20 @ flags + kernel base - str r3, [r4, r5, lsl #2] @ identity mapping - teq r5, r6 - addne r5, r5, #1 @ next section - bne 1b +1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base + str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping + cmp r5, r6 + addlo r5, r5, #1 @ next section + blo 1b /* * Now setup the pagetables for our kernel direct * mapped region. */ mov r3, pc - mov r3, r3, lsr #20 - orr r3, r7, r3, lsl #20 - add r0, r4, #(KERNEL_START & 0xff000000) >> 18 - str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! + mov r3, r3, lsr #SECTION_SHIFT + orr r3, r7, r3, lsl #SECTION_SHIFT + add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! ldr r6, =(KERNEL_END - 1) - add r0, r0, #4 - add r6, r4, r6, lsr #18 + add r0, r0, #1 << PMD_ORDER + add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 - add r3, r3, #1 << 20 - strls r3, [r0], #4 + add r3, r3, #1 << SECTION_SHIFT + strls r3, [r0], #1 << PMD_ORDER bls 1b #ifdef CONFIG_XIP_KERNEL @@ -203,11 +207,11 @@ __create_page_tables: */ add r3, r8, #TEXT_OFFSET orr r3, r3, r7 - add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 - str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! + add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! ldr r6, =(_end - 1) add r0, r0, #4 - add r6, r4, r6, lsr #18 + add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 add r3, r3, #1 << 20 strls r3, [r0], #4 @@ -218,12 +222,12 @@ __create_page_tables: * Then map boot params address in r2 or * the first 1MB of ram if boot params address is not specified. */ - mov r0, r2, lsr #20 - movs r0, r0, lsl #20 + mov r0, r2, lsr #SECTION_SHIFT + movs r0, r0, lsl #SECTION_SHIFT moveq r0, r8 sub r3, r0, r8 add r3, r3, #PAGE_OFFSET - add r3, r4, r3, lsr #18 + add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) orr r6, r7, r0 str r6, [r3] @@ -236,21 +240,21 @@ __create_page_tables: */ addruart r7, r3 - mov r3, r3, lsr #20 - mov r3, r3, lsl #2 + mov r3, r3, lsr #SECTION_SHIFT + mov r3, r3, lsl #PMD_ORDER add r0, r4, r3 rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) cmp r3, #0x0800 @ limit to 512MB movhi r3, #0x0800 add r6, r0, r3 - mov r3, r7, lsr #20 + mov r3, r7, lsr #SECTION_SHIFT ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags - orr r3, r7, r3, lsl #20 + orr r3, r7, r3, lsl #SECTION_SHIFT 1: str r3, [r0], #4 - add r3, r3, #1 << 20 - teq r0, r6 - bne 1b + add r3, r3, #1 << SECTION_SHIFT + cmp r0, r6 + blo 1b #else /* CONFIG_DEBUG_ICEDCC */ /* we don't need any serial debugging mappings for ICEDCC */ @@ -262,7 +266,7 @@ __create_page_tables: * If we're using the NetWinder or CATS, we also need to map * in the 16550-type serial port for the debug messages */ - add r0, r4, #0xff000000 >> 18 + add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x7c000000 str r3, [r0] #endif @@ -272,10 +276,10 @@ __create_page_tables: * Similar reasons here - for debug. This is * only for Acorn RiscPC architectures. */ - add r0, r4, #0x02000000 >> 18 + add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x02000000 str r3, [r0] - add r0, r4, #0xd8000000 >> 18 + add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) str r3, [r0] #endif #endif @@ -488,13 +492,8 @@ __fixup_pv_table: add r5, r5, r3 @ adjust table end address add r7, r7, r3 @ adjust __pv_phys_offset address str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset -#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT mov r6, r3, lsr #24 @ constant for add/sub instructions teq r3, r6, lsl #24 @ must be 16MiB aligned -#else - mov r6, r3, lsr #16 @ constant for add/sub instructions - teq r3, r6, lsl #16 @ must be 64kiB aligned -#endif THUMB( it ne @ cross section branch ) bne __error str r6, [r7, #4] @ save to __pv_offset @@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table) .text __fixup_a_pv_table: #ifdef CONFIG_THUMB2_KERNEL -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - lsls r0, r6, #24 - lsr r6, #8 - beq 1f - clz r7, r0 - lsr r0, #24 - lsl r0, r7 - bic r0, 0x0080 - lsrs r7, #1 - orrcs r0, #0x0080 - orr r0, r0, r7, lsl #12 -#endif -1: lsls r6, #24 - beq 4f + lsls r6, #24 + beq 2f clz r7, r6 lsr r6, #24 lsl r6, r7 @@ -532,43 +519,25 @@ __fixup_a_pv_table: orrcs r6, #0x0080 orr r6, r6, r7, lsl #12 orr r6, #0x4000 - b 4f -2: @ at this point the C flag is always clear - add r7, r3 -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - ldrh ip, [r7] - tst ip, 0x0400 @ the i bit tells us LS or MS byte - beq 3f - cmp r0, #0 @ set C flag, and ... - biceq ip, 0x0400 @ immediate zero value has a special encoding - streqh ip, [r7] @ that requires the i bit cleared -#endif -3: ldrh ip, [r7, #2] + b 2f +1: add r7, r3 + ldrh ip, [r7, #2] and ip, 0x8f00 - orrcc ip, r6 @ mask in offset bits 31-24 - orrcs ip, r0 @ mask in offset bits 23-16 + orr ip, r6 @ mask in offset bits 31-24 strh ip, [r7, #2] -4: cmp r4, r5 +2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 2b + bcc 1b bx lr #else -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT - and r0, r6, #255 @ offset bits 23-16 - mov r6, r6, lsr #8 @ offset bits 31-24 -#else - mov r0, #0 @ just in case... -#endif - b 3f -2: ldr ip, [r7, r3] + b 2f +1: ldr ip, [r7, r3] bic ip, ip, #0x000000ff - tst ip, #0x400 @ rotate shift tells us LS or MS byte - orrne ip, ip, r6 @ mask in offset bits 31-24 - orreq ip, ip, r0 @ mask in offset bits 23-16 + orr ip, ip, r6 @ mask in offset bits 31-24 str ip, [r7, r3] -3: cmp r4, r5 +2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 2b + bcc 1b mov pc, lr #endif ENDPROC(__fixup_a_pv_table) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index de3dcab8610b..53919b230e8b 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -35,8 +35,8 @@ #include <linux/list.h> #include <linux/kallsyms.h> #include <linux/proc_fs.h> -#include <linux/ftrace.h> +#include <asm/exception.h> #include <asm/system.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e59bbd496c39..c1b4463dcc83 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -32,6 +32,24 @@ static atomic_t waiting_for_crash_ipi; int machine_kexec_prepare(struct kimage *image) { + unsigned long page_list; + void *reboot_code_buffer; + page_list = image->head & PAGE_MASK; + + reboot_code_buffer = page_address(image->control_code_page); + + /* Prepare parameters for reboot_code_buffer*/ + kexec_start_address = image->start; + kexec_indirection_page = page_list; + kexec_mach_type = machine_arch_type; + kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + + /* copy our kernel relocation code to the control code page */ + memcpy(reboot_code_buffer, + relocate_new_kernel, relocate_new_kernel_size); + + flush_icache_range((unsigned long) reboot_code_buffer, + (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); return 0; } @@ -82,31 +100,14 @@ void (*kexec_reinit)(void); void machine_kexec(struct kimage *image) { - unsigned long page_list; unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; - - page_list = image->head & PAGE_MASK; - /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); - /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; - - /* copy our kernel relocation code to the control code page */ - memcpy(reboot_code_buffer, - relocate_new_kernel, relocate_new_kernel_size); - - - flush_icache_range((unsigned long) reboot_code_buffer, - (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index cc2020c2c709..1e9be5d25e56 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -33,7 +33,7 @@ * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. */ #undef MODULES_VADDR -#define MODULES_VADDR (((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK) +#define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) #endif #ifdef CONFIG_MMU diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4c851834f68e..6be3e2e4d838 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -321,8 +321,8 @@ static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_COHERENT_LINE_HIT, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_COHERENT_LINE_MISS, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_DCACHE_ACCESS, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_DCACHE_REFILL, [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES, diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2b70709376c3..c53474fe84df 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -31,7 +31,7 @@ static int __devinit pmu_register(struct platform_device *pdev, { if (type < 0 || type >= ARM_NUM_PMU_DEVICES) { pr_warning("received registration request for unknown " - "device %d\n", type); + "PMU device type %d\n", type); return -EINVAL; } @@ -112,17 +112,17 @@ static int __init register_pmu_driver(void) device_initcall(register_pmu_driver); struct platform_device * -reserve_pmu(enum arm_pmu_type device) +reserve_pmu(enum arm_pmu_type type) { struct platform_device *pdev; - if (test_and_set_bit_lock(device, &pmu_lock)) { + if (test_and_set_bit_lock(type, &pmu_lock)) { pdev = ERR_PTR(-EBUSY); - } else if (pmu_devices[device] == NULL) { - clear_bit_unlock(device, &pmu_lock); + } else if (pmu_devices[type] == NULL) { + clear_bit_unlock(type, &pmu_lock); pdev = ERR_PTR(-ENODEV); } else { - pdev = pmu_devices[device]; + pdev = pmu_devices[type]; } return pdev; @@ -130,11 +130,11 @@ reserve_pmu(enum arm_pmu_type device) EXPORT_SYMBOL_GPL(reserve_pmu); int -release_pmu(enum arm_pmu_type device) +release_pmu(enum arm_pmu_type type) { - if (WARN_ON(!pmu_devices[device])) + if (WARN_ON(!pmu_devices[type])) return -EINVAL; - clear_bit_unlock(device, &pmu_lock); + clear_bit_unlock(type, &pmu_lock); return 0; } EXPORT_SYMBOL_GPL(release_pmu); @@ -182,17 +182,17 @@ init_cpu_pmu(void) } int -init_pmu(enum arm_pmu_type device) +init_pmu(enum arm_pmu_type type) { int err = 0; - switch (device) { + switch (type) { case ARM_PMU_DEVICE_CPU: err = init_cpu_pmu(); break; default: - pr_warning("attempt to initialise unknown device %d\n", - device); + pr_warning("attempt to initialise PMU of unknown " + "type %d\n", type); err = -EINVAL; } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1a347f481e5e..fd0814076ff6 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -319,7 +319,7 @@ void show_regs(struct pt_regs * regs) printk("\n"); printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); __show_regs(regs); - __backtrace(); + dump_stack(); } ATOMIC_NOTIFIER_HEAD(thread_notify_head); diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 9cf4cbf8f95b..d0cdedf4864d 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -57,7 +57,8 @@ relocate_new_kernel: mov r0,#0 ldr r1,kexec_mach_type ldr r2,kexec_boot_atags - mov pc,lr + ARM( mov pc, lr ) + THUMB( bx lr ) .align diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 70bca649e925..3fe93f75b55a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -29,6 +29,8 @@ #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/memblock.h> +#include <linux/bug.h> +#include <linux/compiler.h> #include <asm/unified.h> #include <asm/cpu.h> @@ -42,6 +44,7 @@ #include <asm/cacheflush.h> #include <asm/cachetype.h> #include <asm/tlbflush.h> +#include <asm/system.h> #include <asm/prom.h> #include <asm/mach/arch.h> @@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __read_mostly; EXPORT_SYMBOL(outer_cache); #endif +/* + * Cached cpu_architecture() result for use by assembler code. + * C code should use the cpu_architecture() function instead of accessing this + * variable directly. + */ +int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN; + struct stack { u32 irq[3]; u32 abt[3]; @@ -210,7 +220,7 @@ static const char *proc_arch[] = { "?(17)", }; -int cpu_architecture(void) +static int __get_cpu_architecture(void) { int cpu_arch; @@ -243,11 +253,22 @@ int cpu_architecture(void) return cpu_arch; } +int __pure cpu_architecture(void) +{ + BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); + + return __cpu_architecture; +} + static int cpu_has_aliasing_icache(unsigned int arch) { int aliasing_icache; unsigned int id_reg, num_sets, line_size; + /* PIPT caches never alias. */ + if (icache_is_pipt()) + return 0; + /* arch specifies the register format */ switch (arch) { case CPU_ARCH_ARMv7: @@ -280,18 +301,25 @@ static void __init cacheid_init(void) if (arch >= CPU_ARCH_ARMv6) { if ((cachetype & (7 << 29)) == 4 << 29) { /* ARMv7 register format */ + arch = CPU_ARCH_ARMv7; cacheid = CACHEID_VIPT_NONALIASING; - if ((cachetype & (3 << 14)) == 1 << 14) + switch (cachetype & (3 << 14)) { + case (1 << 14): cacheid |= CACHEID_ASID_TAGGED; - else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7)) - cacheid |= CACHEID_VIPT_I_ALIASING; - } else if (cachetype & (1 << 23)) { - cacheid = CACHEID_VIPT_ALIASING; + break; + case (3 << 14): + cacheid |= CACHEID_PIPT; + break; + } } else { - cacheid = CACHEID_VIPT_NONALIASING; - if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6)) - cacheid |= CACHEID_VIPT_I_ALIASING; + arch = CPU_ARCH_ARMv6; + if (cachetype & (1 << 23)) + cacheid = CACHEID_VIPT_ALIASING; + else + cacheid = CACHEID_VIPT_NONALIASING; } + if (cpu_has_aliasing_icache(arch)) + cacheid |= CACHEID_VIPT_I_ALIASING; } else { cacheid = CACHEID_VIVT; } @@ -299,10 +327,11 @@ static void __init cacheid_init(void) printk("CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : - cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", + cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown", cache_is_vivt() ? "VIVT" : icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : icache_is_vipt_aliasing() ? "VIPT aliasing" : + icache_is_pipt() ? "PIPT" : cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); } @@ -413,6 +442,7 @@ static void __init setup_processor(void) } cpu_name = list->cpu_name; + __cpu_architecture = __get_cpu_architecture(); #ifdef MULTI_CPU processor = *list->proc; @@ -860,7 +890,7 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr) } if (mdesc->fixup) - mdesc->fixup(mdesc, tags, &from, &meminfo); + mdesc->fixup(tags, &from, &meminfo); if (tags->hdr.tag == ATAG_CORE) { if (meminfo.nr_banks != 0) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e82..94f34a6c8610 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -16,7 +16,6 @@ #include <linux/cache.h> #include <linux/profile.h> #include <linux/errno.h> -#include <linux/ftrace.h> #include <linux/mm.h> #include <linux/err.h> #include <linux/cpu.h> @@ -31,6 +30,8 @@ #include <asm/cacheflush.h> #include <asm/cpu.h> #include <asm/cputype.h> +#include <asm/exception.h> +#include <asm/topology.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> @@ -39,6 +40,7 @@ #include <asm/tlbflush.h> #include <asm/ptrace.h> #include <asm/localtimer.h> +#include <asm/smp_plat.h> /* * as from 2.5, kernels no longer have an init_tasks structure @@ -259,6 +261,20 @@ void __ref cpu_die(void) } #endif /* CONFIG_HOTPLUG_CPU */ +int __cpu_logical_map[NR_CPUS]; + +void __init smp_setup_processor_id(void) +{ + int i; + u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; + + cpu_logical_map(0) = cpu; + for (i = 1; i < NR_CPUS; ++i) + cpu_logical_map(i) = i == cpu ? 0 : i; + + printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); +} + /* * Called by both boot and secondaries to move global data into * per-processor storage. @@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); cpu_info->loops_per_jiffy = loops_per_jiffy; + + store_cpu_topology(cpuid); } /* @@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) */ platform_secondary_init(cpu); - /* - * Enable local interrupts. - */ notify_cpu_starting(cpu); - local_irq_enable(); - local_fiq_enable(); - - /* - * Setup the percpu timer for this CPU. - */ - percpu_timer_setup(); calibrate_delay(); @@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * before we continue. */ set_cpu_online(cpu, true); + + /* + * Setup the percpu timer for this CPU. + */ + percpu_timer_setup(); + while (!cpu_active(cpu)) cpu_relax(); /* + * cpu_active bit is set, so it's safe to enalbe interrupts + * now. + */ + local_irq_enable(); + local_fiq_enable(); + + /* * OK, it's off to the idle thread for us */ cpu_idle(); @@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = num_possible_cpus(); + init_cpu_topology(); + smp_store_cpu_info(smp_processor_id()); /* @@ -460,6 +483,11 @@ static void ipi_timer(void) #ifdef CONFIG_LOCAL_TIMERS asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) { + handle_local_timer(regs); +} + +void handle_local_timer(struct pt_regs *regs) +{ struct pt_regs *old_regs = set_irq_regs(regs); int cpu = smp_processor_id(); @@ -538,7 +566,7 @@ static void percpu_timer_stop(void) } #endif -static DEFINE_SPINLOCK(stop_lock); +static DEFINE_RAW_SPINLOCK(stop_lock); /* * ipi_cpu_stop - handle IPI from smp_send_stop() @@ -547,10 +575,10 @@ static void ipi_cpu_stop(unsigned int cpu) { if (system_state == SYSTEM_BOOTING || system_state == SYSTEM_RUNNING) { - spin_lock(&stop_lock); + raw_spin_lock(&stop_lock); printk(KERN_CRIT "CPU%u: stopping\n", cpu); dump_stack(); - spin_unlock(&stop_lock); + raw_spin_unlock(&stop_lock); } set_cpu_online(cpu, false); @@ -567,6 +595,11 @@ static void ipi_cpu_stop(unsigned int cpu) */ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) { + handle_IPI(ipinr, regs); +} + +void handle_IPI(int ipinr, struct pt_regs *regs) +{ unsigned int cpu = smp_processor_id(); struct pt_regs *old_regs = set_irq_regs(regs); diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 79ed5e7f204a..8f5dd7963356 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -13,6 +13,7 @@ #include <asm/smp_scu.h> #include <asm/cacheflush.h> +#include <asm/cputype.h> #define SCU_CTRL 0x00 #define SCU_CONFIG 0x04 @@ -33,10 +34,19 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base) /* * Enable the SCU */ -void __init scu_enable(void __iomem *scu_base) +void scu_enable(void __iomem *scu_base) { u32 scu_ctrl; +#ifdef CONFIG_ARM_ERRATA_764369 + /* Cortex-A9 only */ + if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { + scu_ctrl = __raw_readl(scu_base + 0x30); + if (!(scu_ctrl & 1)) + __raw_writel(scu_ctrl | 0x1, scu_base + 0x30); + } +#endif + scu_ctrl = __raw_readl(scu_base + SCU_CTRL); /* already enabled? */ if (scu_ctrl & 1) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 2c277d40cee6..01c186222f3b 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -137,8 +137,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); clk->min_delta_ns = clockevent_delta2ns(0xf, clk); + clockevents_register_device(clk); + /* Make sure our local interrupt controller has this enabled */ gic_enable_ppi(clk->irq); - - clockevents_register_device(clk); } diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index cb634c3e28e9..5a54b95d6bd2 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -39,13 +39,11 @@ */ static struct sys_timer *system_timer; -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ + defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) /* this needs a better home */ DEFINE_SPINLOCK(rtc_lock); - -#ifdef CONFIG_RTC_DRV_CMOS_MODULE EXPORT_SYMBOL(rtc_lock); -#endif #endif /* pc-style 'CMOS' RTC support */ /* change this if you have some constant time drift */ diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c new file mode 100644 index 000000000000..1040c00405d0 --- /dev/null +++ b/arch/arm/kernel/topology.c @@ -0,0 +1,148 @@ +/* + * arch/arm/kernel/topology.c + * + * Copyright (C) 2011 Linaro Limited. + * Written by: Vincent Guittot + * + * based on arch/sh/kernel/topology.c + * + * 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/cpu.h> +#include <linux/cpumask.h> +#include <linux/init.h> +#include <linux/percpu.h> +#include <linux/node.h> +#include <linux/nodemask.h> +#include <linux/sched.h> + +#include <asm/cputype.h> +#include <asm/topology.h> + +#define MPIDR_SMP_BITMASK (0x3 << 30) +#define MPIDR_SMP_VALUE (0x2 << 30) + +#define MPIDR_MT_BITMASK (0x1 << 24) + +/* + * These masks reflect the current use of the affinity levels. + * The affinity level can be up to 16 bits according to ARM ARM + */ + +#define MPIDR_LEVEL0_MASK 0x3 +#define MPIDR_LEVEL0_SHIFT 0 + +#define MPIDR_LEVEL1_MASK 0xF +#define MPIDR_LEVEL1_SHIFT 8 + +#define MPIDR_LEVEL2_MASK 0xFF +#define MPIDR_LEVEL2_SHIFT 16 + +struct cputopo_arm cpu_topology[NR_CPUS]; + +const struct cpumask *cpu_coregroup_mask(unsigned int cpu) +{ + return &cpu_topology[cpu].core_sibling; +} + +/* + * store_cpu_topology is called at boot when only one cpu is running + * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, + * which prevents simultaneous write access to cpu_topology array + */ +void store_cpu_topology(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int mpidr; + unsigned int cpu; + + /* If the cpu topology has been already set, just return */ + if (cpuid_topo->core_id != -1) + return; + + mpidr = read_cpuid_mpidr(); + + /* create cpu topology mapping */ + if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { + /* + * This is a multiprocessor system + * multiprocessor format & multiprocessor mode field are set + */ + + if (mpidr & MPIDR_MT_BITMASK) { + /* core performance interdependency */ + cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) + & MPIDR_LEVEL0_MASK; + cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) + & MPIDR_LEVEL1_MASK; + cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) + & MPIDR_LEVEL2_MASK; + } else { + /* largely independent cores */ + cpuid_topo->thread_id = -1; + cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) + & MPIDR_LEVEL0_MASK; + cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) + & MPIDR_LEVEL1_MASK; + } + } else { + /* + * This is an uniprocessor system + * we are in multiprocessor format but uniprocessor system + * or in the old uniprocessor format + */ + cpuid_topo->thread_id = -1; + cpuid_topo->core_id = 0; + cpuid_topo->socket_id = -1; + } + + /* update core and thread sibling masks */ + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->socket_id == cpu_topo->socket_id) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); + + printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", + cpuid, cpu_topology[cpuid].thread_id, + cpu_topology[cpuid].core_id, + cpu_topology[cpuid].socket_id, mpidr); +} + +/* + * init_cpu_topology is called at boot when only one cpu is running + * which prevent simultaneous write access to cpu_topology array + */ +void init_cpu_topology(void) +{ + unsigned int cpu; + + /* init core mask */ + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); + + cpu_topo->thread_id = -1; + cpu_topo->core_id = -1; + cpu_topo->socket_id = -1; + cpumask_clear(&cpu_topo->core_sibling); + cpumask_clear(&cpu_topo->thread_sibling); + } + smp_wmb(); +} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index bc9f9da782cb..99a572702509 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -21,12 +21,14 @@ #include <linux/kdebug.h> #include <linux/module.h> #include <linux/kexec.h> +#include <linux/bug.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/atomic.h> #include <asm/cacheflush.h> +#include <asm/exception.h> #include <asm/system.h> #include <asm/unistd.h> #include <asm/traps.h> @@ -255,7 +257,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt return ret; } -static DEFINE_SPINLOCK(die_lock); +static DEFINE_RAW_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. @@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs *regs, int err) oops_enter(); - spin_lock_irq(&die_lock); + raw_spin_lock_irq(&die_lock); console_verbose(); bust_spinlocks(1); + if (!user_mode(regs)) + report_bug(regs->ARM_pc, regs); ret = __die(str, err, thread, regs); if (regs && kexec_should_crash(thread->task)) @@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs *regs, int err) bust_spinlocks(0); add_taint(TAINT_DIE); - spin_unlock_irq(&die_lock); + raw_spin_unlock_irq(&die_lock); oops_exit(); if (in_interrupt()) @@ -301,25 +305,43 @@ void arm_notify_die(const char *str, struct pt_regs *regs, } } +#ifdef CONFIG_GENERIC_BUG + +int is_valid_bugaddr(unsigned long pc) +{ +#ifdef CONFIG_THUMB2_KERNEL + unsigned short bkpt; +#else + unsigned long bkpt; +#endif + + if (probe_kernel_address((unsigned *)pc, bkpt)) + return 0; + + return bkpt == BUG_INSTR_VALUE; +} + +#endif + static LIST_HEAD(undef_hook); -static DEFINE_SPINLOCK(undef_lock); +static DEFINE_RAW_SPINLOCK(undef_lock); void register_undef_hook(struct undef_hook *hook) { unsigned long flags; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_add(&hook->node, &undef_hook); - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); } void unregister_undef_hook(struct undef_hook *hook) { unsigned long flags; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_del(&hook->node); - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); } static int call_undef_hook(struct pt_regs *regs, unsigned int instr) @@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) unsigned long flags; int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; - spin_lock_irqsave(&undef_lock, flags); + raw_spin_lock_irqsave(&undef_lock, flags); list_for_each_entry(hook, &undef_hook, node) if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) fn = hook->fn; - spin_unlock_irqrestore(&undef_lock, flags); + raw_spin_unlock_irqrestore(&undef_lock, flags); return fn ? fn(regs, instr) : 1; } @@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) arm_notify_die("unknown data abort code", regs, &info, instr, 0); } -void __attribute__((noreturn)) __bug(const char *file, int line) -{ - printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); - *(int *)0 = 0; - - /* Avoid "noreturn function does return" */ - for (;;); -} -EXPORT_SYMBOL(__bug); - void __readwrite_bug(const char *fn) { printk("%s called, but not implemented\n", fn); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index bf977f8514f6..20b3041e0860 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -21,10 +21,13 @@ #define ARM_CPU_KEEP(x) #endif -#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK) +#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ + defined(CONFIG_GENERIC_BUG) #define ARM_EXIT_KEEP(x) x +#define ARM_EXIT_DISCARD(x) #else #define ARM_EXIT_KEEP(x) +#define ARM_EXIT_DISCARD(x) x #endif OUTPUT_ARCH(arm) @@ -39,6 +42,11 @@ jiffies = jiffies_64 + 4; SECTIONS { /* + * XXX: The linker does not define how output sections are + * assigned to input sections when there are multiple statements + * matching the same input section name. There is no documented + * order of matching. + * * unwind exit sections must be discarded before the rest of the * unwind sections get included. */ @@ -47,6 +55,9 @@ SECTIONS *(.ARM.extab.exit.text) ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text)) ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) + ARM_EXIT_DISCARD(EXIT_TEXT) + ARM_EXIT_DISCARD(EXIT_DATA) + EXIT_CALL #ifndef CONFIG_HOTPLUG *(.ARM.exidx.devexit.text) *(.ARM.extab.devexit.text) @@ -58,6 +69,8 @@ SECTIONS #ifndef CONFIG_SMP_ON_UP *(.alt.smp.init) #endif + *(.discard) + *(.discard.*) } #ifdef CONFIG_XIP_KERNEL @@ -279,9 +292,6 @@ SECTIONS STABS_DEBUG .comment 0 : { *(.comment) } - - /* Default discards */ - DISCARDS } /* diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index a673297b0cf1..cd07b5814c23 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -22,15 +22,10 @@ #define mask r7 #define offset r8 -ENTRY(__backtrace) - mov r1, #0x10 - mov r0, fp - ENTRY(c_backtrace) #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) mov pc, lr -ENDPROC(__backtrace) ENDPROC(c_backtrace) #else stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... @@ -107,7 +102,6 @@ for_each_frame: tst frame, mask @ Check for address exceptions mov r1, frame bl printk no_frame: ldmfd sp!, {r4 - r8, pc} -ENDPROC(__backtrace) ENDPROC(c_backtrace) .pushsection __ex_table,"a" diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S index faa7748142da..e55c4842c290 100644 --- a/arch/arm/lib/div64.S +++ b/arch/arm/lib/div64.S @@ -13,6 +13,7 @@ */ #include <linux/linkage.h> +#include <asm/unwind.h> #ifdef __ARMEB__ #define xh r0 @@ -44,6 +45,7 @@ */ ENTRY(__do_div64) +UNWIND(.fnstart) @ Test for easy paths first. subs ip, r4, #1 @@ -189,7 +191,12 @@ ENTRY(__do_div64) moveq yh, xh moveq xh, #0 moveq pc, lr +UNWIND(.fnend) +UNWIND(.fnstart) +UNWIND(.pad #4) +UNWIND(.save {lr}) +Ldiv0_64: @ Division by 0: str lr, [sp, #-8]! bl __div0 @@ -200,4 +207,5 @@ ENTRY(__do_div64) mov xh, #0 ldr pc, [sp], #8 +UNWIND(.fnend) ENDPROC(__do_div64) diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index 8b9b13649f81..025f742dd4df 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -17,6 +17,7 @@ #include <linux/sched.h> #include <linux/hardirq.h> /* for in_atomic() */ #include <linux/gfp.h> +#include <linux/highmem.h> #include <asm/current.h> #include <asm/page.h> diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index 3462b815054a..9ab5a3e5f4f1 100644 --- a/arch/arm/mach-at91/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot @@ -4,15 +4,15 @@ # INITRD_PHYS must be in RAM ifeq ($(CONFIG_ARCH_AT91CAP9),y) - zreladdr-y := 0x70008000 + zreladdr-y += 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70410000 else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y) - zreladdr-y := 0x70008000 + zreladdr-y += 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70410000 else - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 initrd_phys-y := 0x20410000 endif diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index d522b47e30b5..6c8e3b5f669f 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -157,7 +157,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk), CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk), - CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc1_clk), + CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), diff --git a/arch/arm/mach-bcmring/Kconfig b/arch/arm/mach-bcmring/Kconfig index 457b4384913e..9170d16dca50 100644 --- a/arch/arm/mach-bcmring/Kconfig +++ b/arch/arm/mach-bcmring/Kconfig @@ -17,5 +17,3 @@ config BCM_ZRELADDR hex "Compressed ZREL ADDR" endmenu - -# source "drivers/char/bcmring/Kconfig" diff --git a/arch/arm/mach-bcmring/Makefile.boot b/arch/arm/mach-bcmring/Makefile.boot index fb53b283bebb..aef2467757fa 100644 --- a/arch/arm/mach-bcmring/Makefile.boot +++ b/arch/arm/mach-bcmring/Makefile.boot @@ -1,6 +1,6 @@ # Address where decompressor will be written and eventually executed. # # default to SDRAM -zreladdr-y := $(CONFIG_BCM_ZRELADDR) +zreladdr-y += $(CONFIG_BCM_ZRELADDR) params_phys-y := 0x00000800 diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index a604b9ebb501..31a143592c81 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c @@ -136,8 +136,8 @@ static void __init bcmring_init_machine(void) * *****************************************************************************/ -static void __init bcmring_fixup(struct machine_desc *desc, - struct tag *t, char **cmdline, struct meminfo *mi) { +static void __init bcmring_fixup(struct tag *t, char **cmdline, + struct meminfo *mi) { #ifdef CONFIG_BLK_DEV_INITRD printk(KERN_NOTICE "bcmring_fixup\n"); t->hdr.tag = ATAG_CORE; diff --git a/arch/arm/mach-bcmring/irq.c b/arch/arm/mach-bcmring/irq.c index c48feaf4e8e9..437fa683bcb2 100644 --- a/arch/arm/mach-bcmring/irq.c +++ b/arch/arm/mach-bcmring/irq.c @@ -20,7 +20,6 @@ #include <linux/stddef.h> #include <linux/list.h> #include <linux/timer.h> -#include <linux/version.h> #include <linux/io.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-bcmring/timer.c b/arch/arm/mach-bcmring/timer.c index 2d415d2a8e68..af9c3d7e2a0c 100644 --- a/arch/arm/mach-bcmring/timer.c +++ b/arch/arm/mach-bcmring/timer.c @@ -12,7 +12,6 @@ * consent. *****************************************************************************/ -#include <linux/version.h> #include <linux/types.h> #include <linux/module.h> #include <csp/tmrHw.h> diff --git a/arch/arm/mach-clps711x/Makefile.boot b/arch/arm/mach-clps711x/Makefile.boot index a51fcef64fe0..9398e859b5af 100644 --- a/arch/arm/mach-clps711x/Makefile.boot +++ b/arch/arm/mach-clps711x/Makefile.boot @@ -1,5 +1,5 @@ # The standard locations for stuff on CLPS711x type processors - zreladdr-y := 0xc0028000 + zreladdr-y += 0xc0028000 params_phys-y := 0xc0000100 # Should probably have some agreement on these... initrd_phys-$(CONFIG_ARCH_P720T) := 0xc0400000 diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c index 67b5abb4a60a..0a2e74feb24a 100644 --- a/arch/arm/mach-clps711x/clep7312.c +++ b/arch/arm/mach-clps711x/clep7312.c @@ -26,8 +26,7 @@ #include "common.h" static void __init -fixup_clep7312(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi) { mi->nr_banks=1; mi->bank[0].start = 0xc0000000; diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c index 98ca5b2e940d..725a7a54ba42 100644 --- a/arch/arm/mach-clps711x/edb7211-arch.c +++ b/arch/arm/mach-clps711x/edb7211-arch.c @@ -37,8 +37,7 @@ static void __init edb7211_reserve(void) } static void __init -fixup_edb7211(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi) { /* * Bank start addresses are not present in the information diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index b1cb479e71e9..1947b30f9b8c 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -57,8 +57,7 @@ typedef struct tag_IMAGE_PARAMS #define IMAGE_PARAMS_PHYS 0xC01F0000 static void __init -fortunet_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi) { IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS); *cmdline = phys_to_virt(ip->command_line); diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index cefbce0480b9..3f796e0d3284 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -56,8 +56,7 @@ static struct map_desc p720t_io_desc[] __initdata = { }; static void __init -fixup_p720t(struct machine_desc *desc, struct tag *tag, - char **cmdline, struct meminfo *mi) +fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi) { /* * Our bootloader doesn't setup any tags (yet). diff --git a/arch/arm/mach-cns3xxx/Makefile.boot b/arch/arm/mach-cns3xxx/Makefile.boot index 777012865220..d079de0b6e3b 100644 --- a/arch/arm/mach-cns3xxx/Makefile.boot +++ b/arch/arm/mach-cns3xxx/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00C00000 diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index 6bd83ed90afe..d87bfc397d39 100644 --- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -8,7 +8,6 @@ * published by the Free Software Foundation. */ -#include <mach/hardware.h> #include <asm/hardware/entry-macro-gic.S> .macro disable_fiq diff --git a/arch/arm/mach-cns3xxx/include/mach/system.h b/arch/arm/mach-cns3xxx/include/mach/system.h index 58bb03ae3cf4..4f16c9b79f78 100644 --- a/arch/arm/mach-cns3xxx/include/mach/system.h +++ b/arch/arm/mach-cns3xxx/include/mach/system.h @@ -13,7 +13,6 @@ #include <linux/io.h> #include <asm/proc-fns.h> -#include <mach/hardware.h> static inline void arch_idle(void) { diff --git a/arch/arm/mach-cns3xxx/include/mach/uncompress.h b/arch/arm/mach-cns3xxx/include/mach/uncompress.h index de8ead9b91f7..a91b6058ab4f 100644 --- a/arch/arm/mach-cns3xxx/include/mach/uncompress.h +++ b/arch/arm/mach-cns3xxx/include/mach/uncompress.h @@ -8,7 +8,6 @@ */ #include <asm/mach-types.h> -#include <mach/hardware.h> #include <mach/cns3xxx.h> #define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c index 06fd25d70aec..0f8fca48a5ed 100644 --- a/arch/arm/mach-cns3xxx/pcie.c +++ b/arch/arm/mach-cns3xxx/pcie.c @@ -49,7 +49,7 @@ static struct cns3xxx_pcie *sysdata_to_cnspci(void *sysdata) return &cns3xxx_pcie[root->domain]; } -static struct cns3xxx_pcie *pdev_to_cnspci(struct pci_dev *dev) +static struct cns3xxx_pcie *pdev_to_cnspci(const struct pci_dev *dev) { return sysdata_to_cnspci(dev->sysdata); } diff --git a/arch/arm/mach-davinci/Makefile.boot b/arch/arm/mach-davinci/Makefile.boot index db97ef2c6477..04a6c4e67b14 100644 --- a/arch/arm/mach-davinci/Makefile.boot +++ b/arch/arm/mach-davinci/Makefile.boot @@ -2,12 +2,12 @@ ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y) ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y) $(error Cannot enable DaVinci and DA8XX platforms concurrently) else - zreladdr-y := 0xc0008000 + zreladdr-y += 0xc0008000 params_phys-y := 0xc0000100 initrd_phys-y := 0xc0800000 endif else - zreladdr-y := 0x80008000 + zreladdr-y += 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x80800000 endif diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index bd5394537c88..008d51407cd7 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -115,6 +115,32 @@ static struct spi_board_info da850evm_spi_info[] = { }, }; +#ifdef CONFIG_MTD +static void da850_evm_m25p80_notify_add(struct mtd_info *mtd) +{ + char *mac_addr = davinci_soc_info.emac_pdata->mac_addr; + size_t retlen; + + if (!strcmp(mtd->name, "MAC-Address")) { + mtd->read(mtd, 0, ETH_ALEN, &retlen, mac_addr); + if (retlen == ETH_ALEN) + pr_info("Read MAC addr from SPI Flash: %pM\n", + mac_addr); + } +} + +static struct mtd_notifier da850evm_spi_notifier = { + .add = da850_evm_m25p80_notify_add, +}; + +static void da850_evm_setup_mac_addr(void) +{ + register_mtd_user(&da850evm_spi_notifier); +} +#else +static void da850_evm_setup_mac_addr(void) { } +#endif + static struct mtd_partition da850_evm_norflash_partition[] = { { .name = "bootloaders + env", @@ -1244,6 +1270,8 @@ static __init void da850_evm_init(void) if (ret) pr_warning("da850_evm_init: sata registration failed: %d\n", ret); + + da850_evm_setup_mac_addr(); } #ifdef CONFIG_SERIAL_8250_CONSOLE diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 47fd0bc3d3e7..fa59c097223d 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -243,7 +243,7 @@ #define PSC_STATE_DISABLE 2 #define PSC_STATE_ENABLE 3 -#define MDSTAT_STATE_MASK 0x1f +#define MDSTAT_STATE_MASK 0x3f #define MDCTL_FORCE BIT(31) #ifndef __ASSEMBLER__ diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S index fb5e72b532b0..5f1e045a3ad1 100644 --- a/arch/arm/mach-davinci/sleep.S +++ b/arch/arm/mach-davinci/sleep.S @@ -217,7 +217,11 @@ ddr2clk_stop_done: ENDPROC(davinci_ddr_psc_config) CACHE_FLUSH: - .word arm926_flush_kern_cache_all +#ifdef CONFIG_CPU_V6 + .word v6_flush_kern_cache_all +#else + .word arm926_flush_kern_cache_all +#endif ENTRY(davinci_cpu_suspend_sz) .word . - davinci_cpu_suspend diff --git a/arch/arm/mach-dove/Makefile.boot b/arch/arm/mach-dove/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-dove/Makefile.boot +++ b/arch/arm/mach-dove/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 83dce859886d..a9e0dae86a26 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -158,7 +158,7 @@ void __init dove_spi0_init(void) void __init dove_spi1_init(void) { - orion_spi_init(DOVE_SPI1_PHYS_BASE, get_tclk()); + orion_spi_1_init(DOVE_SPI1_PHYS_BASE, get_tclk()); } /***************************************************************************** diff --git a/arch/arm/mach-ebsa110/Makefile.boot b/arch/arm/mach-ebsa110/Makefile.boot index 232126044935..83cf07c38ada 100644 --- a/arch/arm/mach-ebsa110/Makefile.boot +++ b/arch/arm/mach-ebsa110/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000400 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-ebsa110/include/mach/io.h b/arch/arm/mach-ebsa110/include/mach/io.h index f68daa632af0..44679db672fb 100644 --- a/arch/arm/mach-ebsa110/include/mach/io.h +++ b/arch/arm/mach-ebsa110/include/mach/io.h @@ -13,8 +13,6 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffff - u8 __inb8(unsigned int port); void __outb8(u8 val, unsigned int port); diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot index 0ad33f15c622..d3113a71cb40 100644 --- a/arch/arm/mach-ep93xx/Makefile.boot +++ b/arch/arm/mach-ep93xx/Makefile.boot @@ -1,14 +1,14 @@ - zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00008000 + zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) += 0x00008000 params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100 - zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0008000 + zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) += 0xc0008000 params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100 - zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0008000 + zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) += 0xd0008000 params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100 - zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0008000 + zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) += 0xe0008000 params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100 - zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0008000 + zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) += 0xf0008000 params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100 diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h index 0eabec62cd9d..f1397a13e76b 100644 --- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h +++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h @@ -6,7 +6,7 @@ * TS72xx memory map: * * virt phys size - * febff000 22000000 4K model number register + * febff000 22000000 4K model number register (bits 0-2) * febfe000 22400000 4K options register * febfd000 22800000 4K options register #2 * febf9000 10800000 4K TS-5620 RTC index register @@ -20,6 +20,9 @@ #define TS72XX_MODEL_TS7200 0x00 #define TS72XX_MODEL_TS7250 0x01 #define TS72XX_MODEL_TS7260 0x02 +#define TS72XX_MODEL_TS7300 0x03 +#define TS72XX_MODEL_TS7400 0x04 +#define TS72XX_MODEL_MASK 0x07 #define TS72XX_OPTIONS_PHYS_BASE 0x22400000 @@ -51,19 +54,34 @@ #ifndef __ASSEMBLY__ +static inline int ts72xx_model(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK; +} + static inline int board_is_ts7200(void) { - return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200; + return ts72xx_model() == TS72XX_MODEL_TS7200; } static inline int board_is_ts7250(void) { - return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250; + return ts72xx_model() == TS72XX_MODEL_TS7250; } static inline int board_is_ts7260(void) { - return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260; + return ts72xx_model() == TS72XX_MODEL_TS7260; +} + +static inline int board_is_ts7300(void) +{ + return ts72xx_model() == TS72XX_MODEL_TS7300; +} + +static inline int board_is_ts7400(void) +{ + return ts72xx_model() == TS72XX_MODEL_TS7400; } static inline int is_max197_installed(void) diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index 0c77ab99fa16..fc1f92dfbea8 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -12,6 +12,7 @@ if ARCH_EXYNOS4 config CPU_EXYNOS4210 bool select S3C_PL330_DMA + select ARM_CPU_SUSPEND if PM help Enable EXYNOS4210 CPU support diff --git a/arch/arm/mach-exynos4/Makefile.boot b/arch/arm/mach-exynos4/Makefile.boot index d65956ffb43d..b9862e22bf10 100644 --- a/arch/arm/mach-exynos4/Makefile.boot +++ b/arch/arm/mach-exynos4/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x40008000 + zreladdr-y += 0x40008000 params_phys-y := 0x40000100 diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c index 851dea018578..86964d2e9e1b 100644 --- a/arch/arm/mach-exynos4/clock.c +++ b/arch/arm/mach-exynos4/clock.c @@ -520,7 +520,7 @@ static struct clk init_clocks_off[] = { .ctrlbit = (1 << 21), }, { .name = "ac97", - .id = -1, + .devname = "samsung-ac97", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 27), }, { @@ -899,8 +899,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 }, }, { .clk = { - .name = "sclk_cam", - .devname = "exynos4-fimc.0", + .name = "sclk_cam0", .enable = exynos4_clksrc_mask_cam_ctrl, .ctrlbit = (1 << 16), }, @@ -909,8 +908,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 }, }, { .clk = { - .name = "sclk_cam", - .devname = "exynos4-fimc.1", + .name = "sclk_cam1", .enable = exynos4_clksrc_mask_cam_ctrl, .ctrlbit = (1 << 20), }, @@ -1160,7 +1158,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void) vpllsrc = clk_get_rate(&clk_vpllsrc.clk); vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), - __raw_readl(S5P_VPLL_CON1), pll_4650); + __raw_readl(S5P_VPLL_CON1), pll_4650c); clk_fout_apll.ops = &exynos4_fout_apll_ops; clk_fout_mpll.rate = mpll; diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 2d8a40c9e6e5..746d6fc6d397 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -24,12 +24,13 @@ #include <plat/exynos4.h> #include <plat/adc-core.h> #include <plat/sdhci.h> -#include <plat/devs.h> #include <plat/fb-core.h> #include <plat/fimc-core.h> #include <plat/iic-core.h> +#include <plat/reset.h> #include <mach/regs-irq.h> +#include <mach/regs-pmu.h> extern int combiner_init(unsigned int combiner_nr, void __iomem *base, unsigned int irq_start); @@ -128,6 +129,11 @@ static void exynos4_idle(void) local_irq_enable(); } +static void exynos4_sw_reset(void) +{ + __raw_writel(0x1, S5P_SWRESET); +} + /* * exynos4_map_io * @@ -241,5 +247,8 @@ int __init exynos4_init(void) /* set idle function */ pm_idle = exynos4_idle; + /* set sw_reset function */ + s5p_reset_hook = exynos4_sw_reset; + return sysdev_register(&exynos4_sysdev); } diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h index 934d2a493982..f8952f8f3757 100644 --- a/arch/arm/mach-exynos4/include/mach/irqs.h +++ b/arch/arm/mach-exynos4/include/mach/irqs.h @@ -80,9 +80,8 @@ #define IRQ_HSMMC3 IRQ_SPI(76) #define IRQ_DWMCI IRQ_SPI(77) -#define IRQ_MIPICSI0 IRQ_SPI(78) - -#define IRQ_MIPICSI1 IRQ_SPI(80) +#define IRQ_MIPI_CSIS0 IRQ_SPI(78) +#define IRQ_MIPI_CSIS1 IRQ_SPI(80) #define IRQ_ONENAND_AUDI IRQ_SPI(82) #define IRQ_ROTATOR IRQ_SPI(83) diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h index fa49bbb8e7b0..cdf9b47c303c 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h @@ -29,6 +29,8 @@ #define S5P_USE_STANDBY_WFE1 (1 << 25) #define S5P_USE_MASK ((0x3 << 16) | (0x3 << 24)) +#define S5P_SWRESET S5P_PMUREG(0x0400) + #define S5P_WAKEUP_STAT S5P_PMUREG(0x0600) #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) #define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) diff --git a/arch/arm/mach-exynos4/irq-eint.c b/arch/arm/mach-exynos4/irq-eint.c index 9d87d2ac7f68..badb8c66fc9b 100644 --- a/arch/arm/mach-exynos4/irq-eint.c +++ b/arch/arm/mach-exynos4/irq-eint.c @@ -23,6 +23,8 @@ #include <mach/regs-gpio.h> +#include <asm/mach/irq.h> + static DEFINE_SPINLOCK(eint_lock); static unsigned int eint0_15_data[16]; @@ -184,8 +186,11 @@ static inline void exynos4_irq_demux_eint(unsigned int start) static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) { + struct irq_chip *chip = irq_get_chip(irq); + chained_irq_enter(chip, desc); exynos4_irq_demux_eint(IRQ_EINT(16)); exynos4_irq_demux_eint(IRQ_EINT(24)); + chained_irq_exit(chip, desc); } static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) @@ -193,6 +198,7 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) u32 *irq_data = irq_get_handler_data(irq); struct irq_chip *chip = irq_get_chip(irq); + chained_irq_enter(chip, desc); chip->irq_mask(&desc->irq_data); if (chip->irq_ack) @@ -201,6 +207,7 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) generic_handle_irq(*irq_data); chip->irq_unmask(&desc->irq_data); + chained_irq_exit(chip, desc); } int __init exynos4_init_irq_eint(void) diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c index 0e280d12301e..b3b5d8911004 100644 --- a/arch/arm/mach-exynos4/mach-universal_c210.c +++ b/arch/arm/mach-exynos4/mach-universal_c210.c @@ -79,7 +79,7 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = { }; static struct regulator_consumer_supply max8952_consumer = - REGULATOR_SUPPLY("vddarm", NULL); + REGULATOR_SUPPLY("vdd_arm", NULL); static struct max8952_platform_data universal_max8952_pdata __initdata = { .gpio_vid0 = EXYNOS4_GPX0(3), @@ -105,7 +105,7 @@ static struct max8952_platform_data universal_max8952_pdata __initdata = { }; static struct regulator_consumer_supply lp3974_buck1_consumer = - REGULATOR_SUPPLY("vddint", NULL); + REGULATOR_SUPPLY("vdd_int", NULL); static struct regulator_consumer_supply lp3974_buck2_consumer = REGULATOR_SUPPLY("vddg3d", NULL); diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c index 1ae059b7ad7b..ddd86864fb83 100644 --- a/arch/arm/mach-exynos4/mct.c +++ b/arch/arm/mach-exynos4/mct.c @@ -132,12 +132,18 @@ static cycle_t exynos4_frc_read(struct clocksource *cs) return ((cycle_t)hi << 32) | lo; } +static void exynos4_frc_resume(struct clocksource *cs) +{ + exynos4_mct_frc_start(0, 0); +} + struct clocksource mct_frc = { .name = "mct-frc", .rating = 400, .read = exynos4_frc_read, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .resume = exynos4_frc_resume, }; static void __init exynos4_clocksource_init(void) @@ -389,9 +395,11 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) } /* Setup the local clock events for a CPU */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) +int __cpuinit local_timer_setup(struct clock_event_device *evt) { exynos4_mct_tick_init(evt); + + return 0; } int local_timer_ack(void) diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c index 7c2282c6ba81..0c90896ad9a0 100644 --- a/arch/arm/mach-exynos4/platsmp.c +++ b/arch/arm/mach-exynos4/platsmp.c @@ -106,6 +106,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu) */ spin_lock(&boot_lock); spin_unlock(&boot_lock); + + set_cpu_online(cpu, true); } int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -191,12 +193,10 @@ void __init smp_init_cpus(void) ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ - if (ncores > NR_CPUS) { - printk(KERN_WARNING - "EXYNOS4: no. of cores (%d) greater than configured " - "maximum of %d - clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) diff --git a/arch/arm/mach-exynos4/setup-keypad.c b/arch/arm/mach-exynos4/setup-keypad.c index 1ee0ebff111f..7862bfb5933d 100644 --- a/arch/arm/mach-exynos4/setup-keypad.c +++ b/arch/arm/mach-exynos4/setup-keypad.c @@ -19,15 +19,16 @@ void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) if (rows > 8) { /* Set all the necessary GPX2 pins: KP_ROW[0~7] */ - s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3)); + s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3), + S3C_GPIO_PULL_UP); /* Set all the necessary GPX3 pins: KP_ROW[8~] */ - s3c_gpio_cfgrange_nopull(EXYNOS4_GPX3(0), (rows - 8), - S3C_GPIO_SFN(3)); + s3c_gpio_cfgall_range(EXYNOS4_GPX3(0), (rows - 8), + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); } else { /* Set all the necessary GPX2 pins: KP_ROW[x] */ - s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), rows, - S3C_GPIO_SFN(3)); + s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), rows, S3C_GPIO_SFN(3), + S3C_GPIO_PULL_UP); } /* Set all the necessary GPX1 pins to special-function 3: KP_COL[x] */ diff --git a/arch/arm/mach-exynos4/setup-usb-phy.c b/arch/arm/mach-exynos4/setup-usb-phy.c index 0883c1b824b9..39aca045f660 100644 --- a/arch/arm/mach-exynos4/setup-usb-phy.c +++ b/arch/arm/mach-exynos4/setup-usb-phy.c @@ -82,7 +82,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev) rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK); writel(rstcon, EXYNOS4_RSTCON); - udelay(50); + udelay(80); clk_disable(otg_clk); clk_put(otg_clk); diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig index dc26fff22cf0..f643ef819da6 100644 --- a/arch/arm/mach-footbridge/Kconfig +++ b/arch/arm/mach-footbridge/Kconfig @@ -4,8 +4,8 @@ menu "Footbridge Implementations" config ARCH_CATS bool "CATS" - select CLKSRC_I8253 select CLKEVT_I8253 + select CLKSRC_I8253 select FOOTBRIDGE_HOST select ISA select ISA_DMA @@ -61,6 +61,7 @@ config ARCH_EBSA285_HOST config ARCH_NETWINDER bool "NetWinder" + select CLKEVT_I8253 select CLKSRC_I8253 select FOOTBRIDGE_HOST select ISA diff --git a/arch/arm/mach-footbridge/Makefile.boot b/arch/arm/mach-footbridge/Makefile.boot index c7e75acfe6c9..ff0a4b5b0a82 100644 --- a/arch/arm/mach-footbridge/Makefile.boot +++ b/arch/arm/mach-footbridge/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 5b1a8db779be..206ff2f39d6c 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -76,8 +76,7 @@ __initcall(cats_hw_init); * hard reboots fail on early boards. */ static void __init -fixup_cats(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_cats(struct tag *tags, char **cmdline, struct meminfo *mi) { screen_info.orig_video_lines = 25; screen_info.orig_video_points = 16; diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index 1331fff51ae2..18c32a5541d9 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -18,6 +18,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/spinlock.h> +#include <video/vga.h> #include <asm/irq.h> #include <asm/system.h> diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h index 15d54981674c..e3d6ccac2162 100644 --- a/arch/arm/mach-footbridge/include/mach/hardware.h +++ b/arch/arm/mach-footbridge/include/mach/hardware.h @@ -93,7 +93,7 @@ #define CPLD_FLASH_WR_ENABLE 1 #ifndef __ASSEMBLY__ -extern spinlock_t nw_gpio_lock; +extern raw_spinlock_t nw_gpio_lock; extern void nw_gpio_modify_op(unsigned int mask, unsigned int set); extern void nw_gpio_modify_io(unsigned int mask, unsigned int in); extern unsigned int nw_gpio_read(void); diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h index 32e4cc397c28..15a70396c27d 100644 --- a/arch/arm/mach-footbridge/include/mach/io.h +++ b/arch/arm/mach-footbridge/include/mach/io.h @@ -23,8 +23,6 @@ #define PCIO_SIZE 0x00100000 #define PCIO_BASE MMU_IO(0xff000000, 0x7c000000) -#define IO_SPACE_LIMIT 0xffff - /* * Translation of various region addresses to virtual addresses */ diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index 06e514f372d0..0f7aeff486c9 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -68,7 +68,7 @@ static inline void wb977_ww(int reg, int val) /* * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE */ -DEFINE_SPINLOCK(nw_gpio_lock); +DEFINE_RAW_SPINLOCK(nw_gpio_lock); EXPORT_SYMBOL(nw_gpio_lock); static unsigned int current_gpio_op; @@ -327,9 +327,9 @@ static inline void wb977_init_gpio(void) /* * Set Group1/Group2 outputs */ - spin_lock_irqsave(&nw_gpio_lock, flags); + raw_spin_lock_irqsave(&nw_gpio_lock, flags); nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN); - spin_unlock_irqrestore(&nw_gpio_lock, flags); + raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); } /* @@ -390,9 +390,9 @@ static void __init cpld_init(void) { unsigned long flags; - spin_lock_irqsave(&nw_gpio_lock, flags); + raw_spin_lock_irqsave(&nw_gpio_lock, flags); nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE); - spin_unlock_irqrestore(&nw_gpio_lock, flags); + raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); } static unsigned char rwa_unlock[] __initdata = @@ -616,9 +616,9 @@ static int __init nw_hw_init(void) cpld_init(); rwa010_init(); - spin_lock_irqsave(&nw_gpio_lock, flags); + raw_spin_lock_irqsave(&nw_gpio_lock, flags); nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); - spin_unlock_irqrestore(&nw_gpio_lock, flags); + raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); } return 0; } @@ -631,8 +631,7 @@ __initcall(nw_hw_init); * the parameter page. */ static void __init -fixup_netwinder(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_netwinder(struct tag *tags, char **cmdline, struct meminfo *mi) { #ifdef CONFIG_ISAPNP extern int isapnp_disable; diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c index 00269fe0be8a..e57102e871fc 100644 --- a/arch/arm/mach-footbridge/netwinder-leds.c +++ b/arch/arm/mach-footbridge/netwinder-leds.c @@ -31,13 +31,13 @@ static char led_state; static char hw_led_state; -static DEFINE_SPINLOCK(leds_lock); +static DEFINE_RAW_SPINLOCK(leds_lock); static void netwinder_leds_event(led_event_t evt) { unsigned long flags; - spin_lock_irqsave(&leds_lock, flags); + raw_spin_lock_irqsave(&leds_lock, flags); switch (evt) { case led_start: @@ -117,12 +117,12 @@ static void netwinder_leds_event(led_event_t evt) break; } - spin_unlock_irqrestore(&leds_lock, flags); + raw_spin_unlock_irqrestore(&leds_lock, flags); if (led_state & LED_STATE_ENABLED) { - spin_lock_irqsave(&nw_gpio_lock, flags); + raw_spin_lock_irqsave(&nw_gpio_lock, flags); nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state); - spin_unlock_irqrestore(&nw_gpio_lock, flags); + raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); } } diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot index 22a52c228d93..683f52b20e3d 100644 --- a/arch/arm/mach-gemini/Makefile.boot +++ b/arch/arm/mach-gemini/Makefile.boot @@ -1,9 +1,9 @@ ifeq ($(CONFIG_GEMINI_MEM_SWAP),y) - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 else - zreladdr-y := 0x10008000 + zreladdr-y += 0x10008000 params_phys-y := 0x10000100 initrd_phys-y := 0x10800000 endif diff --git a/arch/arm/mach-h720x/Makefile.boot b/arch/arm/mach-h720x/Makefile.boot index 52984017bd91..d875a7094dfe 100644 --- a/arch/arm/mach-h720x/Makefile.boot +++ b/arch/arm/mach-h720x/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-$(CONFIG_ARCH_H720X) := 0x40008000 + zreladdr-$(CONFIG_ARCH_H720X) += 0x40008000 diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot index ebee18b3884c..dbe61201bcd8 100644 --- a/arch/arm/mach-imx/Makefile.boot +++ b/arch/arm/mach-imx/Makefile.boot @@ -1,19 +1,19 @@ -zreladdr-$(CONFIG_ARCH_MX1) := 0x08008000 +zreladdr-$(CONFIG_ARCH_MX1) += 0x08008000 params_phys-$(CONFIG_ARCH_MX1) := 0x08000100 initrd_phys-$(CONFIG_ARCH_MX1) := 0x08800000 -zreladdr-$(CONFIG_MACH_MX21) := 0xC0008000 +zreladdr-$(CONFIG_MACH_MX21) += 0xC0008000 params_phys-$(CONFIG_MACH_MX21) := 0xC0000100 initrd_phys-$(CONFIG_MACH_MX21) := 0xC0800000 -zreladdr-$(CONFIG_ARCH_MX25) := 0x80008000 +zreladdr-$(CONFIG_ARCH_MX25) += 0x80008000 params_phys-$(CONFIG_ARCH_MX25) := 0x80000100 initrd_phys-$(CONFIG_ARCH_MX25) := 0x80800000 -zreladdr-$(CONFIG_MACH_MX27) := 0xA0008000 +zreladdr-$(CONFIG_MACH_MX27) += 0xA0008000 params_phys-$(CONFIG_MACH_MX27) := 0xA0000100 initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000 -zreladdr-$(CONFIG_ARCH_MX3) := 0x80008000 +zreladdr-$(CONFIG_ARCH_MX3) += 0x80008000 params_phys-$(CONFIG_ARCH_MX3) := 0x80000100 initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000 diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index 87887ac5806b..f851fe903687 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -310,7 +310,7 @@ static struct sys_timer eukrea_cpuimx27_timer = { .init = eukrea_cpuimx27_timer_init, }; -MACHINE_START(CPUIMX27, "EUKREA CPUIMX27") +MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27") .boot_params = MX27_PHYS_OFFSET + 0x100, .map_io = mx27_map_io, .init_early = imx27_init_early, diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index f39a478ba1a6..4bd083ba9af2 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -192,7 +192,7 @@ struct sys_timer eukrea_cpuimx35_timer = { .init = eukrea_cpuimx35_timer_init, }; -MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35") +MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35") /* Maintainer: Eukrea Electromatique */ .boot_params = MX3x_PHYS_OFFSET + 0x100, .map_io = mx35_map_io, diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index da36da52969d..2442d5da883d 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -161,7 +161,7 @@ static struct sys_timer eukrea_cpuimx25_timer = { .init = eukrea_cpuimx25_timer_init, }; -MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25") +MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25") /* Maintainer: Eukrea Electromatique */ .boot_params = MX25_PHYS_OFFSET + 0x100, .map_io = mx25_map_io, diff --git a/arch/arm/mach-integrator/Makefile.boot b/arch/arm/mach-integrator/Makefile.boot index c7e75acfe6c9..ff0a4b5b0a82 100644 --- a/arch/arm/mach-integrator/Makefile.boot +++ b/arch/arm/mach-integrator/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 77315b995681..4b38e13667ac 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -126,6 +126,10 @@ static struct clk_lookup lookups[] = { { /* Bus clock */ .con_id = "apb_pclk", .clk = &dummy_apb_pclk, + }, { + /* Integrator/AP timer frequency */ + .dev_id = "ap_timer", + .clk = &clk24mhz, }, { /* UART0 */ .dev_id = "mb:16", .clk = &uartclk, @@ -205,7 +209,7 @@ static struct amba_pl010_data integrator_uart_data = { #define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) -static DEFINE_SPINLOCK(cm_lock); +static DEFINE_RAW_SPINLOCK(cm_lock); /** * cm_control - update the CM_CTRL register. @@ -217,10 +221,10 @@ void cm_control(u32 mask, u32 set) unsigned long flags; u32 val; - spin_lock_irqsave(&cm_lock, flags); + raw_spin_lock_irqsave(&cm_lock, flags); val = readl(CM_CTRL) & ~mask; writel(val | set, CM_CTRL); - spin_unlock_irqrestore(&cm_lock, flags); + raw_spin_unlock_irqrestore(&cm_lock, flags); } EXPORT_SYMBOL(cm_control); diff --git a/arch/arm/mach-integrator/include/mach/io.h b/arch/arm/mach-integrator/include/mach/io.h index f21bb5493dd9..37beed3fa3ed 100644 --- a/arch/arm/mach-integrator/include/mach/io.h +++ b/arch/arm/mach-integrator/include/mach/io.h @@ -20,8 +20,6 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffff - /* * WARNING: this has to mirror definitions in platform.h */ diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h index 5e6ea5cfea6e..ec467baade09 100644 --- a/arch/arm/mach-integrator/include/mach/platform.h +++ b/arch/arm/mach-integrator/include/mach/platform.h @@ -13,9 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* DO NOT EDIT!! - this file automatically generated - * from .s file by awk -f s2h.awk - */ /************************************************************************** * * Copyright © ARM Limited 1998. All rights reserved. * ***********************************************************************/ @@ -399,15 +396,6 @@ #define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100) #define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200) -#define TICKS_PER_uSEC 24 - -/* - * These are useconds NOT ticks. - * - */ -#define mSEC_1 1000 -#define mSEC_10 (mSEC_1 * 10) - #define INTEGRATOR_CSR_BASE 0x10000000 #define INTEGRATOR_CSR_SIZE 0x10000000 diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 2fbbdd5eac35..f2119908a0b3 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -32,6 +32,8 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/mtd/physmap.h> +#include <linux/clk.h> +#include <video/vga.h> #include <mach/hardware.h> #include <mach/platform.h> @@ -154,6 +156,7 @@ static struct map_desc ap_io_desc[] __initdata = { static void __init ap_map_io(void) { iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc)); + vga_base = PCI_MEMORY_VADDR; } #define INTEGRATOR_SC_VALID_INT 0x003fffff @@ -320,35 +323,24 @@ static void __init ap_init(void) #define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE) #define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE) -/* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - static unsigned long timer_reload; -static void integrator_clocksource_init(u32 khz) +static void integrator_clocksource_init(unsigned long inrate) { void __iomem *base = (void __iomem *)TIMER2_VA_BASE; - u32 ctrl = TIMER_CTRL_ENABLE; + u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; + unsigned long rate = inrate; - if (khz >= 1500) { - khz /= 16; - ctrl = TIMER_CTRL_DIV16; + if (rate >= 1500000) { + rate /= 16; + ctrl |= TIMER_CTRL_DIV16; } - writel(ctrl, base + TIMER_CTRL); writel(0xffff, base + TIMER_LOAD); + writel(ctrl, base + TIMER_CTRL); clocksource_mmio_init(base + TIMER_VALUE, "timer2", - khz * 1000, 200, 16, clocksource_mmio_readl_down); + rate, 200, 16, clocksource_mmio_readl_down); } static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; @@ -372,15 +364,29 @@ static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_devic { u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; - BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT); + /* Disable timer */ + writel(ctrl, clkevt_base + TIMER_CTRL); - if (mode == CLOCK_EVT_MODE_PERIODIC) { - writel(ctrl, clkevt_base + TIMER_CTRL); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* Enable the timer and start the periodic tick */ writel(timer_reload, clkevt_base + TIMER_LOAD); ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; + writel(ctrl, clkevt_base + TIMER_CTRL); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* Leave the timer disabled, .set_next_event will enable it */ + ctrl &= ~TIMER_CTRL_PERIODIC; + writel(ctrl, clkevt_base + TIMER_CTRL); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + default: + /* Just leave in disabled state */ + break; } - writel(ctrl, clkevt_base + TIMER_CTRL); } static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) @@ -396,12 +402,10 @@ static int clkevt_set_next_event(unsigned long next, struct clock_event_device * static struct clock_event_device integrator_clockevent = { .name = "timer1", - .shift = 34, - .features = CLOCK_EVT_FEAT_PERIODIC, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = clkevt_set_mode, .set_next_event = clkevt_set_next_event, .rating = 300, - .cpumask = cpu_all_mask, }; static struct irqaction integrator_timer_irq = { @@ -411,29 +415,27 @@ static struct irqaction integrator_timer_irq = { .dev_id = &integrator_clockevent, }; -static void integrator_clockevent_init(u32 khz) +static void integrator_clockevent_init(unsigned long inrate) { - struct clock_event_device *evt = &integrator_clockevent; + unsigned long rate = inrate; unsigned int ctrl = 0; - if (khz * 1000 > 0x100000 * HZ) { - khz /= 256; + /* Calculate and program a divisor */ + if (rate > 0x100000 * HZ) { + rate /= 256; ctrl |= TIMER_CTRL_DIV256; - } else if (khz * 1000 > 0x10000 * HZ) { - khz /= 16; + } else if (rate > 0x10000 * HZ) { + rate /= 16; ctrl |= TIMER_CTRL_DIV16; } - - timer_reload = khz * 1000 / HZ; + timer_reload = rate / HZ; writel(ctrl, clkevt_base + TIMER_CTRL); - evt->irq = IRQ_TIMERINT1; - evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift); - evt->max_delta_ns = clockevent_delta2ns(0xffff, evt); - evt->min_delta_ns = clockevent_delta2ns(0xf, evt); - setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); - clockevents_register_device(evt); + clockevents_config_and_register(&integrator_clockevent, + rate, + 1, + 0xffffU); } /* @@ -441,14 +443,20 @@ static void integrator_clockevent_init(u32 khz) */ static void __init ap_init_timer(void) { - u32 khz = TICKS_PER_uSEC * 1000; + struct clk *clk; + unsigned long rate; + + clk = clk_get_sys("ap_timer", NULL); + BUG_ON(IS_ERR(clk)); + clk_enable(clk); + rate = clk_get_rate(clk); writel(0, TIMER0_VA_BASE + TIMER_CTRL); writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL); - integrator_clocksource_init(khz); - integrator_clockevent_init(khz); + integrator_clocksource_init(rate); + integrator_clockevent_init(rate); } static struct sys_timer ap_timer = { diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index dd56bfb351e3..b4d8f8b8a085 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -27,7 +27,6 @@ #include <linux/spinlock.h> #include <linux/init.h> #include <linux/io.h> -#include <video/vga.h> #include <mach/hardware.h> #include <mach/platform.h> @@ -164,7 +163,7 @@ * 7:2 register number * */ -static DEFINE_SPINLOCK(v3_lock); +static DEFINE_RAW_SPINLOCK(v3_lock); #define PCI_BUS_NONMEM_START 0x00000000 #define PCI_BUS_NONMEM_SIZE SZ_256M @@ -285,7 +284,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where, unsigned long flags; u32 v; - spin_lock_irqsave(&v3_lock, flags); + raw_spin_lock_irqsave(&v3_lock, flags); addr = v3_open_config_window(bus, devfn, where); switch (size) { @@ -303,7 +302,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where, } v3_close_config_window(); - spin_unlock_irqrestore(&v3_lock, flags); + raw_spin_unlock_irqrestore(&v3_lock, flags); *val = v; return PCIBIOS_SUCCESSFUL; @@ -315,7 +314,7 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, unsigned long addr; unsigned long flags; - spin_lock_irqsave(&v3_lock, flags); + raw_spin_lock_irqsave(&v3_lock, flags); addr = v3_open_config_window(bus, devfn, where); switch (size) { @@ -336,7 +335,7 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, } v3_close_config_window(); - spin_unlock_irqrestore(&v3_lock, flags); + raw_spin_unlock_irqrestore(&v3_lock, flags); return PCIBIOS_SUCCESSFUL; } @@ -505,7 +504,6 @@ void __init pci_v3_preinit(void) pcibios_min_io = 0x6000; pcibios_min_mem = 0x00100000; - vga_base = PCI_MEMORY_VADDR; /* * Hook in our fault handler for PCI errors @@ -515,7 +513,7 @@ void __init pci_v3_preinit(void) hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); - spin_lock_irqsave(&v3_lock, flags); + raw_spin_lock_irqsave(&v3_lock, flags); /* * Unlock V3 registers, but only if they were previously locked. @@ -588,7 +586,7 @@ void __init pci_v3_preinit(void) printk(KERN_ERR "PCI: unable to grab PCI error " "interrupt: %d\n", ret); - spin_unlock_irqrestore(&v3_lock, flags); + raw_spin_unlock_irqrestore(&v3_lock, flags); } void __init pci_v3_postinit(void) diff --git a/arch/arm/mach-iop13xx/Makefile.boot b/arch/arm/mach-iop13xx/Makefile.boot index 0b0e19fdfe6c..3a8c38c3189c 100644 --- a/arch/arm/mach-iop13xx/Makefile.boot +++ b/arch/arm/mach-iop13xx/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-iop32x/Makefile.boot b/arch/arm/mach-iop32x/Makefile.boot index 47000dccd61f..0a833b11e38c 100644 --- a/arch/arm/mach-iop32x/Makefile.boot +++ b/arch/arm/mach-iop32x/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0xa0008000 + zreladdr-y += 0xa0008000 params_phys-y := 0xa0000100 initrd_phys-y := 0xa0800000 diff --git a/arch/arm/mach-iop33x/Makefile.boot b/arch/arm/mach-iop33x/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-iop33x/Makefile.boot +++ b/arch/arm/mach-iop33x/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-ixp2000/Makefile.boot b/arch/arm/mach-ixp2000/Makefile.boot index d84c5807a43d..9c7af91d93da 100644 --- a/arch/arm/mach-ixp2000/Makefile.boot +++ b/arch/arm/mach-ixp2000/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot index d5561ad15bad..44fb4a717c3f 100644 --- a/arch/arm/mach-ixp23xx/Makefile.boot +++ b/arch/arm/mach-ixp23xx/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 diff --git a/arch/arm/mach-ixp4xx/Makefile.boot b/arch/arm/mach-ixp4xx/Makefile.boot index d84c5807a43d..9c7af91d93da 100644 --- a/arch/arm/mach-ixp4xx/Makefile.boot +++ b/arch/arm/mach-ixp4xx/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 2131832ee6ba..f72a3a893c47 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -54,7 +54,7 @@ unsigned long ixp4xx_pci_reg_base = 0; * these transactions are atomic or we will end up * with corrupt data on the bus or in a driver. */ -static DEFINE_SPINLOCK(ixp4xx_pci_lock); +static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock); /* * Read from PCI config space @@ -62,10 +62,10 @@ static DEFINE_SPINLOCK(ixp4xx_pci_lock); static void crp_read(u32 ad_cbe, u32 *data) { unsigned long flags; - spin_lock_irqsave(&ixp4xx_pci_lock, flags); + raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags); *PCI_CRP_AD_CBE = ad_cbe; *data = *PCI_CRP_RDATA; - spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); + raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); } /* @@ -74,10 +74,10 @@ static void crp_read(u32 ad_cbe, u32 *data) static void crp_write(u32 ad_cbe, u32 data) { unsigned long flags; - spin_lock_irqsave(&ixp4xx_pci_lock, flags); + raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags); *PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe; *PCI_CRP_WDATA = data; - spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); + raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); } static inline int check_master_abort(void) @@ -101,7 +101,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32 cmd, u32* data) int retval = 0; int i; - spin_lock_irqsave(&ixp4xx_pci_lock, flags); + raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags); *PCI_NP_AD = addr; @@ -118,7 +118,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32 cmd, u32* data) if(check_master_abort()) retval = 1; - spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); + raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); return retval; } @@ -127,7 +127,7 @@ int ixp4xx_pci_read_no_errata(u32 addr, u32 cmd, u32* data) unsigned long flags; int retval = 0; - spin_lock_irqsave(&ixp4xx_pci_lock, flags); + raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags); *PCI_NP_AD = addr; @@ -140,7 +140,7 @@ int ixp4xx_pci_read_no_errata(u32 addr, u32 cmd, u32* data) if(check_master_abort()) retval = 1; - spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); + raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); return retval; } @@ -149,7 +149,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data) unsigned long flags; int retval = 0; - spin_lock_irqsave(&ixp4xx_pci_lock, flags); + raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags); *PCI_NP_AD = addr; @@ -162,7 +162,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data) if(check_master_abort()) retval = 1; - spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); + raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags); return retval; } @@ -397,7 +397,8 @@ void __init ixp4xx_pci_preinit(void) local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET); local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M); local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M); - local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M); + local_write_config(PCI_BASE_ADDRESS_3, 4, + PHYS_OFFSET + SZ_32M + SZ_16M); /* * Enable CSR window at 64 MiB to allow PCI masters diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h index 57b5410c31f4..ffb9d6afb89f 100644 --- a/arch/arm/mach-ixp4xx/include/mach/io.h +++ b/arch/arm/mach-ixp4xx/include/mach/io.h @@ -17,8 +17,6 @@ #include <mach/hardware.h> -#define IO_SPACE_LIMIT 0x0000ffff - extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data); extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-kirkwood/Makefile.boot +++ b/arch/arm/mach-kirkwood/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-ks8695/Makefile.boot b/arch/arm/mach-ks8695/Makefile.boot index 48eb2cb3ac77..c9b0bebcf237 100644 --- a/arch/arm/mach-ks8695/Makefile.boot +++ b/arch/arm/mach-ks8695/Makefile.boot @@ -3,6 +3,6 @@ # PARAMS_PHYS must be within 4MB of ZRELADDR # INITRD_PHYS must be in RAM - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot index b796b41ebf8f..2cfe0ee635c5 100644 --- a/arch/arm/mach-lpc32xx/Makefile.boot +++ b/arch/arm/mach-lpc32xx/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x80008000 + zreladdr-y += 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x82000000 diff --git a/arch/arm/mach-mmp/Makefile.boot b/arch/arm/mach-mmp/Makefile.boot index 574a4aa8321a..5edf03e2beed 100644 --- a/arch/arm/mach-mmp/Makefile.boot +++ b/arch/arm/mach-mmp/Makefile.boot @@ -1 +1 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 06b5fa853c93..49c5d6d843d6 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -160,7 +160,7 @@ static struct mtd_partition aspenite_nand_partitions[] = { }, { .name = "filesystem", .offset = MTDPART_OFS_APPEND, - .size = SZ_48M, + .size = SZ_32M + SZ_16M, .mask_flags = 0, } }; diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7f005843a707..7fb568d2845b 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -35,6 +35,13 @@ extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +struct pxa168_usb_pdata { + /* If NULL, default phy init routine for PXA168 would be called */ + int (*phy_init)(void __iomem *usb_phy_reg_base); +}; +/* pdata can be NULL */ +int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata); + static inline int pxa168_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 0156f535dae7..b2b280c517dd 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -25,6 +25,9 @@ #include <mach/dma.h> #include <mach/devices.h> #include <mach/mfp.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <mach/pxa168.h> #include "common.h" #include "clock.h" @@ -83,6 +86,7 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000); static APMU_CLK(nand, NAND, 0x19b, 156000000); static APMU_CLK(lcd, LCD, 0x7f, 312000000); static APMU_CLK(eth, ETH, 0x09, 0); +static APMU_CLK(usb, USB, 0x12, 0); /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { @@ -104,6 +108,7 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), + INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"), }; static int __init pxa168_init(void) @@ -169,3 +174,44 @@ PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61); PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8); PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c); PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff); + +struct resource pxa168_usb_host_resources[] = { + /* USB Host conroller register base */ + [0] = { + .start = 0xd4209000, + .end = 0xd4209000 + 0x200, + .flags = IORESOURCE_MEM, + .name = "pxa168-usb-host", + }, + /* USB PHY register base */ + [1] = { + .start = 0xd4206000, + .end = 0xd4206000 + 0xff, + .flags = IORESOURCE_MEM, + .name = "pxa168-usb-phy", + }, + [2] = { + .start = IRQ_PXA168_USB2, + .end = IRQ_PXA168_USB2, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32); +struct platform_device pxa168_device_usb_host = { + .name = "pxa168-ehci", + .id = -1, + .dev = { + .dma_mask = &pxa168_usb_host_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + + .num_resources = ARRAY_SIZE(pxa168_usb_host_resources), + .resource = pxa168_usb_host_resources, +}; + +int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata) +{ + pxa168_device_usb_host.dev.platform_data = pdata; + return platform_device_register(&pxa168_device_usb_host); +} diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index 6bd37a27e5fc..176515a76989 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -93,7 +93,7 @@ static struct mtd_partition ttc_dkb_onenand_partitions[] = { }, { .name = "filesystem", .offset = MTDPART_OFS_APPEND, - .size = SZ_48M, + .size = SZ_32M + SZ_16M, .mask_flags = 0, } }; diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot index 24dfbf8c07c4..9b803a578b4d 100644 --- a/arch/arm/mach-msm/Makefile.boot +++ b/arch/arm/mach-msm/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x10008000 + zreladdr-y += 0x10008000 params_phys-y := 0x10000100 initrd_phys-y := 0x10800000 diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index 18a3c97bc863..f81ef1f9d46f 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -78,8 +78,8 @@ static void __init halibut_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init halibut_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static void __init halibut_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks=1; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c index 7a9a03eb189c..1df15aa3c66d 100644 --- a/arch/arm/mach-msm/board-mahimahi.c +++ b/arch/arm/mach-msm/board-mahimahi.c @@ -53,8 +53,8 @@ static void __init mahimahi_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init mahimahi_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static void __init mahimahi_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks = 2; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index b7a84966b711..d1e4cc83b1e6 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -24,6 +24,7 @@ #include <linux/smsc911x.h> #include <linux/usb/msm_hsusb.h> #include <linux/clkdev.h> +#include <linux/memblock.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -42,6 +43,21 @@ extern struct sys_timer msm_timer; +static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tag, + char **cmdline, struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) { + tag->u.mem.start = 0; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm7x30_reserve(void) +{ + memblock_remove(0x0, SZ_2M); +} + static int hsusb_phy_init_seq[] = { 0x30, 0x32, /* Enable and set Pre-Emphasis Depth to 20% */ 0x02, 0x36, /* Disable CDR Auto Reset feature */ @@ -107,6 +123,8 @@ static void __init msm7x30_map_io(void) MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF") .boot_params = PLAT_PHYS_OFFSET + 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -115,6 +133,8 @@ MACHINE_END MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") .boot_params = PLAT_PHYS_OFFSET + 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -123,6 +143,8 @@ MACHINE_END MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") .boot_params = PLAT_PHYS_OFFSET + 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c index 35c7ceeb3f29..b04468e7d00e 100644 --- a/arch/arm/mach-msm/board-msm8960.c +++ b/arch/arm/mach-msm/board-msm8960.c @@ -20,16 +20,34 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/clkdev.h> +#include <linux/memblock.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> +#include <asm/setup.h> #include <mach/board.h> #include <mach/msm_iomap.h> #include "devices.h" +static void __init msm8960_fixup(struct machine_desc *desc, struct tag *tag, + char **cmdline, struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && + tag->u.mem.start == 0x40200000) { + tag->u.mem.start = 0x40000000; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm8960_reserve(void) +{ + memblock_remove(0x40000000, SZ_2M); +} + static void __init msm8960_map_io(void) { msm_map_msm8960_io(); @@ -76,6 +94,8 @@ static void __init msm8960_rumi3_init(void) } MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR") + .fixup = msm8960_fixup, + .reserve = msm8960_reserve, .map_io = msm8960_map_io, .init_irq = msm8960_init_irq, .timer = &msm_timer, @@ -83,6 +103,8 @@ MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR") MACHINE_END MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3") + .fixup = msm8960_fixup, + .reserve = msm8960_reserve, .map_io = msm8960_map_io, .init_irq = msm8960_init_irq, .timer = &msm_timer, diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index 1163b6fd05d2..9221f54778be 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -20,14 +20,31 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/memblock.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> +#include <asm/setup.h> #include <mach/board.h> #include <mach/msm_iomap.h> +static void __init msm8x60_fixup(struct machine_desc *desc, struct tag *tag, + char **cmdline, struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && + tag->u.mem.start == 0x40200000) { + tag->u.mem.start = 0x40000000; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm8x60_reserve(void) +{ + memblock_remove(0x40000000, SZ_2M); +} static void __init msm8x60_map_io(void) { @@ -65,6 +82,8 @@ static void __init msm8x60_init(void) } MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, .map_io = msm8x60_map_io, .init_irq = msm8x60_init_irq, .init_machine = msm8x60_init, @@ -72,6 +91,8 @@ MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3") MACHINE_END MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, .map_io = msm8x60_map_io, .init_irq = msm8x60_init_irq, .init_machine = msm8x60_init, @@ -79,6 +100,8 @@ MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF") MACHINE_END MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, .map_io = msm8x60_map_io, .init_irq = msm8x60_init_irq, .init_machine = msm8x60_init, @@ -86,6 +109,8 @@ MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR") MACHINE_END MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, .map_io = msm8x60_map_io, .init_irq = msm8x60_init_irq, .init_machine = msm8x60_init, diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c index 68f930f07d77..c6e043c896aa 100644 --- a/arch/arm/mach-msm/board-sapphire.c +++ b/arch/arm/mach-msm/board-sapphire.c @@ -77,8 +77,8 @@ static struct map_desc sapphire_io_desc[] __initdata = { } }; -static void __init sapphire_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static void __init sapphire_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { int smi_sz = parse_tag_smi((const struct tag *)tags); diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index 814386772c66..7acd2021ada9 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -48,8 +48,8 @@ static void __init trout_init_irq(void) msm_init_irq(); } -static void __init trout_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static void __init trout_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks = 1; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index 22a537669624..d9145dfc2a3b 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c @@ -18,7 +18,7 @@ #include <linux/list.h> #include <linux/err.h> #include <linux/spinlock.h> -#include <linux/pm_qos_params.h> +#include <linux/pm_qos.h> #include <linux/mutex.h> #include <linux/clk.h> #include <linux/string.h> diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index f2f8d299ba95..58d5e7eec431 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -22,11 +22,11 @@ #elif defined(CONFIG_ARCH_QSD8X50) #define PLAT_PHYS_OFFSET UL(0x20000000) #elif defined(CONFIG_ARCH_MSM7X30) -#define PLAT_PHYS_OFFSET UL(0x00200000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_ARCH_MSM8X60) -#define PLAT_PHYS_OFFSET UL(0x40200000) +#define PLAT_PHYS_OFFSET UL(0x40000000) #elif defined(CONFIG_ARCH_MSM8960) -#define PLAT_PHYS_OFFSET UL(0x40200000) +#define PLAT_PHYS_OFFSET UL(0x40000000) #else #define PLAT_PHYS_OFFSET UL(0x10000000) #endif diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 1a1af9e56250..727659520912 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -156,6 +156,12 @@ void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + for (i = 0; i < ncores; i++) set_cpu_possible(i, true); diff --git a/arch/arm/mach-mv78xx0/Makefile.boot b/arch/arm/mach-mv78xx0/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-mv78xx0/Makefile.boot +++ b/arch/arm/mach-mv78xx0/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot index e928be1b6757..ca207ca305ec 100644 --- a/arch/arm/mach-mx5/Makefile.boot +++ b/arch/arm/mach-mx5/Makefile.boot @@ -1,9 +1,9 @@ - zreladdr-$(CONFIG_ARCH_MX50) := 0x70008000 + zreladdr-$(CONFIG_ARCH_MX50) += 0x70008000 params_phys-$(CONFIG_ARCH_MX50) := 0x70000100 initrd_phys-$(CONFIG_ARCH_MX50) := 0x70800000 - zreladdr-$(CONFIG_ARCH_MX51) := 0x90008000 + zreladdr-$(CONFIG_ARCH_MX51) += 0x90008000 params_phys-$(CONFIG_ARCH_MX51) := 0x90000100 initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000 - zreladdr-$(CONFIG_ARCH_MX53) := 0x70008000 + zreladdr-$(CONFIG_ARCH_MX53) += 0x70008000 params_phys-$(CONFIG_ARCH_MX53) := 0x70000100 initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000 diff --git a/arch/arm/mach-mxs/Makefile.boot b/arch/arm/mach-mxs/Makefile.boot index eb541e0291da..07b11fe6453f 100644 --- a/arch/arm/mach-mxs/Makefile.boot +++ b/arch/arm/mach-mxs/Makefile.boot @@ -1 +1 @@ -zreladdr-y := 0x40008000 +zreladdr-y += 0x40008000 diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot index b81cf6aff0ac..534a4d27055e 100644 --- a/arch/arm/mach-netx/Makefile.boot +++ b/arch/arm/mach-netx/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x80008000 + zreladdr-y += 0x80008000 diff --git a/arch/arm/mach-nomadik/Makefile.boot b/arch/arm/mach-nomadik/Makefile.boot index c7e75acfe6c9..ff0a4b5b0a82 100644 --- a/arch/arm/mach-nomadik/Makefile.boot +++ b/arch/arm/mach-nomadik/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-nuc93x/Makefile.boot b/arch/arm/mach-nuc93x/Makefile.boot index a057b546b6e5..6c3d421c2d11 100644 --- a/arch/arm/mach-nuc93x/Makefile.boot +++ b/arch/arm/mach-nuc93x/Makefile.boot @@ -1,3 +1,3 @@ -zreladdr-y := 0x00008000 +zreladdr-y += 0x00008000 params_phys-y := 0x00000100 diff --git a/arch/arm/mach-nuc93x/time.c b/arch/arm/mach-nuc93x/time.c index 2f90f9dc6e30..f9807c029ec5 100644 --- a/arch/arm/mach-nuc93x/time.c +++ b/arch/arm/mach-nuc93x/time.c @@ -82,7 +82,7 @@ static void nuc93x_timer_setup(void) timer0_load = (rate / TICKS_PER_SEC); __raw_writel(timer0_load, REG_TICR0); - val |= (PERIOD | COUNTEN | INTEN | PRESCALE);; + val |= (PERIOD | COUNTEN | INTEN | PRESCALE); __raw_writel(val, REG_TCSR0); } diff --git a/arch/arm/mach-omap1/Makefile.boot b/arch/arm/mach-omap1/Makefile.boot index 292d56c5a888..13bda8dbd604 100644 --- a/arch/arm/mach-omap1/Makefile.boot +++ b/arch/arm/mach-omap1/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x10008000 + zreladdr-y += 0x10008000 params_phys-y := 0x10000100 initrd_phys-y := 0x10800000 diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c index 943072d5a1d5..7868e75ad077 100644 --- a/arch/arm/mach-omap1/pm_bus.c +++ b/arch/arm/mach-omap1/pm_bus.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/io.h> #include <linux/pm_runtime.h> +#include <linux/pm_clock.h> #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/clk.h> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 57b66d590c52..89bfb49389f2 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -36,6 +36,7 @@ config ARCH_OMAP3 select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 select ARCH_HAS_OPP select PM_OPP if PM + select ARM_CPU_SUSPEND if PM config ARCH_OMAP4 bool "TI OMAP4" @@ -50,6 +51,7 @@ config ARCH_OMAP4 select ARCH_HAS_OPP select PM_OPP if PM select USB_ARCH_HAS_EHCI + select ARM_CPU_SUSPEND if PM comment "OMAP Core Type" depends on ARCH_OMAP2 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f34336560437..7317a2b39dd1 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -242,14 +242,11 @@ obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \ obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ hsmmc.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \ - hsmmc.o \ - omap_phy_internal.o + hsmmc.o obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \ - hsmmc.o \ - omap_phy_internal.o + hsmmc.o -obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \ - omap_phy_internal.o \ +obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o @@ -260,6 +257,8 @@ obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o obj-y += $(usbfs-m) $(usbfs-y) obj-y += usb-musb.o +obj-y += omap_phy_internal.o + obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o obj-y += usb-host.o diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot index 565aff7f37a9..b03e562acc60 100644 --- a/arch/arm/mach-omap2/Makefile.boot +++ b/arch/arm/mach-omap2/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x80008000 + zreladdr-y += 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x80800000 diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 2028464cf5b9..f79b7d2a8ed4 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -193,7 +193,8 @@ static int __init omap2430_i2c_init(void) { omap_register_i2c_bus(1, 100, sdp2430_i2c1_boardinfo, ARRAY_SIZE(sdp2430_i2c1_boardinfo)); - omap2_pmic_init("twl4030", &sdp2430_twldata); + omap_pmic_init(2, 100, "twl4030", INT_24XX_SYS_NIRQ, + &sdp2430_twldata); return 0; } diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index ffd55b1c4396..b9b844683147 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3078,6 +3078,7 @@ static struct clk gpt12_fck = { .name = "gpt12_fck", .ops = &clkops_null, .parent = &secure_32k_fck, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -3085,6 +3086,7 @@ static struct clk wdt1_fck = { .name = "wdt1_fck", .ops = &clkops_null, .parent = &secure_32k_fck, + .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 2af0e3f00ce1..c0b6fbda3408 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3376,10 +3376,18 @@ int __init omap4xxx_clk_init(void) } else if (cpu_is_omap446x()) { cpu_mask = RATE_IN_4460; cpu_clkflg = CK_446X; + } else { + return 0; } clk_init(&omap2_clk_functions); - omap2_clk_disable_clkdm_control(); + + /* + * Must stay commented until all OMAP SoC drivers are + * converted to runtime PM, or drivers may start crashing + * + * omap2_clk_disable_clkdm_control(); + */ for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks); c++) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index ab7db083f97f..8f0890685d7b 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -747,6 +747,7 @@ int clkdm_wakeup(struct clockdomain *clkdm) spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; ret = arch_clkdm->clkdm_wakeup(clkdm); + ret |= pwrdm_state_switch(clkdm->pwrdm.ptr); spin_unlock_irqrestore(&clkdm->lock, flags); return ret; } @@ -818,6 +819,7 @@ void clkdm_deny_idle(struct clockdomain *clkdm) spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; arch_clkdm->clkdm_deny_idle(clkdm); + pwrdm_state_switch(clkdm->pwrdm.ptr); spin_unlock_irqrestore(&clkdm->lock, flags); } diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index a9b45c76e1d3..097a42d81e59 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -137,8 +137,7 @@ static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot, */ reg = omap4_ctrl_pad_readl(control_pbias_offset); reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK | - OMAP4_MMC1_PWRDNZ_MASK | - OMAP4_USBC1_ICUSB_PWRDNZ_MASK); + OMAP4_MMC1_PWRDNZ_MASK); omap4_ctrl_pad_writel(reg, control_pbias_offset); } @@ -156,8 +155,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, else reg |= OMAP4_MMC1_PBIASLITE_VMODE_MASK; reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK | - OMAP4_MMC1_PWRDNZ_MASK | - OMAP4_USBC1_ICUSB_PWRDNZ_MASK); + OMAP4_MMC1_PWRDNZ_MASK); omap4_ctrl_pad_writel(reg, control_pbias_offset); timeout = jiffies + msecs_to_jiffies(5); @@ -171,16 +169,14 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) { pr_err("Pbias Voltage is not same as LDO\n"); /* Caution : On VMODE_ERROR Power Down MMC IO */ - reg &= ~(OMAP4_MMC1_PWRDNZ_MASK | - OMAP4_USBC1_ICUSB_PWRDNZ_MASK); + reg &= ~(OMAP4_MMC1_PWRDNZ_MASK); omap4_ctrl_pad_writel(reg, control_pbias_offset); } } else { reg = omap4_ctrl_pad_readl(control_pbias_offset); reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK | OMAP4_MMC1_PWRDNZ_MASK | - OMAP4_MMC1_PBIASLITE_VMODE_MASK | - OMAP4_USBC1_ICUSB_PWRDNZ_MASK); + OMAP4_MMC1_PBIASLITE_VMODE_MASK); omap4_ctrl_pad_writel(reg, control_pbias_offset); } } diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index ce65e9329c7b..889464dc7b2d 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -109,12 +109,10 @@ void __init smp_init_cpus(void) ncores = scu_get_core_count(scu_base); /* sanity check */ - if (ncores > NR_CPUS) { - printk(KERN_WARNING - "OMAP4: no. of cores (%d) greater than configured " - "maximum of %d - clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 16743c7d6e8e..408193d8e044 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -192,6 +192,7 @@ static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = { .pa_end = OMAP243X_HS_BASE + SZ_4K - 1, .flags = ADDR_TYPE_RT }, + { } }; /* l4_core ->usbhsotg interface */ diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 3feb35911a32..472bf22d5e84 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -130,7 +130,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) } else { hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); - pwrdm_wait_transition(pwrdm); sleep_switch = FORCEWAKEUP_SWITCH; } } @@ -156,7 +155,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) return ret; } - pwrdm_wait_transition(pwrdm); pwrdm_state_switch(pwrdm); err: return ret; diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 9af08473bf10..ef71fdd40fc4 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -195,28 +195,35 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) /** * pwrdm_init - set up the powerdomain layer - * @pwrdm_list: array of struct powerdomain pointers to register + * @pwrdms: array of struct powerdomain pointers to register * @custom_funcs: func pointers for arch specific implementations * - * Loop through the array of powerdomains @pwrdm_list, registering all - * that are available on the current CPU. If pwrdm_list is supplied - * and not null, all of the referenced powerdomains will be - * registered. No return value. XXX pwrdm_list is not really a - * "list"; it is an array. Rename appropriately. + * Loop through the array of powerdomains @pwrdms, registering all + * that are available on the current CPU. Also, program all + * powerdomain target state as ON; this is to prevent domains from + * hitting low power states (if bootloader has target states set to + * something other than ON) and potentially even losing context while + * PM is not fully initialized. The PM late init code can then program + * the desired target state for all the power domains. No return + * value. */ -void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs) +void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs) { struct powerdomain **p = NULL; + struct powerdomain *temp_p; if (!custom_funcs) WARN(1, "powerdomain: No custom pwrdm functions registered\n"); else arch_pwrdm = custom_funcs; - if (pwrdm_list) { - for (p = pwrdm_list; *p; p++) + if (pwrdms) { + for (p = pwrdms; *p; p++) _pwrdm_register(*p); } + + list_for_each_entry(temp_p, &pwrdm_list, node) + pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON); } /** diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 34c01a7de810..f49804f181d4 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -247,7 +247,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr) * driver register and sr device intializtion API's. Only one call * will ultimately succeed. * - * Currently this function registers interrrupt handler for a particular SR + * Currently this function registers interrupt handler for a particular SR * if smartreflex class driver is already registered and has * requested for interrupts and the SR interrupt line in present. */ diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index a65145b02a55..19e4dac62a8c 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -137,9 +137,6 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) musb_plat.mode = board_data->mode; musb_plat.extvbus = board_data->extvbus; - if (cpu_is_omap44xx()) - omap4430_phy_init(dev); - if (cpu_is_omap3517() || cpu_is_omap3505()) { oh_name = "am35x_otg_hs"; name = "musb-am35x"; diff --git a/arch/arm/mach-orion5x/Makefile.boot b/arch/arm/mach-orion5x/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-orion5x/Makefile.boot +++ b/arch/arm/mach-orion5x/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 0ab531d047fc..22ace0bf2f92 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -308,8 +308,8 @@ void __init orion5x_init(void) * Many orion-based systems have buggy bootloader implementations. * This is a common fixup for bogus memory tags. */ -void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t, - char **from, struct meminfo *meminfo) +void __init tag_fixup_mem32(struct tag *t, char **from, + struct meminfo *meminfo) { for (; t->hdr.size; t = tag_next(t)) if (t->hdr.tag == ATAG_MEM && diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index 3e5499dda49a..909489f4d23e 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -53,11 +53,9 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -struct machine_desc; struct meminfo; struct tag; -extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *, - char **, struct meminfo *); +extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *); #endif diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index a6eddae82a0b..c105556a0ee1 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -77,7 +77,7 @@ static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) /* * Check for devices with hard-wired IRQs. */ - irq = orion5x_pci_map_irq(const dev, slot, pin); + irq = orion5x_pci_map_irq(dev, slot, pin); if (irq != -1) return irq; diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c index 28b8760ab9fa..bc4a920e26ee 100644 --- a/arch/arm/mach-orion5x/pci.c +++ b/arch/arm/mach-orion5x/pci.c @@ -14,6 +14,7 @@ #include <linux/pci.h> #include <linux/slab.h> #include <linux/mbus.h> +#include <video/vga.h> #include <asm/irq.h> #include <asm/mach/pci.h> #include <plat/pcie.h> diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot index 44c7117e20dd..9fa19baa7f2e 100644 --- a/arch/arm/mach-pnx4008/Makefile.boot +++ b/arch/arm/mach-pnx4008/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x80008000 + zreladdr-y += 0x80008000 params_phys-y := 0x80000100 initrd_phys-y := 0x80800000 diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot index d023db3ae4ff..c77a4883a4ee 100644 --- a/arch/arm/mach-prima2/Makefile.boot +++ b/arch/arm/mach-prima2/Makefile.boot @@ -1,3 +1,3 @@ -zreladdr-y := 0x00008000 +zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c index f9a2aaf63f71..615a4e75ceab 100644 --- a/arch/arm/mach-prima2/clock.c +++ b/arch/arm/mach-prima2/clock.c @@ -481,6 +481,7 @@ static void __init sirfsoc_clk_init(void) static struct of_device_id clkc_ids[] = { { .compatible = "sirf,prima2-clkc" }, + {}, }; void __init sirfsoc_of_clk_init(void) diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c index c3404cbb6ff7..7af254d046ba 100644 --- a/arch/arm/mach-prima2/irq.c +++ b/arch/arm/mach-prima2/irq.c @@ -51,6 +51,7 @@ static __init void sirfsoc_irq_init(void) static struct of_device_id intc_ids[] = { { .compatible = "sirf,prima2-intc" }, + {}, }; void __init sirfsoc_of_irq_init(void) diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c index d074786e83d4..492cfa8d2610 100644 --- a/arch/arm/mach-prima2/rstc.c +++ b/arch/arm/mach-prima2/rstc.c @@ -19,6 +19,7 @@ static DEFINE_MUTEX(rstc_lock); static struct of_device_id rstc_ids[] = { { .compatible = "sirf,prima2-rstc" }, + {}, }; static int __init sirfsoc_of_rstc_init(void) diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c index 44027f34a88a..ed7ec48d11da 100644 --- a/arch/arm/mach-prima2/timer.c +++ b/arch/arm/mach-prima2/timer.c @@ -190,6 +190,7 @@ static void __init sirfsoc_timer_init(void) static struct of_device_id timer_ids[] = { { .compatible = "sirf,prima2-tick" }, + {}, }; static void __init sirfsoc_of_timer_map(void) diff --git a/arch/arm/mach-pxa/Makefile.boot b/arch/arm/mach-pxa/Makefile.boot index 1ead67178eca..2c1ae92f2106 100644 --- a/arch/arm/mach-pxa/Makefile.boot +++ b/arch/arm/mach-pxa/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0xa0008000 + zreladdr-y += 0xa0008000 diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index b6a51340270b..d940e8a72270 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -839,8 +839,8 @@ static void __init cm_x300_init(void) cm_x300_init_bl(); } -static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static void __init cm_x300_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { /* Make sure that mi->bank[0].start = PHYS_ADDR */ for (; tags->hdr.size; tags = tag_next(tags)) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 185a37cad254..3e9483b06053 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -705,8 +705,8 @@ static void __init corgi_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init fixup_corgi(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init fixup_corgi(struct tag *tags, char **cmdline, + struct meminfo *mi) { sharpsl_save_param(); mi->nr_banks=1; diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index b4599ec9d619..e4a1f4dc89ff 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -41,8 +41,7 @@ #include "clock.h" /* Only e800 has 128MB RAM */ -void __init eseries_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi) { mi->nr_banks=1; mi->bank[0].start = 0xa0000000; diff --git a/arch/arm/mach-pxa/eseries.h b/arch/arm/mach-pxa/eseries.h index 5930f5e2a123..be921965e91a 100644 --- a/arch/arm/mach-pxa/eseries.h +++ b/arch/arm/mach-pxa/eseries.h @@ -1,5 +1,4 @@ -void __init eseries_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi); +void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi); extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info; extern struct pxaficp_platform_data e7xx_ficp_platform_data; diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index b09e848eb6c6..ca6075717824 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -19,6 +19,8 @@ #include <linux/io.h> #include <linux/irq.h> +#include <asm/exception.h> + #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/gpio.h> diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index a113ea9ab4ab..948ce3e729fa 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -454,8 +454,8 @@ static void __init poodle_init(void) poodle_init_spi(); } -static void __init fixup_poodle(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init fixup_poodle(struct tag *tags, char **cmdline, + struct meminfo *mi) { sharpsl_save_param(); mi->nr_banks=1; diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index df4356e8acae..72001ec6e7b5 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -540,7 +540,7 @@ static struct mtd_partition saar_onenand_partitions[] = { }, { .name = "filesystem", .offset = MTDPART_OFS_APPEND, - .size = SZ_48M, + .size = SZ_32M + SZ_16M, .mask_flags = 0, } }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 438c7b5e451f..d8dec9113aad 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -970,8 +970,8 @@ static void __init spitz_init(void) spitz_i2c_init(); } -static void __init spitz_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init spitz_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { sharpsl_save_param(); mi->nr_banks = 1; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 9f69a2682693..402b0c96613b 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -960,8 +960,8 @@ static void __init tosa_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init fixup_tosa(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init fixup_tosa(struct tag *tags, char **cmdline, + struct meminfo *mi) { sharpsl_save_param(); mi->nr_banks=1; diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c index acc600f5e72f..937c42845df9 100644 --- a/arch/arm/mach-pxa/xcep.c +++ b/arch/arm/mach-pxa/xcep.c @@ -142,8 +142,7 @@ static struct platform_device *devices[] __initdata = { /* We have to state that there are HWMON devices on the I2C bus on XCEP. * Drivers for HWMON verify capabilities of the adapter when loading and - * refuse to attach if the adapter doesn't support HWMON class of devices. - * See also Documentation/i2c/porting-clients. */ + * refuse to attach if the adapter doesn't support HWMON class of devices. */ static struct i2c_pxa_platform_data xcep_i2c_platform_data = { .class = I2C_CLASS_HWMON }; diff --git a/arch/arm/mach-realview/Makefile.boot b/arch/arm/mach-realview/Makefile.boot index d97e003d3df4..d2c3d788f688 100644 --- a/arch/arm/mach-realview/Makefile.boot +++ b/arch/arm/mach-realview/Makefile.boot @@ -1,9 +1,9 @@ ifeq ($(CONFIG_REALVIEW_HIGH_PHYS_OFFSET),y) - zreladdr-y := 0x70008000 + zreladdr-y += 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70800000 else - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 endif diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 5c23450d2d1d..d5ed5d4f77d6 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -517,8 +517,7 @@ void __init realview_timer_init(unsigned int timer_irq) /* * Setup the memory banks. */ -void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from, - struct meminfo *meminfo) +void realview_fixup(struct tag *tags, char **from, struct meminfo *meminfo) { /* * Most RealView platforms have 512MB contiguous RAM at 0x70000000. diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 5c83d1e87a03..47259c89a75e 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -63,8 +63,8 @@ extern int realview_flash_register(struct resource *res, u32 num); extern int realview_eth_register(const char *name, struct resource *res); extern int realview_usb_register(struct resource *res); extern void realview_init_early(void); -extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags, - char **from, struct meminfo *meminfo); +extern void realview_fixup(struct tag *tags, char **from, + struct meminfo *meminfo); extern void (*realview_reset)(char); #endif diff --git a/arch/arm/mach-realview/include/mach/board-pb1176.h b/arch/arm/mach-realview/include/mach/board-pb1176.h index 002ab5d8c11c..2a15fef94730 100644 --- a/arch/arm/mach-realview/include/mach/board-pb1176.h +++ b/arch/arm/mach-realview/include/mach/board-pb1176.h @@ -70,6 +70,7 @@ #define REALVIEW_DC1176_GIC_CPU_BASE 0x10120000 /* GIC CPU interface, on devchip */ #define REALVIEW_DC1176_GIC_DIST_BASE 0x10121000 /* GIC distributor, on devchip */ +#define REALVIEW_DC1176_ROM_BASE 0x10200000 /* 16KiB NRAM preudo-ROM, on devchip */ #define REALVIEW_PB1176_GIC_CPU_BASE 0x10040000 /* GIC CPU interface, on FPGA */ #define REALVIEW_PB1176_GIC_DIST_BASE 0x10041000 /* GIC distributor, on FPGA */ #define REALVIEW_PB1176_L220_BASE 0x10110000 /* L220 registers */ diff --git a/arch/arm/mach-realview/include/mach/system.h b/arch/arm/mach-realview/include/mach/system.h index a30f2e3ec178..6657ff231161 100644 --- a/arch/arm/mach-realview/include/mach/system.h +++ b/arch/arm/mach-realview/include/mach/system.h @@ -44,6 +44,7 @@ static inline void arch_reset(char mode, const char *cmd) */ if (realview_reset) realview_reset(mode); + dsb(); } #endif diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 4ae943bafa92..e83c654a58d0 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -52,12 +52,10 @@ void __init smp_init_cpus(void) ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ - if (ncores > NR_CPUS) { - printk(KERN_WARNING - "Realview: no. of cores (%d) greater than configured " - "maximum of %d - clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index ad5671acb66a..865d440fcf58 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -26,6 +26,8 @@ #include <linux/amba/pl061.h> #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/partitions.h> #include <linux/io.h> #include <mach/hardware.h> @@ -204,22 +206,48 @@ static struct amba_device *amba_devs[] __initdata = { * RealView PB1176 platform devices */ static struct resource realview_pb1176_flash_resources[] = { - [0] = { + { .start = REALVIEW_PB1176_FLASH_BASE, .end = REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1, .flags = IORESOURCE_MEM, }, - [1] = { +#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH + { .start = REALVIEW_PB1176_SEC_FLASH_BASE, .end = REALVIEW_PB1176_SEC_FLASH_BASE + REALVIEW_PB1176_SEC_FLASH_SIZE - 1, .flags = IORESOURCE_MEM, }, -}; -#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH -#define PB1176_FLASH_BLOCKS 2 -#else -#define PB1176_FLASH_BLOCKS 1 #endif +}; + +static struct physmap_flash_data pb1176_rom_pdata = { + .probe_type = "map_rom", + .width = 4, + .nr_parts = 0, +}; + +static struct resource pb1176_rom_resources[] = { + /* + * This exposes the PB1176 DevChip ROM as an MTD ROM mapping. + * The reference manual states that this is actually a pseudo-ROM + * programmed in NVRAM. + */ + { + .start = REALVIEW_DC1176_ROM_BASE, + .end = REALVIEW_DC1176_ROM_BASE + SZ_16K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device pb1176_rom_device = { + .name = "physmap-flash", + .id = -1, + .num_resources = ARRAY_SIZE(pb1176_rom_resources), + .resource = pb1176_rom_resources, + .dev = { + .platform_data = &pb1176_rom_pdata, + }, +}; static struct resource realview_pb1176_smsc911x_resources[] = { [0] = { @@ -316,8 +344,7 @@ static void realview_pb1176_reset(char mode) __raw_writel(REALVIEW_PB1176_SYS_SOFT_RESET, reset_ctrl); } -static void realview_pb1176_fixup(struct machine_desc *mdesc, - struct tag *tags, char **from, +static void realview_pb1176_fixup(struct tag *tags, char **from, struct meminfo *meminfo) { /* @@ -338,7 +365,8 @@ static void __init realview_pb1176_init(void) #endif realview_flash_register(realview_pb1176_flash_resources, - PB1176_FLASH_BLOCKS); + ARRAY_SIZE(realview_pb1176_flash_resources)); + platform_device_register(&pb1176_rom_device); realview_eth_register(NULL, realview_pb1176_smsc911x_resources); platform_device_register(&realview_i2c_device); realview_usb_register(realview_pb1176_isp1761_resources); diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 363b0ab56150..3e1eb2eb8132 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -319,8 +319,8 @@ static struct sys_timer realview_pbx_timer = { .init = realview_pbx_timer_init, }; -static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags, - char **from, struct meminfo *meminfo) +static void realview_pbx_fixup(struct tag *tags, char **from, + struct meminfo *meminfo) { #ifdef CONFIG_SPARSEMEM /* @@ -335,7 +335,7 @@ static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags, meminfo->bank[2].size = SZ_256M; meminfo->nr_banks = 3; #else - realview_fixup(mdesc, tags, from, meminfo); + realview_fixup(tags, from, meminfo); #endif } diff --git a/arch/arm/mach-rpc/Makefile.boot b/arch/arm/mach-rpc/Makefile.boot index 9c9e7685ec7c..ae2df0d7d037 100644 --- a/arch/arm/mach-rpc/Makefile.boot +++ b/arch/arm/mach-rpc/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x10008000 + zreladdr-y += 0x10008000 params_phys-y := 0x10000100 initrd_phys-y := 0x18000000 diff --git a/arch/arm/mach-rpc/include/mach/hardware.h b/arch/arm/mach-rpc/include/mach/hardware.h index dde6b3c0e299..050d63c74cc1 100644 --- a/arch/arm/mach-rpc/include/mach/hardware.h +++ b/arch/arm/mach-rpc/include/mach/hardware.h @@ -36,7 +36,7 @@ #define EASI_SIZE 0x08000000 /* EASI I/O */ #define EASI_START 0x08000000 -#define EASI_BASE 0xe5000000 +#define EASI_BASE IOMEM(0xe5000000) #define IO_START 0x03000000 /* I/O */ #define IO_SIZE 0x01000000 @@ -51,21 +51,20 @@ /* * IO Addresses */ -#define VIDC_BASE IOMEM(0xe0400000) -#define EXPMASK_BASE 0xe0360000 -#define IOMD_BASE IOMEM(0xe0200000) -#define IOC_BASE IOMEM(0xe0200000) -#define PCIO_BASE IOMEM(0xe0010000) -#define FLOPPYDMA_BASE IOMEM(0xe002a000) +#define ECARD_EASI_BASE (EASI_BASE) +#define VIDC_BASE (IO_BASE + 0x00400000) +#define EXPMASK_BASE (IO_BASE + 0x00360000) +#define ECARD_IOC4_BASE (IO_BASE + 0x00270000) +#define ECARD_IOC_BASE (IO_BASE + 0x00240000) +#define IOMD_BASE (IO_BASE + 0x00200000) +#define IOC_BASE (IO_BASE + 0x00200000) +#define ECARD_MEMC8_BASE (IO_BASE + 0x0002b000) +#define FLOPPYDMA_BASE (IO_BASE + 0x0002a000) +#define PCIO_BASE (IO_BASE + 0x00010000) +#define ECARD_MEMC_BASE (IO_BASE + 0x00000000) #define vidc_writel(val) __raw_writel(val, VIDC_BASE) -#define IO_EC_EASI_BASE 0x81400000 -#define IO_EC_IOC4_BASE 0x8009c000 -#define IO_EC_IOC_BASE 0x80090000 -#define IO_EC_MEMC8_BASE 0x8000ac00 -#define IO_EC_MEMC_BASE 0x80000000 - #define NETSLOT_BASE 0x0302b000 #define NETSLOT_SIZE 0x00001000 diff --git a/arch/arm/mach-rpc/include/mach/io.h b/arch/arm/mach-rpc/include/mach/io.h index 20da7f486e51..695f4ed2e11b 100644 --- a/arch/arm/mach-rpc/include/mach/io.h +++ b/arch/arm/mach-rpc/include/mach/io.h @@ -15,195 +15,18 @@ #include <mach/hardware.h> -#define IO_SPACE_LIMIT 0xffffffff +#define IO_SPACE_LIMIT 0xffff /* - * We use two different types of addressing - PC style addresses, and ARM - * addresses. PC style accesses the PC hardware with the normal PC IO - * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ - * and are translated to the start of IO. Note that all addresses are - * shifted left! - */ -#define __PORT_PCIO(x) (!((x) & 0x80000000)) - -/* - * Dynamic IO functions. - */ -static inline void __outb (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "strb %1, [%0, %2, lsl #2] @ outb" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -static inline void __outw (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2] @ outw" - : "=&r" (temp) - : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -static inline void __outl (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2] @ outl" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ -static inline unsigned sz __in##fnsuffix (unsigned int port) \ -{ \ - unsigned long temp, value; \ - __asm__ __volatile__( \ - "tst %2, #0x80000000\n\t" \ - "mov %0, %4\n\t" \ - "addeq %0, %0, %3\n\t" \ - "ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \ - : "=&r" (temp), "=r" (value) \ - : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ - : "cc"); \ - return (unsigned sz)value; \ -} - -static inline void __iomem *__deprecated __ioaddr(unsigned int port) -{ - void __iomem *ret; - if (__PORT_PCIO(port)) - ret = PCIO_BASE; - else - ret = IO_BASE; - return ret + (port << 2); -} - -#define DECLARE_IO(sz,fnsuffix,instr) \ - DECLARE_DYN_IN(sz,fnsuffix,instr) - -DECLARE_IO(char,b,"b") -DECLARE_IO(short,w,"") -DECLARE_IO(int,l,"") - -#undef DECLARE_IO -#undef DECLARE_DYN_IN - -/* - * Constant address IO functions + * We need PC style IO addressing for: + * - floppy (at 0x3f2,0x3f4,0x3f5,0x3f7) + * - parport (at 0x278-0x27a, 0x27b-0x27f, 0x778-0x77a) + * - 8250 serial (only for compile) * - * These have to be macros for the 'J' constraint to work - - * +/-4096 immediate operand. + * These peripherals are found in an area of MMIO which looks very much + * like an ISA bus, but with registers at the low byte of each word. */ -#define __outbc(value,port) \ -({ \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "strb %0, [%1, %2] @ outbc" \ - : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "strb %0, [%1, %2] @ outbc" \ - : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inbc(port) \ -({ \ - unsigned char result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2] @ inbc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2] @ inbc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define __outwc(value,port) \ -({ \ - unsigned long __v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outwc" \ - : : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outwc" \ - : : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inwc(port) \ -({ \ - unsigned short result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inwc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inwc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result & 0xffff; \ -}) - -#define __outlc(value,port) \ -({ \ - unsigned long __v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outlc" \ - : : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "str %0, [%1, %2] @ outlc" \ - : : "r" (__v), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inlc(port) \ -({ \ - unsigned long result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inlc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2] @ inlc" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p)) -#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p)) -#define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p)) -#define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p)) -#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p)) -#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p)) - -/* the following macro is deprecated */ -#define ioaddr(port) ((unsigned long)__ioaddr((port))) - -#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l) -#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l) - -#define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l) -#define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l) +#define __io(a) (PCIO_BASE + ((a) << 2)) /* * 1:1 mapping for ioremapped regions. diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index 580b3c73d2c7..1e0e60d04622 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -74,7 +74,7 @@ static struct map_desc rpc_io_desc[] __initdata = { .length = IO_SIZE , .type = MT_DEVICE }, { /* EASI space */ - .virtual = EASI_BASE, + .virtual = (unsigned long)EASI_BASE, .pfn = __phys_to_pfn(EASI_START), .length = EASI_SIZE, .type = MT_DEVICE diff --git a/arch/arm/mach-s3c2410/Makefile.boot b/arch/arm/mach-s3c2410/Makefile.boot index 58c1dd7f8e1d..4457605ba04a 100644 --- a/arch/arm/mach-s3c2410/Makefile.boot +++ b/arch/arm/mach-s3c2410/Makefile.boot @@ -1,7 +1,7 @@ ifeq ($(CONFIG_PM_H1940),y) - zreladdr-y := 0x30108000 + zreladdr-y += 0x30108000 params_phys-y := 0x30100100 else - zreladdr-y := 0x30008000 + zreladdr-y += 0x30008000 params_phys-y := 0x30000100 endif diff --git a/arch/arm/mach-s3c2410/include/mach/io.h b/arch/arm/mach-s3c2410/include/mach/io.h index 9813dbf2ae4f..118749f37c4c 100644 --- a/arch/arm/mach-s3c2410/include/mach/io.h +++ b/arch/arm/mach-s3c2410/include/mach/io.h @@ -199,8 +199,6 @@ DECLARE_IO(int,l,"") #define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p)) #define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p)) #define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p)) -/* the following macro is deprecated */ -#define ioaddr(port) __ioaddr((port)) #define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l) #define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l) diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index f1d3bd8f6f17..343a540d86a9 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -170,7 +170,9 @@ int __init s3c2410_init(void) { printk("S3C2410: Initialising architecture\n"); +#ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); +#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); return sysdev_register(&s3c2410_sysdev); diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c index 834cfb61bcfe..3391713e0c92 100644 --- a/arch/arm/mach-s3c2412/mach-smdk2413.c +++ b/arch/arm/mach-s3c2412/mach-smdk2413.c @@ -92,8 +92,7 @@ static struct platform_device *smdk2413_devices[] __initdata = { &s3c_device_usbgadget, }; -static void __init smdk2413_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, +static void __init smdk2413_fixup(struct tag *tags, char **cmdline, struct meminfo *mi) { if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) { diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c index 83544ebe20ac..b6ed4573553a 100644 --- a/arch/arm/mach-s3c2412/mach-vstms.c +++ b/arch/arm/mach-s3c2412/mach-vstms.c @@ -129,9 +129,8 @@ static struct platform_device *vstms_devices[] __initdata = { &s3c_device_nand, }; -static void __init vstms_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, - struct meminfo *mi) +static void __init vstms_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) { mi->nr_banks=1; diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index ef0958d3e5c6..57a1e01e4e50 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c @@ -245,7 +245,9 @@ int __init s3c2412_init(void) { printk("S3C2412: Initialising architecture\n"); +#ifdef CONFIG_PM register_syscore_ops(&s3c2412_pm_syscore_ops); +#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); return sysdev_register(&s3c2412_sysdev); diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index 494ce913dc95..20b3fdfb3051 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -97,7 +97,9 @@ int __init s3c2416_init(void) s3c_fb_setname("s3c2443-fb"); +#ifdef CONFIG_PM register_syscore_ops(&s3c2416_pm_syscore_ops); +#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); return sysdev_register(&s3c2416_sysdev); diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c index ce99ff72838d..2270d3360216 100644 --- a/arch/arm/mach-s3c2440/s3c2440.c +++ b/arch/arm/mach-s3c2440/s3c2440.c @@ -55,7 +55,9 @@ int __init s3c2440_init(void) /* register suspend/resume handlers */ +#ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); +#endif register_syscore_ops(&s3c244x_pm_syscore_ops); register_syscore_ops(&s3c24xx_irq_syscore_ops); diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c index 9ad99f8016a1..6f2b65e6e068 100644 --- a/arch/arm/mach-s3c2440/s3c2442.c +++ b/arch/arm/mach-s3c2440/s3c2442.c @@ -169,7 +169,9 @@ int __init s3c2442_init(void) { printk("S3C2442: Initialising architecture\n"); +#ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); +#endif register_syscore_ops(&s3c244x_pm_syscore_ops); register_syscore_ops(&s3c24xx_irq_syscore_ops); diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index a1a7176675b9..38058af48972 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -128,7 +128,7 @@ static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) unsigned long clkcon0; clkcon0 = __raw_readl(S3C2443_CLKDIV0); - clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; + clkcon0 &= ~S3C2443_CLKDIV0_ARMDIV_MASK; clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; __raw_writel(clkcon0, S3C2443_CLKDIV0); } diff --git a/arch/arm/mach-s3c64xx/Makefile.boot b/arch/arm/mach-s3c64xx/Makefile.boot index ba41fdc0a586..c642333af3ed 100644 --- a/arch/arm/mach-s3c64xx/Makefile.boot +++ b/arch/arm/mach-s3c64xx/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x50008000 + zreladdr-y += 0x50008000 params_phys-y := 0x50000100 diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c index f797f748b999..c681b99eda08 100644 --- a/arch/arm/mach-s3c64xx/dev-uart.c +++ b/arch/arm/mach-s3c64xx/dev-uart.c @@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S3CUART_RX0, - .end = IRQ_S3CUART_RX0, + .start = IRQ_UART0, + .end = IRQ_UART0, .flags = IORESOURCE_IRQ, }, - [2] = { - .start = IRQ_S3CUART_TX0, - .end = IRQ_S3CUART_TX0, - .flags = IORESOURCE_IRQ, - - }, - [3] = { - .start = IRQ_S3CUART_ERR0, - .end = IRQ_S3CUART_ERR0, - .flags = IORESOURCE_IRQ, - } }; static struct resource s3c64xx_uart1_resource[] = { @@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S3CUART_RX1, - .end = IRQ_S3CUART_RX1, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S3CUART_TX1, - .end = IRQ_S3CUART_TX1, - .flags = IORESOURCE_IRQ, - - }, - [3] = { - .start = IRQ_S3CUART_ERR1, - .end = IRQ_S3CUART_ERR1, + .start = IRQ_UART1, + .end = IRQ_UART1, .flags = IORESOURCE_IRQ, }, }; @@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S3CUART_RX2, - .end = IRQ_S3CUART_RX2, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S3CUART_TX2, - .end = IRQ_S3CUART_TX2, - .flags = IORESOURCE_IRQ, - - }, - [3] = { - .start = IRQ_S3CUART_ERR2, - .end = IRQ_S3CUART_ERR2, + .start = IRQ_UART2, + .end = IRQ_UART2, .flags = IORESOURCE_IRQ, }, }; @@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S3CUART_RX3, - .end = IRQ_S3CUART_RX3, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S3CUART_TX3, - .end = IRQ_S3CUART_TX3, - .flags = IORESOURCE_IRQ, - - }, - [3] = { - .start = IRQ_S3CUART_ERR3, - .end = IRQ_S3CUART_ERR3, + .start = IRQ_UART3, + .end = IRQ_UART3, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h index c026f67a80de..443f85b3c203 100644 --- a/arch/arm/mach-s3c64xx/include/mach/irqs.h +++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h @@ -27,36 +27,6 @@ #define IRQ_VIC0_BASE S3C_IRQ(0) #define IRQ_VIC1_BASE S3C_IRQ(32) -/* UART interrupts, each UART has 4 intterupts per channel so - * use the space between the ISA and S3C main interrupts. Note, these - * are not in the same order as the S3C24XX series! */ - -#define IRQ_S3CUART_BASE0 (16) -#define IRQ_S3CUART_BASE1 (20) -#define IRQ_S3CUART_BASE2 (24) -#define IRQ_S3CUART_BASE3 (28) - -#define UART_IRQ_RXD (0) -#define UART_IRQ_ERR (1) -#define UART_IRQ_TXD (2) -#define UART_IRQ_MODEM (3) - -#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) -#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) -#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) - -#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) -#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) -#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) - -#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) -#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) -#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) - -#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) -#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) -#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) - /* VIC based IRQs */ #define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x)) diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c index 75d9a0e49193..b07357e94958 100644 --- a/arch/arm/mach-s3c64xx/irq.c +++ b/arch/arm/mach-s3c64xx/irq.c @@ -25,29 +25,6 @@ #include <plat/irq-uart.h> #include <plat/cpu.h> -static struct s3c_uart_irq uart_irqs[] = { - [0] = { - .regs = S3C_VA_UART0, - .base_irq = IRQ_S3CUART_BASE0, - .parent_irq = IRQ_UART0, - }, - [1] = { - .regs = S3C_VA_UART1, - .base_irq = IRQ_S3CUART_BASE1, - .parent_irq = IRQ_UART1, - }, - [2] = { - .regs = S3C_VA_UART2, - .base_irq = IRQ_S3CUART_BASE2, - .parent_irq = IRQ_UART2, - }, - [3] = { - .regs = S3C_VA_UART3, - .base_irq = IRQ_S3CUART_BASE3, - .parent_irq = IRQ_UART3, - }, -}; - /* setup the sources the vic should advertise resume for, even though it * is not doing the wake (set_irq_wake needs to be valid) */ #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE)) @@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) /* add the timer sub-irqs */ s3c_init_vic_timer_irq(5, IRQ_TIMER0); - - s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); } diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index ecbea92bf83b..a9f3183e0290 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -262,45 +262,6 @@ static struct samsung_keypad_platdata smdk6410_keypad_data __initdata = { .cols = 8, }; -static int smdk6410_backlight_init(struct device *dev) -{ - int ret; - - ret = gpio_request(S3C64XX_GPF(15), "Backlight"); - if (ret) { - printk(KERN_ERR "failed to request GPF for PWM-OUT1\n"); - return ret; - } - - /* Configure GPIO pin with S3C64XX_GPF15_PWM_TOUT1 */ - s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2)); - - return 0; -} - -static void smdk6410_backlight_exit(struct device *dev) -{ - s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_OUTPUT); - gpio_free(S3C64XX_GPF(15)); -} - -static struct platform_pwm_backlight_data smdk6410_backlight_data = { - .pwm_id = 1, - .max_brightness = 255, - .dft_brightness = 255, - .pwm_period_ns = 78770, - .init = smdk6410_backlight_init, - .exit = smdk6410_backlight_exit, -}; - -static struct platform_device smdk6410_backlight_device = { - .name = "pwm-backlight", - .dev = { - .parent = &s3c_device_timer[1].dev, - .platform_data = &smdk6410_backlight_data, - }, -}; - static struct map_desc smdk6410_iodesc[] = {}; static struct platform_device *smdk6410_devices[] __initdata = { diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c index 8bad64370689..055e2858b0dd 100644 --- a/arch/arm/mach-s3c64xx/pm.c +++ b/arch/arm/mach-s3c64xx/pm.c @@ -16,6 +16,7 @@ #include <linux/suspend.h> #include <linux/serial_core.h> #include <linux/io.h> +#include <linux/gpio.h> #include <mach/map.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-s5p64x0/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot index ff90aa13bd67..79ece4055b02 100644 --- a/arch/arm/mach-s5p64x0/Makefile.boot +++ b/arch/arm/mach-s5p64x0/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c index 69ed4545112b..fe7380f5c3cd 100644 --- a/arch/arm/mach-s5p64x0/irq-eint.c +++ b/arch/arm/mach-s5p64x0/irq-eint.c @@ -129,7 +129,7 @@ static int s5p64x0_alloc_gc(void) } ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack; + ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_set_bit; ct->chip.irq_unmask = irq_gc_mask_clr_bit; ct->chip.irq_set_type = s5p64x0_irq_eint_set_type; diff --git a/arch/arm/mach-s5pc100/Makefile.boot b/arch/arm/mach-s5pc100/Makefile.boot index ff90aa13bd67..79ece4055b02 100644 --- a/arch/arm/mach-s5pc100/Makefile.boot +++ b/arch/arm/mach-s5pc100/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 diff --git a/arch/arm/mach-s5pv210/Makefile.boot b/arch/arm/mach-s5pv210/Makefile.boot index ff90aa13bd67..79ece4055b02 100644 --- a/arch/arm/mach-s5pv210/Makefile.boot +++ b/arch/arm/mach-s5pv210/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 52a8e607bcc2..f5f8fa89679c 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -815,8 +815,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 }, }, { .clk = { - .name = "sclk_cam", - .devname = "s5pv210-fimc.0", + .name = "sclk_cam0", .enable = s5pv210_clk_mask0_ctrl, .ctrlbit = (1 << 3), }, @@ -825,8 +824,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 }, }, { .clk = { - .name = "sclk_cam", - .devname = "s5pv210-fimc.1", + .name = "sclk_cam1", .enable = s5pv210_clk_mask0_ctrl, .ctrlbit = (1 << 4), }, diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c index 309e388a8a83..f149d278377b 100644 --- a/arch/arm/mach-s5pv210/pm.c +++ b/arch/arm/mach-s5pv210/pm.c @@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = { SAVE_ITEM(S3C2410_TCNTO(0)), }; -void s5pv210_cpu_suspend(unsigned long arg) +static int s5pv210_cpu_suspend(unsigned long arg) { unsigned long tmp; diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 41252d22e659..00631787e80a 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_SA1100_PLEB) += pleb.o obj-$(CONFIG_SA1100_SHANNON) += shannon.o obj-$(CONFIG_SA1100_SIMPAD) += simpad.o -led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o # LEDs support obj-$(CONFIG_LEDS) += $(led-y) diff --git a/arch/arm/mach-sa1100/Makefile.boot b/arch/arm/mach-sa1100/Makefile.boot index a56ad0417cf2..5a616f6e5612 100644 --- a/arch/arm/mach-sa1100/Makefile.boot +++ b/arch/arm/mach-sa1100/Makefile.boot @@ -1,6 +1,7 @@ - zreladdr-y := 0xc0008000 ifeq ($(CONFIG_ARCH_SA1100),y) - zreladdr-$(CONFIG_SA1111) := 0xc0208000 + zreladdr-$(CONFIG_SA1111) += 0xc0208000 +else + zreladdr-y += 0xc0008000 endif params_phys-y := 0xc0000100 initrd_phys-y := 0xc0800000 diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 26257df19b63..6290ce28b883 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -301,8 +301,7 @@ static void __init get_assabet_scr(void) } static void __init -fixup_assabet(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_assabet(struct tag *tags, char **cmdline, struct meminfo *mi) { /* This must be done before any call to machine_has_neponset() */ map_sa1100_gpio_regs(); diff --git a/arch/arm/mach-sa1100/include/mach/io.h b/arch/arm/mach-sa1100/include/mach/io.h index d8b43f3dcd2d..dfc27ff08344 100644 --- a/arch/arm/mach-sa1100/include/mach/io.h +++ b/arch/arm/mach-sa1100/include/mach/io.h @@ -10,11 +10,9 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffffffff - /* - * We don't actually have real ISA nor PCI buses, but there is so many - * drivers out there that might just work if we fake them... + * __io() is required to be an equivalent mapping to __mem_pci() for + * SOC_COMMON to work. */ #define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h index 9296c4513ce1..db28118103eb 100644 --- a/arch/arm/mach-sa1100/include/mach/simpad.h +++ b/arch/arm/mach-sa1100/include/mach/simpad.h @@ -48,32 +48,80 @@ #define GPIO_SMART_CARD GPIO_GPIO10 #define IRQ_GPIO_SMARD_CARD IRQ_GPIO10 -// CS3 Latch is write only, a shadow is necessary +/*--- ucb1x00 GPIO ---*/ +#define SIMPAD_UCB1X00_GPIO_BASE (GPIO_MAX + 1) +#define SIMPAD_UCB1X00_GPIO_PROG1 (SIMPAD_UCB1X00_GPIO_BASE) +#define SIMPAD_UCB1X00_GPIO_PROG2 (SIMPAD_UCB1X00_GPIO_BASE + 1) +#define SIMPAD_UCB1X00_GPIO_UP (SIMPAD_UCB1X00_GPIO_BASE + 2) +#define SIMPAD_UCB1X00_GPIO_DOWN (SIMPAD_UCB1X00_GPIO_BASE + 3) +#define SIMPAD_UCB1X00_GPIO_LEFT (SIMPAD_UCB1X00_GPIO_BASE + 4) +#define SIMPAD_UCB1X00_GPIO_RIGHT (SIMPAD_UCB1X00_GPIO_BASE + 5) +#define SIMPAD_UCB1X00_GPIO_6 (SIMPAD_UCB1X00_GPIO_BASE + 6) +#define SIMPAD_UCB1X00_GPIO_7 (SIMPAD_UCB1X00_GPIO_BASE + 7) +#define SIMPAD_UCB1X00_GPIO_HEADSET (SIMPAD_UCB1X00_GPIO_BASE + 8) +#define SIMPAD_UCB1X00_GPIO_SPEAKER (SIMPAD_UCB1X00_GPIO_BASE + 9) + +/*--- CS3 Latch ---*/ +#define SIMPAD_CS3_GPIO_BASE (GPIO_MAX + 11) +#define SIMPAD_CS3_VCC_5V_EN (SIMPAD_CS3_GPIO_BASE) +#define SIMPAD_CS3_VCC_3V_EN (SIMPAD_CS3_GPIO_BASE + 1) +#define SIMPAD_CS3_EN1 (SIMPAD_CS3_GPIO_BASE + 2) +#define SIMPAD_CS3_EN0 (SIMPAD_CS3_GPIO_BASE + 3) +#define SIMPAD_CS3_DISPLAY_ON (SIMPAD_CS3_GPIO_BASE + 4) +#define SIMPAD_CS3_PCMCIA_BUFF_DIS (SIMPAD_CS3_GPIO_BASE + 5) +#define SIMPAD_CS3_MQ_RESET (SIMPAD_CS3_GPIO_BASE + 6) +#define SIMPAD_CS3_PCMCIA_RESET (SIMPAD_CS3_GPIO_BASE + 7) +#define SIMPAD_CS3_DECT_POWER_ON (SIMPAD_CS3_GPIO_BASE + 8) +#define SIMPAD_CS3_IRDA_SD (SIMPAD_CS3_GPIO_BASE + 9) +#define SIMPAD_CS3_RS232_ON (SIMPAD_CS3_GPIO_BASE + 10) +#define SIMPAD_CS3_SD_MEDIAQ (SIMPAD_CS3_GPIO_BASE + 11) +#define SIMPAD_CS3_LED2_ON (SIMPAD_CS3_GPIO_BASE + 12) +#define SIMPAD_CS3_IRDA_MODE (SIMPAD_CS3_GPIO_BASE + 13) +#define SIMPAD_CS3_ENABLE_5V (SIMPAD_CS3_GPIO_BASE + 14) +#define SIMPAD_CS3_RESET_SIMCARD (SIMPAD_CS3_GPIO_BASE + 15) + +#define SIMPAD_CS3_PCMCIA_BVD1 (SIMPAD_CS3_GPIO_BASE + 16) +#define SIMPAD_CS3_PCMCIA_BVD2 (SIMPAD_CS3_GPIO_BASE + 17) +#define SIMPAD_CS3_PCMCIA_VS1 (SIMPAD_CS3_GPIO_BASE + 18) +#define SIMPAD_CS3_PCMCIA_VS2 (SIMPAD_CS3_GPIO_BASE + 19) +#define SIMPAD_CS3_LOCK_IND (SIMPAD_CS3_GPIO_BASE + 20) +#define SIMPAD_CS3_CHARGING_STATE (SIMPAD_CS3_GPIO_BASE + 21) +#define SIMPAD_CS3_PCMCIA_SHORT (SIMPAD_CS3_GPIO_BASE + 22) +#define SIMPAD_CS3_GPIO_23 (SIMPAD_CS3_GPIO_BASE + 23) -#define CS3BUSTYPE unsigned volatile long #define CS3_BASE 0xf1000000 -#define VCC_5V_EN 0x0001 // For 5V PCMCIA -#define VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA -#define EN1 0x0004 // This is only for EPROM's -#define EN0 0x0008 // Both should be enable for 3.3V or 5V -#define DISPLAY_ON 0x0010 -#define PCMCIA_BUFF_DIS 0x0020 -#define MQ_RESET 0x0040 -#define PCMCIA_RESET 0x0080 -#define DECT_POWER_ON 0x0100 -#define IRDA_SD 0x0200 // Shutdown for powersave -#define RS232_ON 0x0400 -#define SD_MEDIAQ 0x0800 // Shutdown for powersave -#define LED2_ON 0x1000 -#define IRDA_MODE 0x2000 // Fast/Slow IrDA mode -#define ENABLE_5V 0x4000 // Enable 5V circuit -#define RESET_SIMCARD 0x8000 - -#define RS232_ENABLE 0x0440 -#define PCMCIAMASK 0x402f - - +long simpad_get_cs3_ro(void); +long simpad_get_cs3_shadow(void); +void simpad_set_cs3_bit(int value); +void simpad_clear_cs3_bit(int value); + +#define VCC_5V_EN 0x0001 /* For 5V PCMCIA */ +#define VCC_3V_EN 0x0002 /* FOR 3.3V PCMCIA */ +#define EN1 0x0004 /* This is only for EPROM's */ +#define EN0 0x0008 /* Both should be enable for 3.3V or 5V */ +#define DISPLAY_ON 0x0010 +#define PCMCIA_BUFF_DIS 0x0020 +#define MQ_RESET 0x0040 +#define PCMCIA_RESET 0x0080 +#define DECT_POWER_ON 0x0100 +#define IRDA_SD 0x0200 /* Shutdown for powersave */ +#define RS232_ON 0x0400 +#define SD_MEDIAQ 0x0800 /* Shutdown for powersave */ +#define LED2_ON 0x1000 +#define IRDA_MODE 0x2000 /* Fast/Slow IrDA mode */ +#define ENABLE_5V 0x4000 /* Enable 5V circuit */ +#define RESET_SIMCARD 0x8000 + +#define PCMCIA_BVD1 0x01 +#define PCMCIA_BVD2 0x02 +#define PCMCIA_VS1 0x04 +#define PCMCIA_VS2 0x08 +#define LOCK_IND 0x10 +#define CHARGING_STATE 0x20 +#define PCMCIA_SHORT 0x40 + +/*--- Battery ---*/ struct simpad_battery { unsigned char ac_status; /* line connected yes/no */ unsigned char status; /* battery loading yes/no */ diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c deleted file mode 100644 index d50f4eeaa12e..000000000000 --- a/arch/arm/mach-sa1100/leds-simpad.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-simpad.c - * - * Author: Juergen Messerer <juergen.messerer@siemens.ch> - */ -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/system.h> -#include <mach/simpad.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED 1 -#define LED_STATE_CLAIMED 2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_GREEN (1) -#define LED_MASK (1) - -extern void set_cs3_bit(int value); -extern void clear_cs3_bit(int value); - -void simpad_leds_event(led_event_t evt) -{ - switch (evt) - { - case led_start: - hw_led_state = LED_GREEN; - led_state = LED_STATE_ENABLED; - break; - - case led_stop: - led_state &= ~LED_STATE_ENABLED; - break; - - case led_claim: - led_state |= LED_STATE_CLAIMED; - hw_led_state = LED_GREEN; - break; - - case led_release: - led_state &= ~LED_STATE_CLAIMED; - hw_led_state = LED_GREEN; - break; - -#ifdef CONFIG_LEDS_TIMER - case led_timer: - if (!(led_state & LED_STATE_CLAIMED)) - hw_led_state ^= LED_GREEN; - break; -#endif - -#ifdef CONFIG_LEDS_CPU - case led_idle_start: - break; - - case led_idle_end: - break; -#endif - - case led_halted: - break; - - case led_green_on: - if (led_state & LED_STATE_CLAIMED) - hw_led_state |= LED_GREEN; - break; - - case led_green_off: - if (led_state & LED_STATE_CLAIMED) - hw_led_state &= ~LED_GREEN; - break; - - case led_amber_on: - break; - - case led_amber_off: - break; - - case led_red_on: - break; - - case led_red_off: - break; - - default: - break; - } - - if (led_state & LED_STATE_ENABLED) - set_cs3_bit(LED2_ON); - else - clear_cs3_bit(LED2_ON); -} - diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c index bbfe197fb4d6..5fe71a0f1053 100644 --- a/arch/arm/mach-sa1100/leds.c +++ b/arch/arm/mach-sa1100/leds.c @@ -42,8 +42,6 @@ sa1100_leds_init(void) leds_event = adsbitsy_leds_event; if (machine_is_pt_system3()) leds_event = system3_leds_event; - if (machine_is_simpad()) - leds_event = simpad_leds_event; /* what about machine registry? including led, apm... -zecke */ leds_event(led_start); return 0; diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h index 68cc9f773d6d..776b6020f550 100644 --- a/arch/arm/mach-sa1100/leds.h +++ b/arch/arm/mach-sa1100/leds.h @@ -11,4 +11,3 @@ extern void pfs168_leds_event(led_event_t evt); extern void graphicsmaster_leds_event(led_event_t evt); extern void adsbitsy_leds_event(led_event_t evt); extern void system3_leds_event(led_event_t evt); -extern void simpad_leds_event(led_event_t evt); diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index cfb76077bd25..34659f354bef 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -13,6 +13,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/io.h> +#include <linux/gpio.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -28,35 +29,92 @@ #include <linux/serial_core.h> #include <linux/ioport.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/leds.h> +#include <linux/i2c-gpio.h> #include "generic.h" -long cs3_shadow; +/* + * CS3 support + */ -long get_cs3_shadow(void) +static long cs3_shadow; +static spinlock_t cs3_lock; +static struct gpio_chip cs3_gpio; + +long simpad_get_cs3_ro(void) +{ + return readl(CS3_BASE); +} +EXPORT_SYMBOL(simpad_get_cs3_ro); + +long simpad_get_cs3_shadow(void) { return cs3_shadow; } +EXPORT_SYMBOL(simpad_get_cs3_shadow); -void set_cs3(long value) +static void __simpad_write_cs3(void) { - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value; + writel(cs3_shadow, CS3_BASE); } -void set_cs3_bit(int value) +void simpad_set_cs3_bit(int value) { + unsigned long flags; + + spin_lock_irqsave(&cs3_lock, flags); cs3_shadow |= value; - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; + __simpad_write_cs3(); + spin_unlock_irqrestore(&cs3_lock, flags); } +EXPORT_SYMBOL(simpad_set_cs3_bit); -void clear_cs3_bit(int value) +void simpad_clear_cs3_bit(int value) { + unsigned long flags; + + spin_lock_irqsave(&cs3_lock, flags); cs3_shadow &= ~value; - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; + __simpad_write_cs3(); + spin_unlock_irqrestore(&cs3_lock, flags); } +EXPORT_SYMBOL(simpad_clear_cs3_bit); + +static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + if (offset > 15) + return; + if (value) + simpad_set_cs3_bit(1 << offset); + else + simpad_clear_cs3_bit(1 << offset); +}; + +static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 15) + return simpad_get_cs3_ro() & (1 << (offset - 16)); + return simpad_get_cs3_shadow() & (1 << offset); +}; -EXPORT_SYMBOL(set_cs3_bit); -EXPORT_SYMBOL(clear_cs3_bit); +static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 15) + return 0; + return -EINVAL; +}; + +static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + if (offset > 15) + return -EINVAL; + cs3_gpio_set(chip, offset, value); + return 0; +}; static struct map_desc simpad_io_desc[] __initdata = { { /* MQ200 */ @@ -64,9 +122,9 @@ static struct map_desc simpad_io_desc[] __initdata = { .pfn = __phys_to_pfn(0x4b800000), .length = 0x00800000, .type = MT_DEVICE - }, { /* Paules CS3, write only */ - .virtual = 0xf1000000, - .pfn = __phys_to_pfn(0x18000000), + }, { /* Simpad CS3 */ + .virtual = CS3_BASE, + .pfn = __phys_to_pfn(SA1100_CS3_PHYS), .length = 0x00100000, .type = MT_DEVICE }, @@ -78,12 +136,12 @@ static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate) if (port->mapbase == (u_int)&Ser1UTCR0) { if (state) { - clear_cs3_bit(RS232_ON); - clear_cs3_bit(DECT_POWER_ON); + simpad_clear_cs3_bit(RS232_ON); + simpad_clear_cs3_bit(DECT_POWER_ON); }else { - set_cs3_bit(RS232_ON); - set_cs3_bit(DECT_POWER_ON); + simpad_set_cs3_bit(RS232_ON); + simpad_set_cs3_bit(DECT_POWER_ON); } } } @@ -132,6 +190,7 @@ static struct resource simpad_flash_resources [] = { static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, }; @@ -142,9 +201,10 @@ static void __init simpad_map_io(void) iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); - set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | - ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); - + /* Initialize CS3 */ + cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | + RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); + __simpad_write_cs3(); /* Spinlocks not yet initialized */ sa1100_register_uart_fns(&simpad_port_fns); sa1100_register_uart(0, 3); /* serial interface */ @@ -170,13 +230,14 @@ static void __init simpad_map_io(void) static void simpad_power_off(void) { - local_irq_disable(); // was cli - set_cs3(0x800); /* only SD_MEDIAQ */ + local_irq_disable(); + cs3_shadow = SD_MEDIAQ; + __simpad_write_cs3(); /* Bypass spinlock here */ /* disable internal oscillator, float CS lines */ PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); - /* enable wake-up on GPIO0 (Assabet...) */ - PWER = GFER = GRER = 1; + /* enable wake-up on GPIO0 */ + PWER = GFER = GRER = PWER_GPIO0; /* * set scratchpad to zero, just in case it is used as a * restart address by the bootloader. @@ -192,6 +253,91 @@ static void simpad_power_off(void) } +/* + * gpio_keys +*/ + +static struct gpio_keys_button simpad_button_table[] = { + { KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" }, +}; + +static struct gpio_keys_platform_data simpad_keys_data = { + .buttons = simpad_button_table, + .nbuttons = ARRAY_SIZE(simpad_button_table), +}; + +static struct platform_device simpad_keys = { + .name = "gpio-keys", + .dev = { + .platform_data = &simpad_keys_data, + }, +}; + +static struct gpio_keys_button simpad_polled_button_table[] = { + { KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" }, + { KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" }, + { KEY_UP, SIMPAD_UCB1X00_GPIO_UP, 1, "up button" }, + { KEY_DOWN, SIMPAD_UCB1X00_GPIO_DOWN, 1, "down button" }, + { KEY_LEFT, SIMPAD_UCB1X00_GPIO_LEFT, 1, "left button" }, + { KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" }, +}; + +static struct gpio_keys_platform_data simpad_polled_keys_data = { + .buttons = simpad_polled_button_table, + .nbuttons = ARRAY_SIZE(simpad_polled_button_table), + .poll_interval = 50, +}; + +static struct platform_device simpad_polled_keys = { + .name = "gpio-keys-polled", + .dev = { + .platform_data = &simpad_polled_keys_data, + }, +}; + +/* + * GPIO LEDs + */ + +static struct gpio_led simpad_leds[] = { + { + .name = "simpad:power", + .gpio = SIMPAD_CS3_LED2_ON, + .active_low = 0, + .default_trigger = "default-on", + }, +}; + +static struct gpio_led_platform_data simpad_led_data = { + .num_leds = ARRAY_SIZE(simpad_leds), + .leds = simpad_leds, +}; + +static struct platform_device simpad_gpio_leds = { + .name = "leds-gpio", + .id = 0, + .dev = { + .platform_data = &simpad_led_data, + }, +}; + +/* + * i2c + */ +static struct i2c_gpio_platform_data simpad_i2c_data = { + .sda_pin = GPIO_GPIO21, + .scl_pin = GPIO_GPIO25, + .udelay = 10, + .timeout = HZ, +}; + +static struct platform_device simpad_i2c = { + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &simpad_i2c_data, + }, +}; /* * MediaQ Video Device @@ -202,7 +348,11 @@ static struct platform_device simpad_mq200fb = { }; static struct platform_device *devices[] __initdata = { - &simpad_mq200fb + &simpad_keys, + &simpad_polled_keys, + &simpad_mq200fb, + &simpad_gpio_leds, + &simpad_i2c, }; @@ -211,6 +361,19 @@ static int __init simpad_init(void) { int ret; + spin_lock_init(&cs3_lock); + + cs3_gpio.label = "simpad_cs3"; + cs3_gpio.base = SIMPAD_CS3_GPIO_BASE; + cs3_gpio.ngpio = 24; + cs3_gpio.set = cs3_gpio_set; + cs3_gpio.get = cs3_gpio_get; + cs3_gpio.direction_input = cs3_gpio_direction_input; + cs3_gpio.direction_output = cs3_gpio_direction_output; + ret = gpiochip_add(&cs3_gpio); + if (ret) + printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device"); + pm_power_off = simpad_power_off; sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, diff --git a/arch/arm/mach-shark/Makefile.boot b/arch/arm/mach-shark/Makefile.boot index 4320f8b92771..e40e24e4ca34 100644 --- a/arch/arm/mach-shark/Makefile.boot +++ b/arch/arm/mach-shark/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x08008000 + zreladdr-y += 0x08008000 diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c index c9e32de4adf9..ccd49189bbd0 100644 --- a/arch/arm/mach-shark/leds.c +++ b/arch/arm/mach-shark/leds.c @@ -36,7 +36,7 @@ static char led_state; static short hw_led_state; static short saved_state; -static DEFINE_SPINLOCK(leds_lock); +static DEFINE_RAW_SPINLOCK(leds_lock); short sequoia_read(int addr) { outw(addr,0x24); @@ -52,7 +52,7 @@ static void sequoia_leds_event(led_event_t evt) { unsigned long flags; - spin_lock_irqsave(&leds_lock, flags); + raw_spin_lock_irqsave(&leds_lock, flags); hw_led_state = sequoia_read(0x09); @@ -144,7 +144,7 @@ static void sequoia_leds_event(led_event_t evt) if (led_state & LED_STATE_ENABLED) sequoia_write(hw_led_state,0x09); - spin_unlock_irqrestore(&leds_lock, flags); + raw_spin_unlock_irqrestore(&leds_lock, flags); } static int __init leds_init(void) diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 1c08ee9de86a..498efd99338d 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -1,7 +1,7 @@ __ZRELADDR := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_MEMORY_START) + 0x8000]') - zreladdr-y := $(__ZRELADDR) + zreladdr-y += $(__ZRELADDR) # Unsupported legacy stuff # diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index ce5c2513c6ce..cdfdd624d21d 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -341,6 +341,7 @@ static struct platform_device mipidsi0_device = { static struct sh_mobile_sdhi_info sdhi0_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, + .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, .tmio_caps = MMC_CAP_SD_HIGHSPEED, .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, }; @@ -382,7 +383,7 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) } static struct sh_mobile_sdhi_info sh_sdhi1_info = { - .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT, .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .set_pwr = ag5evm_sdhi1_set_pwr, diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 9e0856b2f9e9..7e90d064ebcb 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -42,6 +42,7 @@ #include <linux/leds.h> #include <linux/input/sh_keysc.h> #include <linux/usb/r8a66597.h> +#include <linux/pm_clock.h> #include <media/sh_mobile_ceu.h> #include <media/sh_mobile_csi2.h> @@ -1408,10 +1409,16 @@ static void __init ap4evb_init(void) sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); + sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); + hdmi_init_pm_clock(); fsi_init_pm_clock(); sh7372_pm_init(); pm_clk_add(&fsi_device.dev, "spu2"); + pm_clk_add(&lcdc1_device.dev, "hdmi"); } static void __init ap4evb_timer_init(void) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index d41c01f83f15..00273dad5bf0 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -39,7 +39,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> -#include <linux/pm_runtime.h> +#include <linux/pm_clock.h> #include <linux/smsc911x.h> #include <linux/sh_intc.h> #include <linux/tca6416_keypad.h> @@ -641,6 +641,8 @@ static struct usbhs_private usbhs0_private = { }, .driver_param = { .buswait_bwait = 4, + .d0_tx_id = SHDMA_SLAVE_USB0_TX, + .d1_rx_id = SHDMA_SLAVE_USB0_RX, }, }, }; @@ -808,8 +810,11 @@ static struct usbhs_private usbhs1_private = { }, .driver_param = { .buswait_bwait = 4, + .has_otg = 1, .pipe_type = usbhs1_pipe_cfg, .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), + .d0_tx_id = SHDMA_SLAVE_USB1_TX, + .d1_rx_id = SHDMA_SLAVE_USB1_RX, }, }, }; @@ -1584,10 +1589,20 @@ static void __init mackerel_init(void) sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) + sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); +#endif + sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device); + sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); hdmi_init_pm_clock(); sh7372_pm_init(); pm_clk_add(&fsi_device.dev, "spu2"); + pm_clk_add(&hdmi_lcdc_device.dev, "hdmi"); } static void __init mackerel_timer_init(void) diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 6b1619a65dba..66975921e646 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -503,16 +503,17 @@ static struct clk *late_main_clks[] = { &sh7372_fsidivb_clk, }; -enum { MSTP001, +enum { MSTP001, MSTP000, MSTP131, MSTP130, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP117, MSTP116, MSTP113, MSTP106, MSTP101, MSTP100, MSTP223, - MSTP218, MSTP217, MSTP216, - MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP329, MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312, - MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403, + MSTP218, MSTP217, MSTP216, MSTP214, MSTP208, MSTP207, + MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312, + MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP407, MSTP406, + MSTP405, MSTP404, MSTP403, MSTP400, MSTP_NR }; #define MSTP(_parent, _reg, _bit, _flags) \ @@ -520,6 +521,7 @@ enum { MSTP001, static struct clk mstp_clks[MSTP_NR] = { [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */ + [MSTP000] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 0, 0), /* MSIOF0 */ [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */ [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */ [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */ @@ -538,14 +540,16 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ [MSTP216] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */ + [MSTP214] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */ + [MSTP208] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 8, 0), /* MSIOF1 */ [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ + [MSTP205] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 5, 0), /* MSIOF2 */ [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */ [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */ [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ - [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */ [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ @@ -557,8 +561,12 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP413] = MSTP(&pllc1_div2_clk, SMSTPCR4, 13, 0), /* HDMI */ [MSTP411] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 10, 0), /* IIC4 */ + [MSTP407] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-DMAC1 */ [MSTP406] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 6, 0), /* USB1 */ + [MSTP405] = MSTP(&r_clk, SMSTPCR4, 5, 0), /* CMT4 */ + [MSTP404] = MSTP(&r_clk, SMSTPCR4, 4, 0), /* CMT3 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ + [MSTP400] = MSTP(&r_clk, SMSTPCR4, 0, 0), /* CMT2 */ }; static struct clk_lookup lookups[] = { @@ -609,6 +617,7 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ + CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */ CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */ CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */ CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */ @@ -629,14 +638,16 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* DMAC1 */ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* DMAC2 */ CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), /* DMAC3 */ + CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), /* USB-DMAC0 */ + CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[MSTP208]), /* MSIOF1 */ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP206]), /* SCIFB */ + CLKDEV_DEV_ID("spi_sh_msiof.2", &mstp_clks[MSTP205]), /* MSIOF2 */ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ - CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */ @@ -650,11 +661,17 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */ + CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */ CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */ + CLKDEV_DEV_ID("sh_cmt.4", &mstp_clks[MSTP405]), /* CMT4 */ + CLKDEV_DEV_ID("sh_cmt.3", &mstp_clks[MSTP404]), /* CMT3 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ + CLKDEV_DEV_ID("sh_cmt.2", &mstp_clks[MSTP400]), /* CMT2 */ + CLKDEV_ICK_ID("hdmi", "sh_mobile_lcdc_fb.1", + &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 6db2ccabc2bf..61a846bb30f2 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -365,7 +365,7 @@ void __init sh73a0_clock_init(void) __raw_writel(0x108, SD2CKCR); /* detect main clock parent */ - switch ((__raw_readl(CKSCR) >> 24) & 0x03) { + switch ((__raw_readl(CKSCR) >> 28) & 0x03) { case 0: main_clk.parent = &sh73a0_extal1_clk; break; diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 06aecb31d9c7..c0cdbf997c91 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(void); extern void sh7372_clock_init(void); extern void sh7372_pinmux_init(void); extern void sh7372_pm_init(void); -extern void sh7372_cpu_suspend(void); -extern void sh7372_cpu_resume(void); +extern void sh7372_resume_core_standby_a3sm(void); +extern int sh7372_do_idle_a3sm(unsigned long unused); extern struct clk sh7372_extal1_clk; extern struct clk sh7372_extal2_clk; diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index ce595cee86cd..84532f9629b2 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -459,6 +459,10 @@ enum { SHDMA_SLAVE_SDHI2_TX, SHDMA_SLAVE_MMCIF_RX, SHDMA_SLAVE_MMCIF_TX, + SHDMA_SLAVE_USB0_TX, + SHDMA_SLAVE_USB0_RX, + SHDMA_SLAVE_USB1_TX, + SHDMA_SLAVE_USB1_RX, }; extern struct clk sh7372_extal1_clk; @@ -475,7 +479,12 @@ struct platform_device; struct sh7372_pm_domain { struct generic_pm_domain genpd; + struct dev_power_governor *gov; + void (*suspend)(void); + void (*resume)(void); unsigned int bit_shift; + bool no_debug; + bool stay_on; }; static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) @@ -487,16 +496,24 @@ static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) extern struct sh7372_pm_domain sh7372_a4lc; extern struct sh7372_pm_domain sh7372_a4mp; extern struct sh7372_pm_domain sh7372_d4; +extern struct sh7372_pm_domain sh7372_a4r; extern struct sh7372_pm_domain sh7372_a3rv; extern struct sh7372_pm_domain sh7372_a3ri; +extern struct sh7372_pm_domain sh7372_a3sp; extern struct sh7372_pm_domain sh7372_a3sg; extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, struct platform_device *pdev); +extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, + struct sh7372_pm_domain *sh7372_sd); #else #define sh7372_init_pm_domain(pd) do { } while(0) #define sh7372_add_device_to_domain(pd, pdev) do { } while(0) +#define sh7372_pm_add_subdomain(pd, sd) do { } while(0) #endif /* CONFIG_PM */ +extern void sh7372_intcs_suspend(void); +extern void sh7372_intcs_resume(void); + #endif /* __ASM_SH7372_H__ */ diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index 3b28743c77eb..29cdc0522d9c 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c @@ -379,7 +379,7 @@ enum { /* BBIF2 */ VPU, TSIF1, - _3DG_SGX530, + /* 3DG */ _2DDMAC, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2, IPMMU_IPMMUR, IPMMU_IPMMUR2, @@ -436,7 +436,7 @@ static struct intc_vect intcs_vectors[] = { /* BBIF2 */ INTCS_VECT(VPU, 0x980), INTCS_VECT(TSIF1, 0x9a0), - INTCS_VECT(_3DG_SGX530, 0x9e0), + /* 3DG */ INTCS_VECT(_2DDMAC, 0xa00), INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0), INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0), @@ -521,7 +521,7 @@ static struct intc_mask_reg intcs_mask_registers[] = { RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } }, { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */ { 0, 0, MSIOF, 0, - _3DG_SGX530, 0, 0, 0 } }, + 0, 0, 0, 0 } }, { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */ { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0, 0, 0, 0, 0 } }, @@ -561,7 +561,6 @@ static struct intc_prio_reg intcs_prio_registers[] = { TMU_TUNI2, TSIF1 } }, { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0, VEU, BEU } }, { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, IIC0 } }, - { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX530, 0, 0 } }, { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, 0, LMB, 0 } }, { 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, 0, 0 } }, { 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } }, @@ -607,9 +606,16 @@ static void intcs_demux(unsigned int irq, struct irq_desc *desc) generic_handle_irq(intcs_evt2irq(evtcodeas)); } +static void __iomem *intcs_ffd2; +static void __iomem *intcs_ffd5; + void __init sh7372_init_irq(void) { - void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); + void __iomem *intevtsa; + + intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE); + intevtsa = intcs_ffd2 + 0x100; + intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE); register_intc_controller(&intca_desc); register_intc_controller(&intcs_desc); @@ -618,3 +624,46 @@ void __init sh7372_init_irq(void) irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa); irq_set_chained_handler(evt2irq(0xf80), intcs_demux); } + +static unsigned short ffd2[0x200]; +static unsigned short ffd5[0x100]; + +void sh7372_intcs_suspend(void) +{ + int k; + + for (k = 0x00; k <= 0x30; k += 4) + ffd2[k] = __raw_readw(intcs_ffd2 + k); + + for (k = 0x80; k <= 0xb0; k += 4) + ffd2[k] = __raw_readb(intcs_ffd2 + k); + + for (k = 0x180; k <= 0x188; k += 4) + ffd2[k] = __raw_readb(intcs_ffd2 + k); + + for (k = 0x00; k <= 0x3c; k += 4) + ffd5[k] = __raw_readw(intcs_ffd5 + k); + + for (k = 0x80; k <= 0x9c; k += 4) + ffd5[k] = __raw_readb(intcs_ffd5 + k); +} + +void sh7372_intcs_resume(void) +{ + int k; + + for (k = 0x00; k <= 0x30; k += 4) + __raw_writew(ffd2[k], intcs_ffd2 + k); + + for (k = 0x80; k <= 0xb0; k += 4) + __raw_writeb(ffd2[k], intcs_ffd2 + k); + + for (k = 0x180; k <= 0x188; k += 4) + __raw_writeb(ffd2[k], intcs_ffd2 + k); + + for (k = 0x00; k <= 0x3c; k += 4) + __raw_writew(ffd5[k], intcs_ffd5 + k); + + for (k = 0x80; k <= 0x9c; k += 4) + __raw_writeb(ffd5[k], intcs_ffd5 + k); +} diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 66f980625a33..e4e485fa2532 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -56,6 +56,12 @@ void __init smp_init_cpus(void) unsigned int ncores = shmobile_smp_get_core_count(); unsigned int i; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + for (i = 0; i < ncores; i++) set_cpu_possible(i, true); diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 933fb411be0f..79612737c5b2 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -15,23 +15,61 @@ #include <linux/list.h> #include <linux/err.h> #include <linux/slab.h> -#include <linux/pm_runtime.h> +#include <linux/pm_clock.h> #include <linux/platform_device.h> #include <linux/delay.h> +#include <linux/irq.h> +#include <linux/bitrev.h> #include <asm/system.h> #include <asm/io.h> #include <asm/tlbflush.h> +#include <asm/suspend.h> #include <mach/common.h> #include <mach/sh7372.h> -#define SMFRAM 0xe6a70000 -#define SYSTBCR 0xe6150024 -#define SBAR 0xe6180020 -#define APARMBAREA 0xe6f10020 +/* DBG */ +#define DBGREG1 0xe6100020 +#define DBGREG9 0xe6100040 +/* CPGA */ +#define SYSTBCR 0xe6150024 +#define MSTPSR0 0xe6150030 +#define MSTPSR1 0xe6150038 +#define MSTPSR2 0xe6150040 +#define MSTPSR3 0xe6150048 +#define MSTPSR4 0xe615004c +#define PLLC01STPCR 0xe61500c8 + +/* SYSC */ #define SPDCR 0xe6180008 #define SWUCR 0xe6180014 +#define SBAR 0xe6180020 +#define WUPRMSK 0xe6180028 +#define WUPSMSK 0xe618002c +#define WUPSMSK2 0xe6180048 #define PSTR 0xe6180080 +#define WUPSFAC 0xe6180098 +#define IRQCR 0xe618022c +#define IRQCR2 0xe6180238 +#define IRQCR3 0xe6180244 +#define IRQCR4 0xe6180248 +#define PDNSEL 0xe6180254 + +/* INTC */ +#define ICR1A 0xe6900000 +#define ICR2A 0xe6900004 +#define ICR3A 0xe6900008 +#define ICR4A 0xe690000c +#define INTMSK00A 0xe6900040 +#define INTMSK10A 0xe6900044 +#define INTMSK20A 0xe6900048 +#define INTMSK30A 0xe690004c + +/* MFIS */ +#define SMFRAM 0xe6a70000 + +/* AP-System Core */ +#define APARMBAREA 0xe6f10020 #define PSTR_RETRIES 100 #define PSTR_DELAY_US 10 @@ -43,6 +81,12 @@ static int pd_power_down(struct generic_pm_domain *genpd) struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); unsigned int mask = 1 << sh7372_pd->bit_shift; + if (sh7372_pd->suspend) + sh7372_pd->suspend(); + + if (sh7372_pd->stay_on) + return 0; + if (__raw_readl(PSTR) & mask) { unsigned int retry_count; @@ -55,8 +99,9 @@ static int pd_power_down(struct generic_pm_domain *genpd) } } - pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", - mask, __raw_readl(PSTR)); + if (!sh7372_pd->no_debug) + pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", + mask, __raw_readl(PSTR)); return 0; } @@ -68,6 +113,9 @@ static int pd_power_up(struct generic_pm_domain *genpd) unsigned int retry_count; int ret = 0; + if (sh7372_pd->stay_on) + goto out; + if (__raw_readl(PSTR) & mask) goto out; @@ -84,66 +132,48 @@ static int pd_power_up(struct generic_pm_domain *genpd) if (__raw_readl(SWUCR) & mask) ret = -EIO; + if (!sh7372_pd->no_debug) + pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", + mask, __raw_readl(PSTR)); + out: - pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", - mask, __raw_readl(PSTR)); + if (ret == 0 && sh7372_pd->resume) + sh7372_pd->resume(); return ret; } -static int pd_power_up_a3rv(struct generic_pm_domain *genpd) +static void sh7372_a4r_suspend(void) { - int ret = pd_power_up(genpd); - - /* force A4LC on after A3RV has been requested on */ - pm_genpd_poweron(&sh7372_a4lc.genpd); - - return ret; + sh7372_intcs_suspend(); + __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ } -static int pd_power_down_a3rv(struct generic_pm_domain *genpd) +static bool pd_active_wakeup(struct device *dev) { - int ret = pd_power_down(genpd); - - /* try to power down A4LC after A3RV is requested off */ - genpd_queue_power_off_work(&sh7372_a4lc.genpd); - - return ret; + return true; } -static int pd_power_down_a4lc(struct generic_pm_domain *genpd) +static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain) { - /* only power down A4LC if A3RV is off */ - if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift))) - return pd_power_down(genpd); - - return -EBUSY; + return false; } -static bool pd_active_wakeup(struct device *dev) -{ - return true; -} +struct dev_power_governor sh7372_always_on_gov = { + .power_down_ok = sh7372_power_down_forbidden, +}; void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) { struct generic_pm_domain *genpd = &sh7372_pd->genpd; - pm_genpd_init(genpd, NULL, false); + pm_genpd_init(genpd, sh7372_pd->gov, false); genpd->stop_device = pm_clk_suspend; genpd->start_device = pm_clk_resume; + genpd->dev_irq_safe = true; genpd->active_wakeup = pd_active_wakeup; - - if (sh7372_pd == &sh7372_a4lc) { - genpd->power_off = pd_power_down_a4lc; - genpd->power_on = pd_power_up; - } else if (sh7372_pd == &sh7372_a3rv) { - genpd->power_off = pd_power_down_a3rv; - genpd->power_on = pd_power_up_a3rv; - } else { - genpd->power_off = pd_power_down; - genpd->power_on = pd_power_up; - } + genpd->power_off = pd_power_down; + genpd->power_on = pd_power_up; genpd->power_on(&sh7372_pd->genpd); } @@ -152,11 +182,15 @@ void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, { struct device *dev = &pdev->dev; - if (!dev->power.subsys_data) { - pm_clk_init(dev); - pm_clk_add(dev, NULL); - } pm_genpd_add_device(&sh7372_pd->genpd, dev); + if (pm_clk_no_clocks(dev)) + pm_clk_add(dev, NULL); +} + +void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, + struct sh7372_pm_domain *sh7372_sd) +{ + pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd); } struct sh7372_pm_domain sh7372_a4lc = { @@ -171,6 +205,14 @@ struct sh7372_pm_domain sh7372_d4 = { .bit_shift = 3, }; +struct sh7372_pm_domain sh7372_a4r = { + .bit_shift = 5, + .gov = &sh7372_always_on_gov, + .suspend = sh7372_a4r_suspend, + .resume = sh7372_intcs_resume, + .stay_on = true, +}; + struct sh7372_pm_domain sh7372_a3rv = { .bit_shift = 6, }; @@ -179,39 +221,187 @@ struct sh7372_pm_domain sh7372_a3ri = { .bit_shift = 8, }; +struct sh7372_pm_domain sh7372_a3sp = { + .bit_shift = 11, + .gov = &sh7372_always_on_gov, + .no_debug = true, +}; + struct sh7372_pm_domain sh7372_a3sg = { .bit_shift = 13, }; #endif /* CONFIG_PM */ +#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) +static int sh7372_do_idle_core_standby(unsigned long unused) +{ + cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ + return 0; +} + static void sh7372_enter_core_standby(void) { - void __iomem *smfram = (void __iomem *)SMFRAM; + /* set reset vector, translate 4k */ + __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); + __raw_writel(0, APARMBAREA); - __raw_writel(0, APARMBAREA); /* translate 4k */ - __raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */ - __raw_writel(0x10, SYSTBCR); /* enable core standby */ + /* enter sleep mode with SYSTBCR to 0x10 */ + __raw_writel(0x10, SYSTBCR); + cpu_suspend(0, sh7372_do_idle_core_standby); + __raw_writel(0, SYSTBCR); - __raw_writel(0, smfram + 0x3c); /* clear page table address */ + /* disable reset vector translation */ + __raw_writel(0, SBAR); +} +#endif + +#ifdef CONFIG_SUSPEND +static void sh7372_enter_a3sm_common(int pllc0_on) +{ + /* set reset vector, translate 4k */ + __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); + __raw_writel(0, APARMBAREA); + + if (pllc0_on) + __raw_writel(0, PLLC01STPCR); + else + __raw_writel(1 << 28, PLLC01STPCR); + + __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */ + __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ + cpu_suspend(0, sh7372_do_idle_a3sm); + __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ + + /* disable reset vector translation */ + __raw_writel(0, SBAR); +} + +static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) +{ + unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; + unsigned long msk, msk2; + + /* check active clocks to determine potential wakeup sources */ + + mstpsr0 = __raw_readl(MSTPSR0); + if ((mstpsr0 & 0x00000003) != 0x00000003) { + pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0); + return 0; + } + + mstpsr1 = __raw_readl(MSTPSR1); + if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) { + pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1); + return 0; + } - sh7372_cpu_suspend(); - cpu_init(); + mstpsr2 = __raw_readl(MSTPSR2); + if ((mstpsr2 & 0x000741ff) != 0x000741ff) { + pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2); + return 0; + } - /* if page table address is non-NULL then we have been powered down */ - if (__raw_readl(smfram + 0x3c)) { - __raw_writel(__raw_readl(smfram + 0x40), - __va(__raw_readl(smfram + 0x3c))); + mstpsr3 = __raw_readl(MSTPSR3); + if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) { + pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3); + return 0; + } - flush_tlb_all(); - set_cr(__raw_readl(smfram + 0x38)); + mstpsr4 = __raw_readl(MSTPSR4); + if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) { + pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4); + return 0; } - __raw_writel(0, SYSTBCR); /* disable core standby */ - __raw_writel(0, SBAR); /* disable reset vector translation */ + msk = 0; + msk2 = 0; + + /* make bitmaps of limited number of wakeup sources */ + + if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */ + msk |= 1 << 31; + + if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */ + msk |= 1 << 21; + + if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */ + msk |= 1 << 2; + + if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */ + msk |= 1 << 1; + + if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */ + msk |= 1 << 1; + + if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */ + msk |= 1 << 1; + + if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */ + msk2 |= 1 << 17; + + *mskp = msk; + *msk2p = msk2; + + return 1; +} + +static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p) +{ + u16 tmp, irqcr1, irqcr2; + int k; + + irqcr1 = 0; + irqcr2 = 0; + + /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */ + for (k = 0; k <= 7; k++) { + tmp = (icr >> ((7 - k) * 4)) & 0xf; + irqcr1 |= (tmp & 0x03) << (k * 2); + irqcr2 |= (tmp >> 2) << (k * 2); + } + + *irqcr1p = irqcr1; + *irqcr2p = irqcr2; +} + +static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) +{ + u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; + unsigned long tmp; + + /* read IRQ0A -> IRQ15A mask */ + tmp = bitrev8(__raw_readb(INTMSK00A)); + tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8; + + /* setup WUPSMSK from clocks and external IRQ mask */ + msk = (~msk & 0xc030000f) | (tmp << 4); + __raw_writel(msk, WUPSMSK); + + /* propage level/edge trigger for external IRQ 0->15 */ + sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low); + sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high); + __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR); + __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2); + + /* read IRQ16A -> IRQ31A mask */ + tmp = bitrev8(__raw_readb(INTMSK20A)); + tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8; + + /* setup WUPSMSK2 from clocks and external IRQ mask */ + msk2 = (~msk2 & 0x00030000) | tmp; + __raw_writel(msk2, WUPSMSK2); + + /* propage level/edge trigger for external IRQ 16->31 */ + sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low); + sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high); + __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); + __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); } +#endif #ifdef CONFIG_CPU_IDLE + static void sh7372_cpuidle_setup(struct cpuidle_device *dev) { struct cpuidle_state *state; @@ -239,9 +429,25 @@ static void sh7372_cpuidle_init(void) {} #endif #ifdef CONFIG_SUSPEND + static int sh7372_enter_suspend(suspend_state_t suspend_state) { - sh7372_enter_core_standby(); + unsigned long msk, msk2; + + /* check active clocks to determine potential wakeup sources */ + if (sh7372_a3sm_valid(&msk, &msk2)) { + + /* convert INTC mask and sense to SYSC mask and sense */ + sh7372_setup_a3sm(msk, msk2); + + /* enter A3SM sleep with PLLC0 off */ + pr_debug("entering A3SM\n"); + sh7372_enter_a3sm_common(0); + } else { + /* default to Core Standby that supports all wakeup sources */ + pr_debug("entering Core Standby\n"); + sh7372_enter_core_standby(); + } return 0; } @@ -253,9 +459,6 @@ static void sh7372_suspend_init(void) static void sh7372_suspend_init(void) {} #endif -#define DBGREG1 0xe6100020 -#define DBGREG9 0xe6100040 - void __init sh7372_pm_init(void) { /* enable DBG hardware block to kick SYSC */ @@ -263,6 +466,9 @@ void __init sh7372_pm_init(void) __raw_writel(0x0000a501, DBGREG9); __raw_writel(0x00000000, DBGREG1); + /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ + __raw_writel(0, PDNSEL); + sh7372_suspend_init(); sh7372_cpuidle_init(); } diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c index 6ec454e1e063..bd5c6a3b8c55 100644 --- a/arch/arm/mach-shmobile/pm_runtime.c +++ b/arch/arm/mach-shmobile/pm_runtime.c @@ -15,6 +15,7 @@ #include <linux/io.h> #include <linux/pm_runtime.h> #include <linux/pm_domain.h> +#include <linux/pm_clock.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/sh_clk.h> diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 79f0413d8725..2380389e6ac5 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -30,6 +30,7 @@ #include <linux/sh_dma.h> #include <linux/sh_intc.h> #include <linux/sh_timer.h> +#include <linux/pm_domain.h> #include <mach/hardware.h> #include <mach/sh7372.h> #include <asm/mach-types.h> @@ -169,35 +170,35 @@ static struct platform_device scif6_device = { }; /* CMT */ -static struct sh_timer_config cmt10_platform_data = { - .name = "CMT10", - .channel_offset = 0x10, - .timer_bit = 0, +static struct sh_timer_config cmt2_platform_data = { + .name = "CMT2", + .channel_offset = 0x40, + .timer_bit = 5, .clockevent_rating = 125, .clocksource_rating = 125, }; -static struct resource cmt10_resources[] = { +static struct resource cmt2_resources[] = { [0] = { - .name = "CMT10", - .start = 0xe6138010, - .end = 0xe613801b, + .name = "CMT2", + .start = 0xe6130040, + .end = 0xe613004b, .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0b00), /* CMT1_CMT10 */ + .start = evt2irq(0x0b80), /* CMT2 */ .flags = IORESOURCE_IRQ, }, }; -static struct platform_device cmt10_device = { +static struct platform_device cmt2_device = { .name = "sh_cmt", - .id = 10, + .id = 2, .dev = { - .platform_data = &cmt10_platform_data, + .platform_data = &cmt2_platform_data, }, - .resource = cmt10_resources, - .num_resources = ARRAY_SIZE(cmt10_resources), + .resource = cmt2_resources, + .num_resources = ARRAY_SIZE(cmt2_resources), }; /* TMU */ @@ -602,6 +603,150 @@ static struct platform_device dma2_device = { }, }; +/* + * USB-DMAC + */ + +unsigned int usbts_shift[] = {3, 4, 5}; + +enum { + XMIT_SZ_8BYTE = 0, + XMIT_SZ_16BYTE = 1, + XMIT_SZ_32BYTE = 2, +}; + +#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) + +static const struct sh_dmae_channel sh7372_usb_dmae_channels[] = { + { + .offset = 0, + }, { + .offset = 0x20, + }, +}; + +/* USB DMAC0 */ +static const struct sh_dmae_slave_config sh7372_usb_dmae0_slaves[] = { + { + .slave_id = SHDMA_SLAVE_USB0_TX, + .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + }, { + .slave_id = SHDMA_SLAVE_USB0_RX, + .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + }, +}; + +static struct sh_dmae_pdata usb_dma0_platform_data = { + .slave = sh7372_usb_dmae0_slaves, + .slave_num = ARRAY_SIZE(sh7372_usb_dmae0_slaves), + .channel = sh7372_usb_dmae_channels, + .channel_num = ARRAY_SIZE(sh7372_usb_dmae_channels), + .ts_low_shift = 6, + .ts_low_mask = 0xc0, + .ts_high_shift = 0, + .ts_high_mask = 0, + .ts_shift = usbts_shift, + .ts_shift_num = ARRAY_SIZE(usbts_shift), + .dmaor_init = DMAOR_DME, + .chcr_offset = 0x14, + .chcr_ie_bit = 1 << 5, + .dmaor_is_32bit = 1, + .needs_tend_set = 1, + .no_dmars = 1, +}; + +static struct resource sh7372_usb_dmae0_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xe68a0020, + .end = 0xe68a0064 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* VCR/SWR/DMICR */ + .start = 0xe68a0000, + .end = 0xe68a0014 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* IRQ for channels */ + .start = evt2irq(0x0a00), + .end = evt2irq(0x0a00), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_dma0_device = { + .name = "sh-dma-engine", + .id = 3, + .resource = sh7372_usb_dmae0_resources, + .num_resources = ARRAY_SIZE(sh7372_usb_dmae0_resources), + .dev = { + .platform_data = &usb_dma0_platform_data, + }, +}; + +/* USB DMAC1 */ +static const struct sh_dmae_slave_config sh7372_usb_dmae1_slaves[] = { + { + .slave_id = SHDMA_SLAVE_USB1_TX, + .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + }, { + .slave_id = SHDMA_SLAVE_USB1_RX, + .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + }, +}; + +static struct sh_dmae_pdata usb_dma1_platform_data = { + .slave = sh7372_usb_dmae1_slaves, + .slave_num = ARRAY_SIZE(sh7372_usb_dmae1_slaves), + .channel = sh7372_usb_dmae_channels, + .channel_num = ARRAY_SIZE(sh7372_usb_dmae_channels), + .ts_low_shift = 6, + .ts_low_mask = 0xc0, + .ts_high_shift = 0, + .ts_high_mask = 0, + .ts_shift = usbts_shift, + .ts_shift_num = ARRAY_SIZE(usbts_shift), + .dmaor_init = DMAOR_DME, + .chcr_offset = 0x14, + .chcr_ie_bit = 1 << 5, + .dmaor_is_32bit = 1, + .needs_tend_set = 1, + .no_dmars = 1, +}; + +static struct resource sh7372_usb_dmae1_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xe68c0020, + .end = 0xe68c0064 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* VCR/SWR/DMICR */ + .start = 0xe68c0000, + .end = 0xe68c0014 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* IRQ for channels */ + .start = evt2irq(0x1d00), + .end = evt2irq(0x1d00), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_dma1_device = { + .name = "sh-dma-engine", + .id = 4, + .resource = sh7372_usb_dmae1_resources, + .num_resources = ARRAY_SIZE(sh7372_usb_dmae1_resources), + .dev = { + .platform_data = &usb_dma1_platform_data, + }, +}; + /* VPU */ static struct uio_info vpu_platform_data = { .name = "VPU5HG", @@ -818,7 +963,7 @@ static struct platform_device *sh7372_early_devices[] __initdata = { &scif4_device, &scif5_device, &scif6_device, - &cmt10_device, + &cmt2_device, &tmu00_device, &tmu01_device, }; @@ -829,6 +974,8 @@ static struct platform_device *sh7372_late_devices[] __initdata = { &dma0_device, &dma1_device, &dma2_device, + &usb_dma0_device, + &usb_dma1_device, &vpu_device, &veu0_device, &veu1_device, @@ -844,9 +991,14 @@ void __init sh7372_add_standard_devices(void) sh7372_init_pm_domain(&sh7372_a4lc); sh7372_init_pm_domain(&sh7372_a4mp); sh7372_init_pm_domain(&sh7372_d4); + sh7372_init_pm_domain(&sh7372_a4r); sh7372_init_pm_domain(&sh7372_a3rv); sh7372_init_pm_domain(&sh7372_a3ri); sh7372_init_pm_domain(&sh7372_a3sg); + sh7372_init_pm_domain(&sh7372_a3sp); + + sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); + sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); platform_add_devices(sh7372_early_devices, ARRAY_SIZE(sh7372_early_devices)); @@ -857,6 +1009,25 @@ void __init sh7372_add_standard_devices(void) sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device); sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device); sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device); + sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device); + sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device); + sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device); + sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device); + sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); + sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); + sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); } void __init sh7372_add_early_devices(void) diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S index d37d3ca4d18f..f3ab3c5810ea 100644 --- a/arch/arm/mach-shmobile/sleep-sh7372.S +++ b/arch/arm/mach-shmobile/sleep-sh7372.S @@ -30,58 +30,20 @@ */ #include <linux/linkage.h> +#include <linux/init.h> +#include <asm/memory.h> #include <asm/assembler.h> -#define SMFRAM 0xe6a70000 - - .align -kernel_flush: - .word v7_flush_dcache_all - - .align 3 -ENTRY(sh7372_cpu_suspend) - stmfd sp!, {r0-r12, lr} @ save registers on stack - - ldr r8, =SMFRAM - - mov r4, sp @ Store sp - mrs r5, spsr @ Store spsr - mov r6, lr @ Store lr - stmia r8!, {r4-r6} - - mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register - mrc p15, 0, r5, c2, c0, 0 @ TTBR0 - mrc p15, 0, r6, c2, c0, 1 @ TTBR1 - mrc p15, 0, r7, c2, c0, 2 @ TTBCR - stmia r8!, {r4-r7} - - mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register - mrc p15, 0, r5, c10, c2, 0 @ PRRR - mrc p15, 0, r6, c10, c2, 1 @ NMRR - stmia r8!,{r4-r6} - - mrc p15, 0, r4, c13, c0, 1 @ Context ID - mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID - mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address - mrs r7, cpsr @ Store current cpsr - stmia r8!, {r4-r7} - - mrc p15, 0, r4, c1, c0, 0 @ save control register - stmia r8!, {r4} - - /* - * jump out to kernel flush routine - * - reuse that code is better - * - it executes in a cached space so is faster than refetch per-block - * - should be faster and will change with kernel - * - 'might' have to copy address, load and jump to it - * Flush all data from the L1 data cache before disabling - * SCTLR.C bit. - */ - ldr r1, kernel_flush - mov lr, pc - bx r1 +#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) + .align 12 + .text + .global sh7372_resume_core_standby_a3sm +sh7372_resume_core_standby_a3sm: + ldr pc, 1f +1: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET + .global sh7372_do_idle_a3sm +sh7372_do_idle_a3sm: /* * Clear the SCTLR.C bit to prevent further data cache * allocation. Clearing SCTLR.C would make all the data accesses @@ -92,10 +54,13 @@ ENTRY(sh7372_cpu_suspend) mcr p15, 0, r0, c1, c0, 0 isb + /* disable L2 cache in the aux control register */ + mrc p15, 0, r10, c1, c0, 1 + bic r10, r10, #2 + mcr p15, 0, r10, c1, c0, 1 + /* - * Invalidate L1 data cache. Even though only invalidate is - * necessary exported flush API is used here. Doing clean - * on already clean cache would be almost NOP. + * Invalidate data cache again. */ ldr r1, kernel_flush blx r1 @@ -115,146 +80,16 @@ ENTRY(sh7372_cpu_suspend) dsb dmb -/* - * =================================== - * == WFI instruction => Enter idle == - * =================================== - */ - wfi @ wait for interrupt - -/* - * =================================== - * == Resume path for non-OFF modes == - * =================================== - */ - mrc p15, 0, r0, c1, c0, 0 - tst r0, #(1 << 2) @ Check C bit enabled? - orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared - mcreq p15, 0, r0, c1, c0, 0 - isb - -/* - * =================================== - * == Exit point from non-OFF modes == - * =================================== - */ - ldmfd sp!, {r0-r12, pc} @ restore regs and return +#define SPDCR 0xe6180008 +#define A3SM (1 << 12) - .pool + /* A3SM power down */ + ldr r0, =SPDCR + ldr r1, =A3SM + str r1, [r0] +1: + b 1b - .align 12 - .text - .global sh7372_cpu_resume -sh7372_cpu_resume: - - mov r1, #0 - /* - * Invalidate all instruction caches to PoU - * and flush branch target cache - */ - mcr p15, 0, r1, c7, c5, 0 - - ldr r3, =SMFRAM - - ldmia r3!, {r4-r6} - mov sp, r4 @ Restore sp - msr spsr_cxsf, r5 @ Restore spsr - mov lr, r6 @ Restore lr - - ldmia r3!, {r4-r7} - mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register - mcr p15, 0, r5, c2, c0, 0 @ TTBR0 - mcr p15, 0, r6, c2, c0, 1 @ TTBR1 - mcr p15, 0, r7, c2, c0, 2 @ TTBCR - - ldmia r3!,{r4-r6} - mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register - mcr p15, 0, r5, c10, c2, 0 @ PRRR - mcr p15, 0, r6, c10, c2, 1 @ NMRR - - ldmia r3!,{r4-r7} - mcr p15, 0, r4, c13, c0, 1 @ Context ID - mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID - mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address - msr cpsr, r7 @ store cpsr - - /* Starting to enable MMU here */ - mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl - /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */ - and r7, #0x7 - cmp r7, #0x0 - beq usettbr0 -ttbr_error: - /* - * More work needs to be done to support N[0:2] value other than 0 - * So looping here so that the error can be detected - */ - b ttbr_error - - .align -cache_pred_disable_mask: - .word 0xFFFFE7FB -ttbrbit_mask: - .word 0xFFFFC000 -table_index_mask: - .word 0xFFF00000 -table_entry: - .word 0x00000C02 -usettbr0: - - mrc p15, 0, r2, c2, c0, 0 - ldr r5, ttbrbit_mask - and r2, r5 - mov r4, pc - ldr r5, table_index_mask - and r4, r5 @ r4 = 31 to 20 bits of pc - /* Extract the value to be written to table entry */ - ldr r6, table_entry - /* r6 has the value to be written to table entry */ - add r6, r6, r4 - /* Getting the address of table entry to modify */ - lsr r4, #18 - /* r2 has the location which needs to be modified */ - add r2, r4 - ldr r4, [r2] - str r6, [r2] /* modify the table entry */ - - mov r7, r6 - mov r5, r2 - mov r6, r4 - /* r5 = original page table address */ - /* r6 = original page table data */ - - mov r0, #0 - mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer - mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array - mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB - mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB - - /* - * Restore control register. This enables the MMU. - * The caches and prediction are not enabled here, they - * will be enabled after restoring the MMU table entry. - */ - ldmia r3!, {r4} - stmia r3!, {r5} /* save original page table address */ - stmia r3!, {r6} /* save original page table data */ - stmia r3!, {r7} /* save modified page table data */ - - ldr r2, cache_pred_disable_mask - and r4, r2 - mcr p15, 0, r4, c1, c0, 0 - dsb - isb - - ldr r0, =restoremmu_on - bx r0 - -/* - * ============================== - * == Exit point from OFF mode == - * ============================== - */ -restoremmu_on: - - ldmfd sp!, {r0-r12, pc} @ restore regs and return +kernel_flush: + .word v7_flush_dcache_all +#endif diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot index 7a1f3c0eadb8..4674a4c221db 100644 --- a/arch/arm/mach-spear3xx/Makefile.boot +++ b/arch/arm/mach-spear3xx/Makefile.boot @@ -1,3 +1,3 @@ -zreladdr-y := 0x00008000 +zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot index 7a1f3c0eadb8..4674a4c221db 100644 --- a/arch/arm/mach-spear6xx/Makefile.boot +++ b/arch/arm/mach-spear6xx/Makefile.boot @@ -1,3 +1,3 @@ -zreladdr-y := 0x00008000 +zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot index f135c9deae10..5e02d4156b04 100644 --- a/arch/arm/mach-tcc8k/Makefile.boot +++ b/arch/arm/mach-tcc8k/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 initrd_phys-y := 0x20800000 diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index 428ad122be03..5e870d29eca1 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -1,4 +1,4 @@ -zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000 +zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) += 0x00008000 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000 diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index 846cd7d69e3e..c78ce41cca16 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -123,8 +123,8 @@ static struct platform_device *harmony_devices[] __initdata = { &harmony_audio_device, }; -static void __init tegra_harmony_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init tegra_harmony_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks = 2; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index ea2f79c9879b..5e6bc7719642 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -84,8 +84,8 @@ static void paz00_usb_init(void) platform_device_register(&tegra_ehci3_device); } -static void __init tegra_paz00_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks = 1; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c index 89a6d2adc1de..652c3404d0e2 100644 --- a/arch/arm/mach-tegra/board-trimslice.c +++ b/arch/arm/mach-tegra/board-trimslice.c @@ -126,8 +126,8 @@ static void trimslice_usb_init(void) platform_device_register(&tegra_ehci1_device); } -static void __init tegra_trimslice_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) +static void __init tegra_trimslice_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) { mi->nr_banks = 2; mi->bank[0].start = PHYS_OFFSET; diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 0e1016a827ac..0e0fd4d889bd 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -32,7 +32,6 @@ #include <asm/system.h> -#include <mach/hardware.h> #include <mach/clk.h> /* Frequency table index must be sequential starting at 0 */ diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 0886cbccddee..7d2b5d03c1df 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -114,10 +114,10 @@ void __init smp_init_cpus(void) { unsigned int i, ncores = scu_get_core_count(scu_base); - if (ncores > NR_CPUS) { - printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 32a7b0f7e9f7..449fd6a8dbd6 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -6,6 +6,8 @@ comment "ST-Ericsson Mobile Platform Products" config MACH_U300 bool "U300" + select PINCTRL + select PINMUX_U300 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index 8fd354aaf0a7..285538124e5e 100644 --- a/arch/arm/mach-u300/Makefile +++ b/arch/arm/mach-u300/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U300 machine. # -obj-y := core.o clock.o timer.o padmux.o +obj-y := core.o clock.o timer.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-u300/Makefile.boot b/arch/arm/mach-u300/Makefile.boot index 6fbfc6ea2d35..69357affbd77 100644 --- a/arch/arm/mach-u300/Makefile.boot +++ b/arch/arm/mach-u300/Makefile.boot @@ -4,10 +4,10 @@ # INITRD_PHYS must be in RAM ifdef CONFIG_MACH_U300_SINGLE_RAM - zreladdr-y := 0x28E08000 + zreladdr-y += 0x28E08000 params_phys-y := 0x28E00100 else - zreladdr-y := 0x48008000 + zreladdr-y += 0x48008000 params_phys-y := 0x48000100 endif diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..2f5929bdeaa2 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -25,6 +25,8 @@ #include <linux/err.h> #include <linux/mtd/nand.h> #include <linux/mtd/fsmc.h> +#include <linux/pinctrl/machine.h> +#include <linux/pinctrl/pinmux.h> #include <asm/types.h> #include <asm/setup.h> @@ -1535,6 +1537,14 @@ static struct coh901318_platform coh901318_platform = { .max_channels = U300_DMA_CHANNELS, }; +static struct resource pinmux_resources[] = { + { + .start = U300_SYSCON_BASE, + .end = U300_SYSCON_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + static struct platform_device wdog_device = { .name = "coh901327_wdog", .id = -1, @@ -1630,6 +1640,72 @@ static struct platform_device dma_device = { }, }; +static struct platform_device pinmux_device = { + .name = "pinmux-u300", + .id = -1, + .num_resources = ARRAY_SIZE(pinmux_resources), + .resource = pinmux_resources, +}; + +/* Pinmux settings */ +static struct pinmux_map u300_pinmux_map[] = { + /* anonymous maps for chip power and EMIFs */ + PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"), + PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"), + PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"), + /* per-device maps for MMC/SD, SPI and UART */ + PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"), + PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"), + PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"), +}; + +struct u300_mux_hog { + const char *name; + struct device *dev; + struct pinmux *pmx; +}; + +static struct u300_mux_hog u300_mux_hogs[] = { + { + .name = "uart0", + .dev = &uart0_device.dev, + }, + { + .name = "spi0", + .dev = &pl022_device.dev, + }, + { + .name = "mmc0", + .dev = &mmcsd_device.dev, + }, +}; + +static int __init u300_pinmux_fetch(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) { + struct pinmux *pmx; + int ret; + + pmx = pinmux_get(u300_mux_hogs[i].dev, NULL); + if (IS_ERR(pmx)) { + pr_err("u300: could not get pinmux hog %s\n", + u300_mux_hogs[i].name); + continue; + } + ret = pinmux_enable(pmx); + if (ret) { + pr_err("u300: could enable pinmux hog %s\n", + u300_mux_hogs[i].name); + continue; + } + u300_mux_hogs[i].pmx = pmx; + } + return 0; +} +subsys_initcall(u300_pinmux_fetch); + /* * Notice that AMBA devices are initialized before platform devices. * @@ -1643,10 +1719,10 @@ static struct platform_device *platform_devs[] __initdata = { &gpio_device, &nand_device, &wdog_device, - &ave_device + &ave_device, + &pinmux_device, }; - /* * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected * together so some interrupts are connected to the first one and some @@ -1828,6 +1904,10 @@ void __init u300_init_devices(void) u300_assign_physmem(); + /* Initialize pinmuxing */ + pinmux_register_mappings(u300_pinmux_map, + ARRAY_SIZE(u300_pinmux_map)); + /* Register subdevices on the I2C buses */ u300_i2c_register_board_devices(); diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h index 7444f5c7da97..6e84f07a7c6f 100644 --- a/arch/arm/mach-u300/include/mach/syscon.h +++ b/arch/arm/mach-u300/include/mach/syscon.h @@ -234,91 +234,6 @@ #define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004) #define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002) #define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001) -/* PAD MUX Control register 1 (LOW) 16bit (R/W) */ -#define U300_SYSCON_PMC1LR (0x007C) -#define U300_SYSCON_PMC1LR_MASK (0xFFFF) -#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000) -#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000) -#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000) -#ifdef CONFIG_MACH_U300_BS335 -#define U300_SYSCON_PMC1LR_CDI_CDI2 (0x8000) -#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO (0xC000) -#elif CONFIG_MACH_U300_BS365 -#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000) -#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000) -#endif -#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000) -#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000) -#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000) -#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000) -#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00) -#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000) -#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400) -#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800) -#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00) -#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300) -#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000) -#define U300_SYSCON_PMC1LR_ETM_APP (0x0100) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C) -#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003) -#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001) -#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002) -#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003) -/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */ -#define U300_SYSCON_PMC1HR (0x007E) -#define U300_SYSCON_PMC1HR_MASK (0xFFFF) -#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000) -#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000) -#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000) -#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0) -#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030) -#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010) -#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020) -#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030) -#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C) -#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004) -#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008) -#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C) -#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003) -#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001) -#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003) /* Step one for killing the applications system 16bit (-/W) */ #define U300_SYSCON_KA1R (0x0080) #define U300_SYSCON_KA1R_MASK (0xFFFF) @@ -357,57 +272,6 @@ #define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE (0x0080) #define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE (0x0040) #define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK (0x003F) -/* Padmux 2 control */ -#define U300_SYSCON_PMC2R (0x100) -#define U300_SYSCON_PMC2R_APP_MISC_0_MASK (0x00C0) -#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM (0x0040) -#define U300_SYSCON_PMC2R_APP_MISC_0_MMC (0x0080) -#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 (0x00C0) -#define U300_SYSCON_PMC2R_APP_MISC_1_MASK (0x0300) -#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM (0x0100) -#define U300_SYSCON_PMC2R_APP_MISC_1_MMC (0x0200) -#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 (0x0300) -#define U300_SYSCON_PMC2R_APP_MISC_2_MASK (0x0C00) -#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM (0x0400) -#define U300_SYSCON_PMC2R_APP_MISC_2_MMC (0x0800) -#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 (0x0C00) -#define U300_SYSCON_PMC2R_APP_MISC_3_MASK (0x3000) -#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM (0x1000) -#define U300_SYSCON_PMC2R_APP_MISC_3_MMC (0x2000) -#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 (0x3000) -#define U300_SYSCON_PMC2R_APP_MISC_4_MASK (0xC000) -#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM (0x4000) -#define U300_SYSCON_PMC2R_APP_MISC_4_MMC (0x8000) -#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO (0xC000) -/* TODO: More SYSCON registers missing */ -#define U300_SYSCON_PMC3R (0x10c) -#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000) -#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000) -#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000) -#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000) -/* TODO: Missing other configs */ -#define U300_SYSCON_PMC4R (0x168) -#define U300_SYSCON_PMC4R_APP_MISC_12_MASK (0x0003) -#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_13_MASK (0x000C) -#define U300_SYSCON_PMC4R_APP_MISC_13_CDI (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA (0x0004) -#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 (0x0008) -#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO (0x000C) -#define U300_SYSCON_PMC4R_APP_MISC_14_MASK (0x0030) -#define U300_SYSCON_PMC4R_APP_MISC_14_CDI (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA (0x0010) -#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 (0x0020) -#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO (0x0030) -#define U300_SYSCON_PMC4R_APP_MISC_16_MASK (0x0300) -#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS (0x0100) -#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N (0x0200) /* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */ #define U300_SYSCON_S0CCR (0x120) #define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF) diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 677ccef5cd32..d5e4a98a9ab8 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -21,7 +21,6 @@ #include <mach/dma_channels.h> #include "mmc.h" -#include "padmux.h" static struct mmci_platform_data mmc0_plat_data = { /* @@ -45,24 +44,9 @@ static struct mmci_platform_data mmc0_plat_data = { int __devinit mmc_init(struct amba_device *adev) { struct device *mmcsd_device = &adev->dev; - struct pmx *pmx; int ret = 0; mmcsd_device->platform_data = &mmc0_plat_data; - /* - * Setup padmuxing for MMC. Since this must always be - * compiled into the kernel, pmx is never released. - */ - pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING); - - if (IS_ERR(pmx)) - pr_warning("Could not get padmux handle\n"); - else { - ret = pmx_activate(mmcsd_device, pmx); - if (IS_ERR_VALUE(ret)) - pr_warning("Could not activate padmuxing\n"); - } - return ret; } diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c deleted file mode 100644 index 4c93c6cefd37..000000000000 --- a/arch/arm/mach-u300/padmux.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * - * arch/arm/mach-u300/padmux.c - * - * - * Copyright (C) 2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * U300 PADMUX functions - * Author: Martin Persson <martin.persson@stericsson.com> - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/mutex.h> -#include <linux/string.h> -#include <linux/bug.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <mach/u300-regs.h> -#include <mach/syscon.h> -#include "padmux.h" - -static DEFINE_MUTEX(pmx_mutex); - -const u32 pmx_registers[] = { - (U300_SYSCON_VBASE + U300_SYSCON_PMC1LR), - (U300_SYSCON_VBASE + U300_SYSCON_PMC1HR), - (U300_SYSCON_VBASE + U300_SYSCON_PMC2R), - (U300_SYSCON_VBASE + U300_SYSCON_PMC3R), - (U300_SYSCON_VBASE + U300_SYSCON_PMC4R) -}; - -/* High level functionality */ - -/* Lazy dog: - * onmask = { - * {"PMC1LR" mask, "PMC1LR" value}, - * {"PMC1HR" mask, "PMC1HR" value}, - * {"PMC2R" mask, "PMC2R" value}, - * {"PMC3R" mask, "PMC3R" value}, - * {"PMC4R" mask, "PMC4R" value} - * } - */ -static struct pmx mmc_setting = { - .setting = U300_APP_PMX_MMC_SETTING, - .default_on = false, - .activated = false, - .name = "MMC", - .onmask = { - {U300_SYSCON_PMC1LR_MMCSD_MASK, - U300_SYSCON_PMC1LR_MMCSD_MMCSD}, - {0, 0}, - {0, 0}, - {0, 0}, - {U300_SYSCON_PMC4R_APP_MISC_12_MASK, - U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO} - }, -}; - -static struct pmx spi_setting = { - .setting = U300_APP_PMX_SPI_SETTING, - .default_on = false, - .activated = false, - .name = "SPI", - .onmask = {{0, 0}, - {U300_SYSCON_PMC1HR_APP_SPI_2_MASK | - U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK | - U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK, - U300_SYSCON_PMC1HR_APP_SPI_2_SPI | - U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI | - U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI}, - {0, 0}, - {0, 0}, - {0, 0} - }, -}; - -/* Available padmux settings */ -static struct pmx *pmx_settings[] = { - &mmc_setting, - &spi_setting, -}; - -static void update_registers(struct pmx *pmx, bool activate) -{ - u16 regval, val, mask; - int i; - - for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) { - if (activate) - val = pmx->onmask[i].val; - else - val = 0; - - mask = pmx->onmask[i].mask; - if (mask != 0) { - regval = readw(pmx_registers[i]); - regval &= ~mask; - regval |= val; - writew(regval, pmx_registers[i]); - } - } -} - -struct pmx *pmx_get(struct device *dev, enum pmx_settings setting) -{ - int i; - struct pmx *pmx = ERR_PTR(-ENOENT); - - if (dev == NULL) - return ERR_PTR(-EINVAL); - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (setting == pmx_settings[i]->setting) { - - if (pmx_settings[i]->dev != NULL) { - WARN(1, "padmux: required setting " - "in use by another consumer\n"); - } else { - pmx = pmx_settings[i]; - pmx->dev = dev; - dev_dbg(dev, "padmux: setting nr %d is now " - "bound to %s and ready to use\n", - setting, dev_name(dev)); - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return pmx; -} -EXPORT_SYMBOL(pmx_get); - -int pmx_put(struct device *dev, struct pmx *pmx) -{ - int i; - int ret = -ENOENT; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx->setting == pmx_settings[i]->setting) { - - if (dev != pmx->dev) { - WARN(1, "padmux: cannot release handle as " - "it is bound to another consumer\n"); - ret = -EINVAL; - break; - } else { - pmx_settings[i]->dev = NULL; - ret = 0; - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return ret; -} -EXPORT_SYMBOL(pmx_put); - -int pmx_activate(struct device *dev, struct pmx *pmx) -{ - int i, j, ret; - ret = 0; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - - /* Make sure the required bits are not used */ - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx) - continue; - - for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - - if (pmx_settings[i]->onmask[j].mask & pmx-> - onmask[j].mask) { - /* More than one entry on the same bits */ - WARN(1, "padmux: cannot activate " - "setting. Bit conflict with " - "an active setting\n"); - - ret = -EUSERS; - goto exit; - } - } - } - update_registers(pmx, true); - pmx->activated = true; - dev_dbg(dev, "padmux: setting nr %d is activated\n", - pmx->setting); - -exit: - mutex_unlock(&pmx_mutex); - return ret; -} -EXPORT_SYMBOL(pmx_activate); - -int pmx_deactivate(struct device *dev, struct pmx *pmx) -{ - int i; - int ret = -ENOENT; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx_settings[i]->dev == NULL) - continue; - - if (pmx->setting == pmx_settings[i]->setting) { - - if (dev != pmx->dev) { - WARN(1, "padmux: cannot deactivate " - "pmx setting as it was activated " - "by another consumer\n"); - - ret = -EBUSY; - continue; - } else { - update_registers(pmx, false); - pmx_settings[i]->dev = NULL; - pmx->activated = false; - ret = 0; - dev_dbg(dev, "padmux: setting nr %d is deactivated", - pmx->setting); - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return ret; -} -EXPORT_SYMBOL(pmx_deactivate); - -/* - * For internal use only. If it is to be exported, - * it should be reentrant. Notice that pmx_activate - * (i.e. runtime settings) always override default settings. - */ -static int pmx_set_default(void) -{ - /* Used to identify several entries on the same bits */ - u16 modbits[ARRAY_SIZE(pmx_registers)]; - - int i, j; - - memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16)); - - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (!pmx_settings[i]->default_on) - continue; - - for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - - /* Make sure there is only one entry on the same bits */ - if (modbits[j] & pmx_settings[i]->onmask[j].mask) { - BUG(); - return -EUSERS; - } - modbits[j] |= pmx_settings[i]->onmask[j].mask; - } - update_registers(pmx_settings[i], true); - } - return 0; -} - -#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) -static int pmx_show(struct seq_file *s, void *data) -{ - int i; - seq_printf(s, "-------------------------------------------------\n"); - seq_printf(s, "SETTING BOUND TO DEVICE STATE\n"); - seq_printf(s, "-------------------------------------------------\n"); - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - /* Format pmx and device name nicely */ - char cdp[33]; - int chars; - - chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name); - while (chars < 16) { - cdp[chars] = ' '; - chars++; - } - chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ? - dev_name(pmx_settings[i]->dev) : "N/A"); - while (chars < 16) { - cdp[chars+16] = ' '; - chars++; - } - cdp[32] = '\0'; - - seq_printf(s, - "%s\t%s\n", - &cdp[0], - pmx_settings[i]->activated ? - "ACTIVATED" : "DEACTIVATED" - ); - - } - mutex_unlock(&pmx_mutex); - return 0; -} - -static int pmx_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmx_show, NULL); -} - -static const struct file_operations pmx_operations = { - .owner = THIS_MODULE, - .open = pmx_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init init_pmx_read_debugfs(void) -{ - /* Expose a simple debugfs interface to view pmx settings */ - (void) debugfs_create_file("padmux", S_IFREG | S_IRUGO, - NULL, NULL, - &pmx_operations); - return 0; -} - -/* - * This needs to come in after the core_initcall(), - * because debugfs is not available until - * the subsystems come up. - */ -module_init(init_pmx_read_debugfs); -#endif - -static int __init pmx_init(void) -{ - int ret; - - ret = pmx_set_default(); - - if (IS_ERR_VALUE(ret)) - pr_crit("padmux: default settings could not be set\n"); - - return 0; -} - -/* Should be initialized before consumers */ -core_initcall(pmx_init); diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h deleted file mode 100644 index 6e8b86064097..000000000000 --- a/arch/arm/mach-u300/padmux.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * arch/arm/mach-u300/padmux.h - * - * - * Copyright (C) 2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * U300 PADMUX API - * Author: Martin Persson <martin.persson@stericsson.com> - */ - -#ifndef __MACH_U300_PADMUX_H -#define __MACH_U300_PADMUX_H - -enum pmx_settings { - U300_APP_PMX_MMC_SETTING, - U300_APP_PMX_SPI_SETTING -}; - -struct pmx_onmask { - u16 mask; /* Mask bits */ - u16 val; /* Value when active */ -}; - -struct pmx { - struct device *dev; - enum pmx_settings setting; - char *name; - bool activated; - bool default_on; - struct pmx_onmask onmask[]; -}; - -struct pmx *pmx_get(struct device *dev, enum pmx_settings setting); -int pmx_put(struct device *dev, struct pmx *pmx); -int pmx_activate(struct device *dev, struct pmx *pmx); -int pmx_deactivate(struct device *dev, struct pmx *pmx); - -#endif diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c index 7b597e2b19e2..a1affacfa59c 100644 --- a/arch/arm/mach-u300/spi.c +++ b/arch/arm/mach-u300/spi.c @@ -14,8 +14,6 @@ #include <mach/coh901318.h> #include <mach/dma_channels.h> -#include "padmux.h" - /* * The following is for the actual devices on the SSP/SPI bus */ @@ -95,25 +93,7 @@ static struct pl022_ssp_controller ssp_platform_data = { void __init u300_spi_init(struct amba_device *adev) { - struct pmx *pmx; - adev->dev.platform_data = &ssp_platform_data; - /* - * Setup padmuxing for SPI. Since this must always be - * compiled into the kernel, pmx is never released. - */ - pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING); - - if (IS_ERR(pmx)) - dev_warn(&adev->dev, "Could not get padmux handle\n"); - else { - int ret; - - ret = pmx_activate(&adev->dev, pmx); - if (IS_ERR_VALUE(ret)) - dev_warn(&adev->dev, "Could not activate padmuxing\n"); - } - } void __init u300_spi_register_board_devices(void) diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 4210cb434dbc..a3e0c8692f0d 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -6,6 +6,7 @@ config UX500_SOC_COMMON select ARM_GIC select HAS_MTU select ARM_ERRATA_753970 + select ARM_ERRATA_754322 menu "Ux500 SoC" diff --git a/arch/arm/mach-ux500/Makefile.boot b/arch/arm/mach-ux500/Makefile.boot index c7e75acfe6c9..ff0a4b5b0a82 100644 --- a/arch/arm/mach-ux500/Makefile.boot +++ b/arch/arm/mach-ux500/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index a33df5f4c27a..eb5199102cfa 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -156,12 +156,10 @@ void __init smp_init_cpus(void) ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ - if (ncores > NR_CPUS) { - printk(KERN_WARNING - "U8500: no. of cores (%d) greater than configured " - "maximum of %d - clipping\n", - ncores, NR_CPUS); - ncores = NR_CPUS; + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) diff --git a/arch/arm/mach-versatile/Makefile.boot b/arch/arm/mach-versatile/Makefile.boot index c7e75acfe6c9..ff0a4b5b0a82 100644 --- a/arch/arm/mach-versatile/Makefile.boot +++ b/arch/arm/mach-versatile/Makefile.boot @@ -1,4 +1,4 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot index 07c2d9c457ec..8630b3d10a4d 100644 --- a/arch/arm/mach-vexpress/Makefile.boot +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x60008000 + zreladdr-y += 0x60008000 params_phys-y := 0x60000100 initrd_phys-y := 0x60800000 diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index bfd32f52c2db..2b1e836a76ed 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -221,6 +221,12 @@ static void ct_ca9x4_init_cpu_map(void) { int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU)); + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c index ea4cbfb90a66..3668cf91d2de 100644 --- a/arch/arm/mach-vexpress/hotplug.c +++ b/arch/arm/mach-vexpress/hotplug.c @@ -13,6 +13,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/system.h> extern volatile int pen_release; @@ -62,13 +63,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) * code will have already disabled interrupts */ for (;;) { - /* - * here's the WFI - */ - asm(".word 0xe320f003\n" - : - : - : "memory", "cc"); + wfi(); if (pen_release == cpu) { /* diff --git a/arch/arm/mach-vexpress/include/mach/io.h b/arch/arm/mach-vexpress/include/mach/io.h index 748bb524ee71..13522d86685e 100644 --- a/arch/arm/mach-vexpress/include/mach/io.h +++ b/arch/arm/mach-vexpress/include/mach/io.h @@ -20,8 +20,6 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffffffff - #define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 9e6b93b1a043..d0d267a8d3f9 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -318,6 +318,10 @@ static struct clk v2m_sp804_clk = { .rate = 1000000, }; +static struct clk v2m_ref_clk = { + .rate = 32768, +}; + static struct clk dummy_apb_pclk; static struct clk_lookup v2m_lookups[] = { @@ -348,6 +352,9 @@ static struct clk_lookup v2m_lookups[] = { }, { /* CLCD */ .dev_id = "mb:clcd", .clk = &osc1_clk, + }, { /* SP805 WDT */ + .dev_id = "mb:wdt", + .clk = &v2m_ref_clk, }, { /* SP804 timers */ .dev_id = "sp804", .con_id = "v2m-timer0", diff --git a/arch/arm/mach-vt8500/Makefile.boot b/arch/arm/mach-vt8500/Makefile.boot index a8acc4e24902..b79c41cdfdff 100644 --- a/arch/arm/mach-vt8500/Makefile.boot +++ b/arch/arm/mach-vt8500/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x01000000 diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h index 9077239f78c9..46181eecf273 100644 --- a/arch/arm/mach-vt8500/include/mach/io.h +++ b/arch/arm/mach-vt8500/include/mach/io.h @@ -20,8 +20,6 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffff - #define __io(a) __typesafe_io((a) + 0xf0000000) #define __mem_pci(a) (a) diff --git a/arch/arm/mach-w90x900/Makefile.boot b/arch/arm/mach-w90x900/Makefile.boot index a057b546b6e5..6c3d421c2d11 100644 --- a/arch/arm/mach-w90x900/Makefile.boot +++ b/arch/arm/mach-w90x900/Makefile.boot @@ -1,3 +1,3 @@ -zreladdr-y := 0x00008000 +zreladdr-y += 0x00008000 params_phys-y := 0x00000100 diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c index 83c56324a472..0a235e502330 100644 --- a/arch/arm/mach-w90x900/cpu.c +++ b/arch/arm/mach-w90x900/cpu.c @@ -60,7 +60,7 @@ static DEFINE_CLK(emc, 7); static DEFINE_SUBCLK(rmii, 2); static DEFINE_CLK(usbd, 8); static DEFINE_CLK(usbh, 9); -static DEFINE_CLK(g2d, 10);; +static DEFINE_CLK(g2d, 10); static DEFINE_CLK(pwm, 18); static DEFINE_CLK(ps2, 24); static DEFINE_CLK(kpi, 25); diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot index 67039c3e0c48..760a0efe7580 100644 --- a/arch/arm/mach-zynq/Makefile.boot +++ b/arch/arm/mach-zynq/Makefile.boot @@ -1,3 +1,3 @@ - zreladdr-y := 0x00008000 + zreladdr-y += 0x00008000 params_phys-y := 0x00000100 initrd_phys-y := 0x00800000 diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S index 52162d59407a..2cbf68ef0e83 100644 --- a/arch/arm/mm/abort-macro.S +++ b/arch/arm/mm/abort-macro.S @@ -17,7 +17,7 @@ cmp \tmp, # 0x5600 @ Is it ldrsb? orreq \tmp, \tmp, #1 << 11 @ Set L-bit if yes tst \tmp, #1 << 11 @ L = 0 -> write - orreq \psr, \psr, #1 << 11 @ yes. + orreq \fsr, \fsr, #1 << 11 @ yes. b do_DataAbort not_thumb: .endm diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index cfbcf8b95599..c335c76e0d88 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -86,16 +86,6 @@ core_param(alignment, ai_usermode, int, 0600); #define UM_FIXUP (1 << 1) #define UM_SIGNAL (1 << 2) -#ifdef CONFIG_PROC_FS -static const char *usermode_action[] = { - "ignored", - "warn", - "fixup", - "fixup+warn", - "signal", - "signal+warn" -}; - /* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned(void) { @@ -123,6 +113,16 @@ static int safe_usermode(int new_usermode, bool warn) return new_usermode; } +#ifdef CONFIG_PROC_FS +static const char *usermode_action[] = { + "ignored", + "warn", + "fixup", + "fixup+warn", + "signal", + "signal+warn" +}; + static int alignment_proc_show(struct seq_file *m, void *v) { seq_printf(m, "User:\t\t%lu\n", ai_user); diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 44c086710d2b..8ac9e9f84790 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -16,9 +16,12 @@ * 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/err.h> #include <linux/init.h> #include <linux/spinlock.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> @@ -26,15 +29,23 @@ #define CACHE_LINE_SIZE 32 static void __iomem *l2x0_base; -static DEFINE_SPINLOCK(l2x0_lock); +static DEFINE_RAW_SPINLOCK(l2x0_lock); static uint32_t l2x0_way_mask; /* Bitmask of active ways */ static uint32_t l2x0_size; +struct l2x0_regs l2x0_saved_regs; + +struct l2x0_of_data { + void (*setup)(const struct device_node *, __u32 *, __u32 *); + void (*save)(void); + void (*resume)(void); +}; + static inline void cache_wait_way(void __iomem *reg, unsigned long mask) { /* wait for cache operation by line or way to complete */ while (readl_relaxed(reg) & mask) - ; + cpu_relax(); } #ifdef CONFIG_CACHE_PL310 @@ -115,9 +126,9 @@ static void l2x0_cache_sync(void) { unsigned long flags; - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void __l2x0_flush_all(void) @@ -134,9 +145,9 @@ static void l2x0_flush_all(void) unsigned long flags; /* clean all ways */ - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); __l2x0_flush_all(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_clean_all(void) @@ -144,11 +155,11 @@ static void l2x0_clean_all(void) unsigned long flags; /* clean all ways */ - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY); cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_inv_all(void) @@ -156,13 +167,13 @@ static void l2x0_inv_all(void) unsigned long flags; /* invalidate all ways */ - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); /* Invalidating when L2 is enabled is a nono */ BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1); writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_inv_range(unsigned long start, unsigned long end) @@ -170,7 +181,7 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) void __iomem *base = l2x0_base; unsigned long flags; - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); if (start & (CACHE_LINE_SIZE - 1)) { start &= ~(CACHE_LINE_SIZE - 1); debug_writel(0x03); @@ -195,13 +206,13 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) } if (blk_end < end) { - spin_unlock_irqrestore(&l2x0_lock, flags); - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); } } cache_wait(base + L2X0_INV_LINE_PA, 1); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_clean_range(unsigned long start, unsigned long end) @@ -214,7 +225,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) return; } - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { unsigned long blk_end = start + min(end - start, 4096UL); @@ -225,13 +236,13 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) } if (blk_end < end) { - spin_unlock_irqrestore(&l2x0_lock, flags); - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); } } cache_wait(base + L2X0_CLEAN_LINE_PA, 1); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_flush_range(unsigned long start, unsigned long end) @@ -244,7 +255,7 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) return; } - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { unsigned long blk_end = start + min(end - start, 4096UL); @@ -257,24 +268,43 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) debug_writel(0x00); if (blk_end < end) { - spin_unlock_irqrestore(&l2x0_lock, flags); - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); } } cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); cache_sync(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); } static void l2x0_disable(void) { unsigned long flags; - spin_lock_irqsave(&l2x0_lock, flags); + raw_spin_lock_irqsave(&l2x0_lock, flags); __l2x0_flush_all(); writel_relaxed(0, l2x0_base + L2X0_CTRL); dsb(); - spin_unlock_irqrestore(&l2x0_lock, flags); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static void l2x0_unlock(__u32 cache_id) +{ + int lockregs; + int i; + + if (cache_id == L2X0_CACHE_ID_PART_L310) + lockregs = 8; + else + /* L210 and unknown types */ + lockregs = 1; + + for (i = 0; i < lockregs; i++) { + writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE + + i * L2X0_LOCKDOWN_STRIDE); + writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE + + i * L2X0_LOCKDOWN_STRIDE); + } } void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) @@ -328,10 +358,14 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) * accessing the below registers will fault. */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + /* Make sure that I&D is not locked down when starting */ + l2x0_unlock(cache_id); /* l2x0 controller is disabled */ writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); + l2x0_saved_regs.aux_ctrl = aux; + l2x0_inv_all(); /* enable L2X0 */ @@ -351,3 +385,202 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", ways, cache_id, aux, l2x0_size); } + +#ifdef CONFIG_OF +static void __init l2x0_of_setup(const struct device_node *np, + __u32 *aux_val, __u32 *aux_mask) +{ + u32 data[2] = { 0, 0 }; + u32 tag = 0; + u32 dirty = 0; + u32 val = 0, mask = 0; + + of_property_read_u32(np, "arm,tag-latency", &tag); + if (tag) { + mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK; + val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT; + } + + of_property_read_u32_array(np, "arm,data-latency", + data, ARRAY_SIZE(data)); + if (data[0] && data[1]) { + mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | + L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK; + val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) | + ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT); + } + + of_property_read_u32(np, "arm,dirty-latency", &dirty); + if (dirty) { + mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK; + val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; + } + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + +static void __init pl310_of_setup(const struct device_node *np, + __u32 *aux_val, __u32 *aux_mask) +{ + u32 data[3] = { 0, 0, 0 }; + u32 tag[3] = { 0, 0, 0 }; + u32 filter[2] = { 0, 0 }; + + of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); + if (tag[0] && tag[1] && tag[2]) + writel_relaxed( + ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | + ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | + ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), + l2x0_base + L2X0_TAG_LATENCY_CTRL); + + of_property_read_u32_array(np, "arm,data-latency", + data, ARRAY_SIZE(data)); + if (data[0] && data[1] && data[2]) + writel_relaxed( + ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | + ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | + ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), + l2x0_base + L2X0_DATA_LATENCY_CTRL); + + of_property_read_u32_array(np, "arm,filter-ranges", + filter, ARRAY_SIZE(filter)); + if (filter[1]) { + writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), + l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN, + l2x0_base + L2X0_ADDR_FILTER_START); + } +} + +static void __init pl310_save(void) +{ + u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base + + L2X0_TAG_LATENCY_CTRL); + l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base + + L2X0_DATA_LATENCY_CTRL); + l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base + + L2X0_ADDR_FILTER_END); + l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base + + L2X0_ADDR_FILTER_START); + + if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { + /* + * From r2p0, there is Prefetch offset/control register + */ + l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base + + L2X0_PREFETCH_CTRL); + /* + * From r3p0, there is Power control register + */ + if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) + l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base + + L2X0_POWER_CTRL); + } +} + +static void l2x0_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + /* restore aux ctrl and enable l2 */ + l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); + + writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + writel_relaxed(1, l2x0_base + L2X0_CTRL); + } +} + +static void pl310_resume(void) +{ + u32 l2x0_revision; + + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + /* restore pl310 setup */ + writel_relaxed(l2x0_saved_regs.tag_latency, + l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.data_latency, + l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.filter_end, + l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed(l2x0_saved_regs.filter_start, + l2x0_base + L2X0_ADDR_FILTER_START); + + l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + l2x0_base + L2X0_PREFETCH_CTRL); + if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) + writel_relaxed(l2x0_saved_regs.pwr_ctrl, + l2x0_base + L2X0_POWER_CTRL); + } + } + + l2x0_resume(); +} + +static const struct l2x0_of_data pl310_data = { + pl310_of_setup, + pl310_save, + pl310_resume, +}; + +static const struct l2x0_of_data l2x0_data = { + l2x0_of_setup, + NULL, + l2x0_resume, +}; + +static const struct of_device_id l2x0_ids[] __initconst = { + { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, + { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, + { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data }, + {} +}; + +int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) +{ + struct device_node *np; + struct l2x0_of_data *data; + struct resource res; + + np = of_find_matching_node(NULL, l2x0_ids); + if (!np) + return -ENODEV; + + if (of_address_to_resource(np, 0, &res)) + return -ENODEV; + + l2x0_base = ioremap(res.start, resource_size(&res)); + if (!l2x0_base) + return -ENOMEM; + + l2x0_saved_regs.phy_base = res.start; + + data = of_match_node(l2x0_ids, np)->data; + + /* L2 configuration can only be changed if the cache is disabled */ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + if (data->setup) + data->setup(np, &aux_val, &aux_mask); + } + + if (data->save) + data->save(); + + l2x0_init(l2x0_base, aux_val, aux_mask); + + outer_cache.resume = data->resume; + return 0; +} +#endif diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 3b24bfa3b828..07c4bc8ea0a4 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -174,6 +174,10 @@ ENTRY(v7_coherent_user_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r12, r0, r3 +#ifdef CONFIG_ARM_ERRATA_764369 + ALT_SMP(W(dsb)) + ALT_UP(W(nop)) +#endif 1: USER( mcr p15, 0, r12, c7, c11, 1 ) @ clean D line to the point of unification add r12, r12, r2 @@ -223,6 +227,10 @@ ENTRY(v7_flush_kern_dcache_area) add r1, r0, r1 sub r3, r2, #1 bic r0, r0, r3 +#ifdef CONFIG_ARM_ERRATA_764369 + ALT_SMP(W(dsb)) + ALT_UP(W(nop)) +#endif 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line add r0, r0, r2 @@ -247,6 +255,10 @@ v7_dma_inv_range: sub r3, r2, #1 tst r0, r3 bic r0, r0, r3 +#ifdef CONFIG_ARM_ERRATA_764369 + ALT_SMP(W(dsb)) + ALT_UP(W(nop)) +#endif mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line tst r1, r3 @@ -270,6 +282,10 @@ v7_dma_clean_range: dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 +#ifdef CONFIG_ARM_ERRATA_764369 + ALT_SMP(W(dsb)) + ALT_UP(W(nop)) +#endif 1: mcr p15, 0, r0, c7, c10, 1 @ clean D / U line add r0, r0, r2 @@ -288,6 +304,10 @@ ENTRY(v7_dma_flush_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 +#ifdef CONFIG_ARM_ERRATA_764369 + ALT_SMP(W(dsb)) + ALT_UP(W(nop)) +#endif 1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line add r0, r0, r2 diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index b0ee9ba3cfab..93aac068da94 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -16,7 +16,7 @@ #include <asm/mmu_context.h> #include <asm/tlbflush.h> -static DEFINE_SPINLOCK(cpu_asid_lock); +static DEFINE_RAW_SPINLOCK(cpu_asid_lock); unsigned int cpu_last_asid = ASID_FIRST_VERSION; #ifdef CONFIG_SMP DEFINE_PER_CPU(struct mm_struct *, current_mm); @@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm); void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) { mm->context.id = 0; - spin_lock_init(&mm->context.id_lock); + raw_spin_lock_init(&mm->context.id_lock); } static void flush_context(void) @@ -58,7 +58,7 @@ static void set_mm_context(struct mm_struct *mm, unsigned int asid) * the broadcast. This function is also called via IPI so the * mm->context.id_lock has to be IRQ-safe. */ - spin_lock_irqsave(&mm->context.id_lock, flags); + raw_spin_lock_irqsave(&mm->context.id_lock, flags); if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) { /* * Old version of ASID found. Set the new one and @@ -67,7 +67,7 @@ static void set_mm_context(struct mm_struct *mm, unsigned int asid) mm->context.id = asid; cpumask_clear(mm_cpumask(mm)); } - spin_unlock_irqrestore(&mm->context.id_lock, flags); + raw_spin_unlock_irqrestore(&mm->context.id_lock, flags); /* * Set the mm_cpumask(mm) bit for the current CPU. @@ -117,7 +117,7 @@ void __new_context(struct mm_struct *mm) { unsigned int asid; - spin_lock(&cpu_asid_lock); + raw_spin_lock(&cpu_asid_lock); #ifdef CONFIG_SMP /* * Check the ASID again, in case the change was broadcast from @@ -125,7 +125,7 @@ void __new_context(struct mm_struct *mm) */ if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) { cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); - spin_unlock(&cpu_asid_lock); + raw_spin_unlock(&cpu_asid_lock); return; } #endif @@ -153,5 +153,5 @@ void __new_context(struct mm_struct *mm) } set_mm_context(mm, asid); - spin_unlock(&cpu_asid_lock); + raw_spin_unlock(&cpu_asid_lock); } diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index b8061519ce77..7d0a8c230342 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -30,7 +30,7 @@ #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ L_PTE_MT_MINICACHE) -static DEFINE_SPINLOCK(minicache_lock); +static DEFINE_RAW_SPINLOCK(minicache_lock); /* * ARMv4 mini-dcache optimised copy_user_highpage @@ -76,14 +76,14 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from, if (!test_and_set_bit(PG_dcache_clean, &from->flags)) __flush_dcache_page(page_mapping(from), from); - spin_lock(&minicache_lock); + raw_spin_lock(&minicache_lock); set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); flush_tlb_kernel_page(0xffff8000); mc_copy_user_page((void *)0xffff8000, kto); - spin_unlock(&minicache_lock); + raw_spin_unlock(&minicache_lock); kunmap_atomic(kto, KM_USER1); } diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 63cca0097130..3d9a1552cef6 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -27,7 +27,7 @@ #define from_address (0xffff8000) #define to_address (0xffffc000) -static DEFINE_SPINLOCK(v6_lock); +static DEFINE_RAW_SPINLOCK(v6_lock); /* * Copy the user page. No aliasing to deal with so we can just @@ -88,7 +88,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to, * Now copy the page using the same cache colour as the * pages ultimate destination. */ - spin_lock(&v6_lock); + raw_spin_lock(&v6_lock); set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0); set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0); @@ -101,7 +101,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to, copy_page((void *)kto, (void *)kfrom); - spin_unlock(&v6_lock); + raw_spin_unlock(&v6_lock); } /* @@ -121,13 +121,13 @@ static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vad * Now clear the page using the same cache colour as * the pages ultimate destination. */ - spin_lock(&v6_lock); + raw_spin_lock(&v6_lock); set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0); flush_tlb_kernel_page(to); clear_page((void *)to); - spin_unlock(&v6_lock); + raw_spin_unlock(&v6_lock); } struct cpu_user_fns v6_user_fns __initdata = { diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index 649bbcd325bf..610c24ced310 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -32,7 +32,7 @@ #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ L_PTE_MT_MINICACHE) -static DEFINE_SPINLOCK(minicache_lock); +static DEFINE_RAW_SPINLOCK(minicache_lock); /* * XScale mini-dcache optimised copy_user_highpage @@ -98,14 +98,14 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from, if (!test_and_set_bit(PG_dcache_clean, &from->flags)) __flush_dcache_page(page_mapping(from), from); - spin_lock(&minicache_lock); + raw_spin_lock(&minicache_lock); set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); flush_tlb_kernel_page(COPYPAGE_MINICACHE); mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); - spin_unlock(&minicache_lock); + raw_spin_unlock(&minicache_lock); kunmap_atomic(kto, KM_USER1); } diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 0a0a1e7c20d2..235eb775fc78 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -123,8 +123,8 @@ static void __dma_free_buffer(struct page *page, size_t size) #endif #define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) -#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) -#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) +#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PMD_SHIFT) +#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PMD_SHIFT) /* * These are the page tables (2MB each) covering uncached, DMA consistent allocations @@ -183,7 +183,7 @@ static int __init consistent_init(void) } consistent_pte[i++] = pte; - base += (1 << PGDIR_SHIFT); + base += PMD_SIZE; } while (base < CONSISTENT_END); return ret; @@ -324,6 +324,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, if (addr) *handle = pfn_to_dma(dev, page_to_pfn(page)); + else + __dma_free_buffer(page, size); return addr; } diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 3b5ea68acbb8..aa33949fef60 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -20,6 +20,7 @@ #include <linux/highmem.h> #include <linux/perf_event.h> +#include <asm/exception.h> #include <asm/system.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 91bca355cd31..f8037ba338ac 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -298,7 +298,7 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, #ifdef CONFIG_HAVE_ARCH_PFN_VALID int pfn_valid(unsigned long pfn) { - return memblock_is_memory(pfn << PAGE_SHIFT); + return memblock_is_memory(__pfn_to_phys(pfn)); } EXPORT_SYMBOL(pfn_valid); #endif @@ -496,6 +496,13 @@ static void __init free_unused_memmap(struct meminfo *mi) */ bank_start = min(bank_start, ALIGN(prev_bank_end, PAGES_PER_SECTION)); +#else + /* + * Align down here since the VM subsystem insists that the + * memmap entries are valid from the bank start aligned to + * MAX_ORDER_NR_PAGES. + */ + bank_start = round_down(bank_start, MAX_ORDER_NR_PAGES); #endif /* * If we had a previous bank, and there is a space diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index ab506272b2d3..bdb248c4f55c 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -289,6 +289,27 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) } EXPORT_SYMBOL(__arm_ioremap); +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space as memory. Needed when the kernel wants to execute + * code in external memory. This is needed for reprogramming source + * clocks that would affect normal memory for example. Please see + * CONFIG_GENERIC_ALLOCATOR for allocating external memory. + */ +void __iomem * +__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) +{ + unsigned int mtype; + + if (cached) + mtype = MT_MEMORY; + else + mtype = MT_MEMORY_NONCACHED; + + return __arm_ioremap_caller(phys_addr, size, mtype, + __builtin_return_address(0)); +} + void __iounmap(volatile void __iomem *io_addr) { void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 010566799c80..ad7cce3bc431 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -12,8 +12,8 @@ static inline pmd_t *pmd_off_k(unsigned long virt) struct mem_type { pteval_t prot_pte; - unsigned int prot_l1; - unsigned int prot_sect; + pmdval_t prot_l1; + pmdval_t prot_sect; unsigned int domain; }; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 594d677b92c8..226f1804be12 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -60,7 +60,7 @@ EXPORT_SYMBOL(pgprot_kernel); struct cachepolicy { const char policy[16]; unsigned int cr_mask; - unsigned int pmd; + pmdval_t pmd; pteval_t pte; }; @@ -288,7 +288,7 @@ static void __init build_mem_type_table(void) { struct cachepolicy *cp; unsigned int cr = get_cr(); - unsigned int user_pgprot, kern_pgprot, vecs_pgprot; + pteval_t user_pgprot, kern_pgprot, vecs_pgprot; int cpu_arch = cpu_architecture(); int i; @@ -863,14 +863,14 @@ static inline void prepare_page_table(void) /* * Clear out all the mappings below the kernel image. */ - for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE) + for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ - addr = ((unsigned long)_etext + PGDIR_SIZE - 1) & PGDIR_MASK; + addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK; #endif - for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE) + for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); /* @@ -885,10 +885,12 @@ static inline void prepare_page_table(void) * memory bank, up to the end of the vmalloc region. */ for (addr = __phys_to_virt(end); - addr < VMALLOC_END; addr += PGDIR_SIZE) + addr < VMALLOC_END; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); } +#define SWAPPER_PG_DIR_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) + /* * Reserve the special regions of memory */ @@ -898,7 +900,7 @@ void __init arm_mm_memblock_reserve(void) * Reserve the page tables. These are already in use, * and can only be in node 0. */ - memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); + memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE); #ifdef CONFIG_SA1111 /* @@ -926,7 +928,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) */ vectors_page = early_alloc(PAGE_SIZE); - for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) + for (addr = VMALLOC_END; addr; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); /* diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 92bd102e3982..2e6849b41f66 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -379,7 +379,7 @@ ENTRY(cpu_arm920_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm920_suspend_size -.equ cpu_arm920_suspend_size, 4 * 3 +.equ cpu_arm920_suspend_size, 4 * 4 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_arm920_do_suspend) stmfd sp!, {r4 - r7, lr} diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 2bbcf053dffd..cd8f79c3a282 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -394,7 +394,7 @@ ENTRY(cpu_arm926_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm926_suspend_size -.equ cpu_arm926_suspend_size, 4 * 3 +.equ cpu_arm926_suspend_size, 4 * 4 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_arm926_do_suspend) stmfd sp!, {r4 - r7, lr} diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 07219c2ae114..69e7f2ef7384 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -182,11 +182,11 @@ ENDPROC(cpu_sa1100_do_suspend) ENTRY(cpu_sa1100_do_resume) ldmia r0, {r4 - r7} @ load cp regs - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs - mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache - mcr p15, 0, r1, c9, c0, 0 @ invalidate RB - mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB + mov ip, #0 + mcr p15, 0, ip, c8, c7, 0 @ flush I+D TLBs + mcr p15, 0, ip, c7, c7, 0 @ flush I&D cache + mcr p15, 0, ip, c9, c0, 0 @ invalidate RB + mcr p15, 0, ip, c9, c0, 5 @ allow user space to use RB mcr p15, 0, r4, c3, c0, 0 @ domain ID mcr p15, 0, r5, c2, c0, 0 @ translation table base addr diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 219138d2f158..a923aa0fd00d 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -223,6 +223,22 @@ __v6_setup: mrc p15, 0, r0, c1, c0, 0 @ read control register bic r0, r0, r5 @ clear bits them orr r0, r0, r6 @ set them +#ifdef CONFIG_ARM_ERRATA_364296 + /* + * Workaround for the 364296 ARM1136 r0p2 erratum (possible cache data + * corruption with hit-under-miss enabled). The conditional code below + * (setting the undocumented bit 31 in the auxiliary control register + * and the FI bit in the control register) disables hit-under-miss + * without putting the processor into full low interrupt latency mode. + */ + ldr r6, =0x4107b362 @ id for ARM1136 r0p2 + mrc p15, 0, r5, c0, c0, 0 @ get processor id + teq r5, r6 @ check for the faulty core + mrceq p15, 0, r5, c1, c0, 1 @ load aux control reg + orreq r5, r5, #(1 << 31) @ set the undocumented bit 31 + mcreq p15, 0, r5, c1, c0, 1 @ write aux control reg + orreq r0, r0, #(1 << 21) @ low interrupt latency configuration +#endif mov pc, lr @ return to head.S:__ret /* diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index a30e78542ccf..9591c8e9fb8c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -66,6 +66,7 @@ ENDPROC(cpu_v7_proc_fin) ENTRY(cpu_v7_reset) mrc p15, 0, r1, c1, c0, 0 @ ctrl register bic r1, r1, #0x1 @ ...............m + THUMB( bic r1, r1, #1 << 30 ) @ SCTLR.TE (Thumb exceptions) mcr p15, 0, r1, c1, c0, 0 @ disable MMU isb mov pc, r0 @@ -217,7 +218,7 @@ ENDPROC(cpu_v7_set_pte_ext) /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */ .globl cpu_v7_suspend_size .equ cpu_v7_suspend_size, 4 * 9 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_v7_do_suspend) stmfd sp!, {r4 - r11, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID @@ -247,13 +248,16 @@ ENTRY(cpu_v7_do_resume) mcr p15, 0, r7, c2, c0, 0 @ TTB 0 mcr p15, 0, r8, c2, c0, 1 @ TTB 1 mcr p15, 0, ip, c2, c0, 2 @ TTB control register - mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register + mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register + teq r4, r10 @ Is it already set? + mcrne p15, 0, r10, c1, c0, 1 @ No, so write it mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control ldr r4, =PRRR @ PRRR ldr r5, =NMRR @ NMRR mcr p15, 0, r4, c10, c2, 0 @ write PRRR mcr p15, 0, r5, c10, c2, 1 @ write NMRR isb + dsb mov r0, r9 @ control register mov r2, r7, lsr #14 @ get TTB0 base mov r2, r2, lsl #14 diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 28c72a2006a1..755e1bf22681 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -406,7 +406,7 @@ ENTRY(cpu_xsc3_set_pte_ext) .align .globl cpu_xsc3_suspend_size -.equ cpu_xsc3_suspend_size, 4 * 8 +.equ cpu_xsc3_suspend_size, 4 * 7 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_xsc3_do_suspend) stmfd sp!, {r4 - r10, lr} @@ -418,12 +418,12 @@ ENTRY(cpu_xsc3_do_suspend) mrc p15, 0, r9, c1, c0, 1 @ auxiliary control reg mrc p15, 0, r10, c1, c0, 0 @ control reg bic r4, r4, #2 @ clear frequency change bit - stmia r0, {r1, r4 - r10} @ store v:p offset + cp regs + stmia r0, {r4 - r10} @ store cp regs ldmia sp!, {r4 - r10, pc} ENDPROC(cpu_xsc3_do_suspend) ENTRY(cpu_xsc3_do_resume) - ldmia r0, {r1, r4 - r10} @ load v:p offset + cp regs + ldmia r0, {r4 - r10} @ load cp regs mov ip, #0 mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index a5353fc0793f..4c8fdbcc9467 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -39,7 +39,7 @@ config ARCH_MX503 select ARCH_MX50_SUPPORTED select ARCH_MX53_SUPPORTED help - This enables support for machines using Freescale's i.MX50 and i.MX51 + This enables support for machines using Freescale's i.MX50 and i.MX53 processors. config ARCH_MX51 diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c index 0d6ed31bdbf2..a34b2ae895f2 100644 --- a/arch/arm/plat-mxc/devices.c +++ b/arch/arm/plat-mxc/devices.c @@ -37,59 +37,6 @@ int __init mxc_register_device(struct platform_device *pdev, void *data) return ret; } -struct platform_device *__init imx_add_platform_device_dmamask( - const char *name, int id, - const struct resource *res, unsigned int num_resources, - const void *data, size_t size_data, u64 dmamask) -{ - int ret = -ENOMEM; - struct platform_device *pdev; - - pdev = platform_device_alloc(name, id); - if (!pdev) - goto err; - - if (dmamask) { - /* - * This memory isn't freed when the device is put, - * I don't have a nice idea for that though. Conceptually - * dma_mask in struct device should not be a pointer. - * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 - */ - pdev->dev.dma_mask = - kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); - if (!pdev->dev.dma_mask) - /* ret is still -ENOMEM; */ - goto err; - - *pdev->dev.dma_mask = dmamask; - pdev->dev.coherent_dma_mask = dmamask; - } - - if (res) { - ret = platform_device_add_resources(pdev, res, num_resources); - if (ret) - goto err; - } - - if (data) { - ret = platform_device_add_data(pdev, data, size_data); - if (ret) - goto err; - } - - ret = platform_device_add(pdev); - if (ret) { -err: - if (dmamask) - kfree(pdev->dev.dma_mask); - platform_device_put(pdev); - return ERR_PTR(ret); - } - - return pdev; -} - struct device mxc_aips_bus = { .init_name = "mxc_aips", .parent = &platform_bus, diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 524538aabc4b..543525d76a60 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -14,10 +14,22 @@ extern struct device mxc_aips_bus; extern struct device mxc_ahb_bus; -struct platform_device *imx_add_platform_device_dmamask( +static inline struct platform_device *imx_add_platform_device_dmamask( const char *name, int id, const struct resource *res, unsigned int num_resources, - const void *data, size_t size_data, u64 dmamask); + const void *data, size_t size_data, u64 dmamask) +{ + struct platform_device_info pdevinfo = { + .name = name, + .id = id, + .res = res, + .num_res = num_resources, + .data = data, + .size_data = size_data, + .dma_mask = dmamask, + }; + return platform_device_register_full(&pdevinfo); +} static inline struct platform_device *imx_add_platform_device( const char *name, int id, diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index bb8f4a6b3e37..5b605a9eb091 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -14,6 +14,7 @@ config ARCH_OMAP1 select CLKDEV_LOOKUP select CLKSRC_MMIO select GENERIC_IRQ_CHIP + select HAVE_IDE help "Systems based on omap7xx, omap15xx or omap16xx" diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index b6b409744954..02609eee0562 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -615,6 +615,9 @@ static int _od_resume_noirq(struct device *dev) return pm_generic_resume_noirq(dev); } +#else +#define _od_suspend_noirq NULL +#define _od_resume_noirq NULL #endif static struct dev_pm_domain omap_device_pm_domain = { @@ -622,7 +625,8 @@ static struct dev_pm_domain omap_device_pm_domain = { SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, _od_runtime_idle) USE_PLATFORM_PM_SLEEP_OPS - SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq) + .suspend_noirq = _od_suspend_noirq, + .resume_noirq = _od_resume_noirq, } }; diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 9843c954c042..9a197e55f669 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -22,7 +22,6 @@ config PLAT_S5P select PLAT_SAMSUNG select SAMSUNG_CLKSRC select SAMSUNG_IRQ_VIC_TIMER - select SAMSUNG_IRQ_UART help Base platform code for Samsung's S5P series SoC. diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index 02af235298e2..5f84a3f13ef9 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -192,7 +192,7 @@ unsigned long s5p_spdif_get_rate(struct clk *clk) if (IS_ERR(pclk)) return -EINVAL; - rate = pclk->ops->get_rate(clk); + rate = pclk->ops->get_rate(pclk); clk_put(pclk); return rate; diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c index afaf87fdb93e..c9308db36183 100644 --- a/arch/arm/plat-s5p/dev-uart.c +++ b/arch/arm/plat-s5p/dev-uart.c @@ -32,20 +32,10 @@ static struct resource s5p_uart0_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX0, - .end = IRQ_S5P_UART_RX0, + .start = IRQ_UART0, + .end = IRQ_UART0, .flags = IORESOURCE_IRQ, }, - [2] = { - .start = IRQ_S5P_UART_TX0, - .end = IRQ_S5P_UART_TX0, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR0, - .end = IRQ_S5P_UART_ERR0, - .flags = IORESOURCE_IRQ, - } }; static struct resource s5p_uart1_resource[] = { @@ -55,18 +45,8 @@ static struct resource s5p_uart1_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX1, - .end = IRQ_S5P_UART_RX1, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S5P_UART_TX1, - .end = IRQ_S5P_UART_TX1, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR1, - .end = IRQ_S5P_UART_ERR1, + .start = IRQ_UART1, + .end = IRQ_UART1, .flags = IORESOURCE_IRQ, }, }; @@ -78,18 +58,8 @@ static struct resource s5p_uart2_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX2, - .end = IRQ_S5P_UART_RX2, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S5P_UART_TX2, - .end = IRQ_S5P_UART_TX2, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR2, - .end = IRQ_S5P_UART_ERR2, + .start = IRQ_UART2, + .end = IRQ_UART2, .flags = IORESOURCE_IRQ, }, }; @@ -102,18 +72,8 @@ static struct resource s5p_uart3_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX3, - .end = IRQ_S5P_UART_RX3, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S5P_UART_TX3, - .end = IRQ_S5P_UART_TX3, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR3, - .end = IRQ_S5P_UART_ERR3, + .start = IRQ_UART3, + .end = IRQ_UART3, .flags = IORESOURCE_IRQ, }, #endif @@ -127,18 +87,8 @@ static struct resource s5p_uart4_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX4, - .end = IRQ_S5P_UART_RX4, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S5P_UART_TX4, - .end = IRQ_S5P_UART_TX4, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR4, - .end = IRQ_S5P_UART_ERR4, + .start = IRQ_UART4, + .end = IRQ_UART4, .flags = IORESOURCE_IRQ, }, #endif @@ -152,18 +102,8 @@ static struct resource s5p_uart5_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_S5P_UART_RX5, - .end = IRQ_S5P_UART_RX5, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_S5P_UART_TX5, - .end = IRQ_S5P_UART_TX5, - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = IRQ_S5P_UART_ERR5, - .end = IRQ_S5P_UART_ERR5, + .start = IRQ_UART5, + .end = IRQ_UART5, .flags = IORESOURCE_IRQ, }, #endif diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h index ba9121c60a2a..144dbfc6506d 100644 --- a/arch/arm/plat-s5p/include/plat/irqs.h +++ b/arch/arm/plat-s5p/include/plat/irqs.h @@ -37,41 +37,6 @@ #define IRQ_VIC1_BASE S5P_VIC1_BASE #define IRQ_VIC2_BASE S5P_VIC2_BASE -/* UART interrupts, each UART has 4 intterupts per channel so - * use the space between the ISA and S3C main interrupts. Note, these - * are not in the same order as the S3C24XX series! */ - -#define IRQ_S5P_UART_BASE0 (16) -#define IRQ_S5P_UART_BASE1 (20) -#define IRQ_S5P_UART_BASE2 (24) -#define IRQ_S5P_UART_BASE3 (28) - -#define UART_IRQ_RXD (0) -#define UART_IRQ_ERR (1) -#define UART_IRQ_TXD (2) - -#define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD) -#define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD) -#define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR) - -#define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD) -#define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD) -#define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR) - -#define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD) -#define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD) -#define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR) - -#define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD) -#define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD) -#define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR) - -/* S3C compatibilty defines */ -#define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0 -#define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1 -#define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2 -#define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3 - /* VIC based IRQs */ #define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x)) diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c index 327ab9f662e8..c65eb791d1bb 100644 --- a/arch/arm/plat-s5p/irq-gpioint.c +++ b/arch/arm/plat-s5p/irq-gpioint.c @@ -23,6 +23,8 @@ #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> +#include <asm/mach/irq.h> + #define GPIO_BASE(chip) (((unsigned long)(chip)->base) & 0xFFFFF000u) #define CON_OFFSET 0x700 @@ -81,6 +83,9 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) int group, pend_offset, mask_offset; unsigned int pend, mask; + struct irq_chip *chip = irq_get_chip(irq); + chained_irq_enter(chip, desc); + for (group = 0; group < bank->nr_groups; group++) { struct s3c_gpio_chip *chip = bank->chips[group]; if (!chip) @@ -102,23 +107,25 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) pend &= ~BIT(offset); } } + chained_irq_exit(chip, desc); } static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) { static int used_gpioint_groups = 0; int group = chip->group; - struct s5p_gpioint_bank *bank = NULL; + struct s5p_gpioint_bank *b, *bank = NULL; struct irq_chip_generic *gc; struct irq_chip_type *ct; if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) return -ENOMEM; - list_for_each_entry(bank, &banks, list) { - if (group >= bank->start && - group < bank->start + bank->nr_groups) + list_for_each_entry(b, &banks, list) { + if (group >= b->start && group < b->start + b->nr_groups) { + bank = b; break; + } } if (!bank) return -EINVAL; @@ -156,9 +163,9 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) ct->chip.irq_mask = irq_gc_mask_set_bit; ct->chip.irq_unmask = irq_gc_mask_clr_bit; ct->chip.irq_set_type = s5p_gpioint_set_type, - ct->regs.ack = PEND_OFFSET + REG_OFFSET(chip->group); - ct->regs.mask = MASK_OFFSET + REG_OFFSET(chip->group); - ct->regs.type = CON_OFFSET + REG_OFFSET(chip->group); + ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start); + ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start); + ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start); irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST | IRQ_NOPROBE, 0); diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c index a97c08957f49..afdaa1082b9f 100644 --- a/arch/arm/plat-s5p/irq.c +++ b/arch/arm/plat-s5p/irq.c @@ -17,42 +17,10 @@ #include <asm/hardware/vic.h> -#include <linux/serial_core.h> #include <mach/map.h> #include <plat/regs-timer.h> -#include <plat/regs-serial.h> #include <plat/cpu.h> #include <plat/irq-vic-timer.h> -#include <plat/irq-uart.h> - -/* - * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] - * are consecutive when looking up the interrupt in the demux routines. - */ -static struct s3c_uart_irq uart_irqs[] = { - [0] = { - .regs = S5P_VA_UART0, - .base_irq = IRQ_S5P_UART_BASE0, - .parent_irq = IRQ_UART0, - }, - [1] = { - .regs = S5P_VA_UART1, - .base_irq = IRQ_S5P_UART_BASE1, - .parent_irq = IRQ_UART1, - }, - [2] = { - .regs = S5P_VA_UART2, - .base_irq = IRQ_S5P_UART_BASE2, - .parent_irq = IRQ_UART2, - }, -#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 - [3] = { - .regs = S5P_VA_UART3, - .base_irq = IRQ_S5P_UART_BASE3, - .parent_irq = IRQ_UART3, - }, -#endif -}; void __init s5p_init_irq(u32 *vic, u32 num_vic) { @@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) #endif s3c_init_vic_timer_irq(5, IRQ_TIMER0); - - s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); } diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index b3e10659e4b8..dffa37bc4a0b 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER help Internal configuration to build the VIC timer interrupt code. -config SAMSUNG_IRQ_UART - bool - help - Internal configuration to build the IRQ UART demux code. - # options for gpio configuration support config SAMSUNG_GPIOLIB_4BIT diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 853764ba8cc5..1105922342fe 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -21,7 +21,6 @@ obj-y += dev-asocdma.o obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o -obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o # ADC diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 302c42670bd1..3b4451979d1b 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -64,6 +64,17 @@ static LIST_HEAD(clocks); */ DEFINE_SPINLOCK(clocks_lock); +/* Global watchdog clock used by arch_wtd_reset() callback */ +struct clk *s3c2410_wdtclk; +static int __init s3c_wdt_reset_init(void) +{ + s3c2410_wdtclk = clk_get(NULL, "watchdog"); + if (IS_ERR(s3c2410_wdtclk)) + printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__); + return 0; +} +arch_initcall(s3c_wdt_reset_init); + /* enable and disable calls for use with the clk struct */ static int clk_null_enable(struct clk *clk, int enable) diff --git a/arch/arm/plat-samsung/include/plat/backlight.h b/arch/arm/plat-samsung/include/plat/backlight.h index 51d8da846a62..ad530c78fe8c 100644 --- a/arch/arm/plat-samsung/include/plat/backlight.h +++ b/arch/arm/plat-samsung/include/plat/backlight.h @@ -20,7 +20,7 @@ struct samsung_bl_gpio_info { int func; }; -extern void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, +extern void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, struct platform_pwm_backlight_data *bl_data); #endif /* __ASM_PLAT_BACKLIGHT_H */ diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 87d5b38a86fb..73c66d4d10fa 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -9,6 +9,9 @@ * published by the Free Software Foundation. */ +#ifndef __ASM_PLAT_CLOCK_H +#define __ASM_PLAT_CLOCK_H __FILE__ + #include <linux/spinlock.h> #include <linux/clkdev.h> @@ -121,3 +124,8 @@ extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); extern void s3c_pwmclk_init(void); +/* Global watchdog clock used by arch_wtd_reset() callback */ + +extern struct clk *s3c2410_wdtclk; + +#endif /* __ASM_PLAT_CLOCK_H */ diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index bac36fa3becb..720734847027 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -186,6 +186,11 @@ #define S3C64XX_UINTSP 0x34 #define S3C64XX_UINTM 0x38 +#define S3C64XX_UINTM_RXD (0) +#define S3C64XX_UINTM_TXD (2) +#define S3C64XX_UINTM_RXD_MSK (1 << S3C64XX_UINTM_RXD) +#define S3C64XX_UINTM_TXD_MSK (1 << S3C64XX_UINTM_TXD) + /* Following are specific to S5PV210 */ #define S5PV210_UCON_CLKMASK (1<<10) #define S5PV210_UCON_PCLK (0<<10) diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h index 54b762acb5a0..40dbb2b0ae22 100644 --- a/arch/arm/plat-samsung/include/plat/watchdog-reset.h +++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include <plat/clock.h> #include <plat/regs-watchdog.h> #include <mach/map.h> @@ -19,17 +20,12 @@ static inline void arch_wdt_reset(void) { - struct clk *wdtclk; - printk("arch_reset: attempting watchdog reset\n"); __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ - wdtclk = clk_get(NULL, "watchdog"); - if (!IS_ERR(wdtclk)) { - clk_enable(wdtclk); - } else - printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__); + if (s3c2410_wdtclk) + clk_enable(s3c2410_wdtclk); /* put initial values into count and data */ __raw_writel(0x80, S3C2410_WTCNT); diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c deleted file mode 100644 index 3014c7226bd1..000000000000 --- a/arch/arm/plat-samsung/irq-uart.c +++ /dev/null @@ -1,96 +0,0 @@ -/* arch/arm/plat-samsung/irq-uart.c - * originally part of arch/arm/plat-s3c64xx/irq.c - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * Samsung- UART Interrupt handling - * - * 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/kernel.h> -#include <linux/interrupt.h> -#include <linux/serial_core.h> -#include <linux/irq.h> -#include <linux/io.h> - -#include <asm/mach/irq.h> - -#include <mach/map.h> -#include <plat/irq-uart.h> -#include <plat/regs-serial.h> -#include <plat/cpu.h> - -/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] - * are consecutive when looking up the interrupt in the demux routines. - */ -static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) -{ - struct s3c_uart_irq *uirq = desc->irq_data.handler_data; - struct irq_chip *chip = irq_get_chip(irq); - u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); - int base = uirq->base_irq; - - chained_irq_enter(chip, desc); - - if (pend & (1 << 0)) - generic_handle_irq(base); - if (pend & (1 << 1)) - generic_handle_irq(base + 1); - if (pend & (1 << 2)) - generic_handle_irq(base + 2); - if (pend & (1 << 3)) - generic_handle_irq(base + 3); - - chained_irq_exit(chip, desc); -} - -static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) -{ - void __iomem *reg_base = uirq->regs; - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - /* mask all interrupts at the start. */ - __raw_writel(0xf, reg_base + S3C64XX_UINTM); - - gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base, - handle_level_irq); - - if (!gc) { - pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", - __func__, uirq->base_irq); - return; - } - - ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->regs.ack = S3C64XX_UINTP; - ct->regs.mask = S3C64XX_UINTM; - irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); - - irq_set_handler_data(uirq->parent_irq, uirq); - irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); -} - -/** - * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing - * @irq: The interrupt data for registering - * @nr_irqs: The number of interrupt descriptions in @irq. - * - * Register the UART interrupts specified by @irq including the demuxing - * routines. This supports the S3C6400 and newer style of devices. - */ -void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) -{ - for (; nr_irqs > 0; nr_irqs--, irq++) - s3c_init_uart_irq(irq); -} diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index f714d060370d..51583cd30164 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -22,9 +22,14 @@ #include <plat/irq-vic-timer.h> #include <plat/regs-timer.h> +#include <asm/mach/irq.h> + static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) { + struct irq_chip *chip = irq_get_chip(irq); + chained_irq_enter(chip, desc); generic_handle_irq((int)desc->irq_data.handler_data); + chained_irq_exit(chip, desc); } /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index fff68d0d521b..5bdeef969847 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,10 +12,9 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# XXX: This is a cut-down version of the file; it contains only machines that -# XXX: are in mainline or have been submitted to the machine database within -# XXX: the last 12 months. If your entry is missing please email rmk at -# XXX: <linux@arm.linux.org.uk> +# This is a cut-down version of the file; it contains only machines that +# are merged into mainline or have been edited in the machine database +# within the last 12 months. References to machine_is_NAME() do not count! # # Last update: Sat May 7 08:48:24 2011 # @@ -65,6 +64,7 @@ h7201 ARCH_H7201 H7201 161 h7202 ARCH_H7202 H7202 162 iq80321 ARCH_IQ80321 IQ80321 169 ks8695 ARCH_KS8695 KS8695 180 +karo ARCH_KARO KARO 190 smdk2410 ARCH_SMDK2410 SMDK2410 193 ceiva ARCH_CEIVA CEIVA 200 voiceblue MACH_VOICEBLUE VOICEBLUE 218 @@ -188,6 +188,7 @@ omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900 davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901 palmz72 MACH_PALMZ72 PALMZ72 904 nxdb500 MACH_NXDB500 NXDB500 905 +apf9328 MACH_APF9328 APF9328 906 palmt5 MACH_PALMT5 PALMT5 917 palmtc MACH_PALMTC PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 @@ -271,10 +272,12 @@ pcm038 MACH_PCM038 PCM038 1551 ts_x09 MACH_TS209 TS209 1565 at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566 mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574 +vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578 terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584 linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585 e350 MACH_E350 E350 1596 ts409 MACH_TS409 TS409 1601 +rsi_ews MACH_RSI_EWS RSI_EWS 1609 cm_x300 MACH_CM_X300 CM_X300 1616 at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624 smdk6410 MACH_SMDK6410 SMDK6410 1626 @@ -331,6 +334,7 @@ smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 saar MACH_SAAR SAAR 1828 at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830 +usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841 mxlads MACH_MXLADS MXLADS 1851 linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858 afeb9260 MACH_AFEB9260 AFEB9260 1859 @@ -351,7 +355,7 @@ centro MACH_CENTRO CENTRO 1944 nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955 omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 -eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 +eukrea_cpuimx27 MACH_EUKREA_CPUIMX27 EUKREA_CPUIMX27 1975 acs5k MACH_ACS5K ACS5K 1982 snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987 dsm320 MACH_DSM320 DSM320 1988 @@ -369,6 +373,7 @@ pcm043 MACH_PCM043 PCM043 2072 sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 +tx37 MACH_TX37 TX37 2127 rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138 ts219 MACH_TS219 TS219 2139 @@ -379,6 +384,7 @@ omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160 magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162 btmavb101 MACH_BTMAVB101 BTMAVB101 2172 btmawb101 MACH_BTMAWB101 BTMAWB101 2173 +tx25 MACH_TX25 TX25 2177 omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178 anw6410 MACH_ANW6410 ANW6410 2183 imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187 @@ -423,6 +429,7 @@ raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 tnetv107x MACH_TNETV107X TNETV107X 2418 +mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428 smdkv210 MACH_SMDKV210 SMDKV210 2456 omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464 omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465 @@ -433,14 +440,17 @@ omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495 ts41x MACH_TS41X TS41X 2502 phy3250 MACH_PHY3250 PHY3250 2511 mini6410 MACH_MINI6410 MINI6410 2520 +tx51 MACH_TX51 TX51 2529 mx28evk MACH_MX28EVK MX28EVK 2531 smartq5 MACH_SMARTQ5 SMARTQ5 2534 davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 riot_x37 MACH_RIOT_X37 RIOT_X37 2578 +pca101 MACH_PCA101 PCA101 2595 capc7117 MACH_CAPC7117 CAPC7117 2612 icontrol MACH_ICONTROL ICONTROL 2624 +gplugd MACH_GPLUGD GPLUGD 2625 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 mx23evk MACH_MX23EVK MX23EVK 2629 ap4evb MACH_AP4EVB AP4EVB 2630 @@ -476,8 +486,8 @@ cns3420vb MACH_CNS3420VB CNS3420VB 2776 omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791 ti8168evm MACH_TI8168EVM TI8168EVM 2800 teton_bga MACH_TETON_BGA TETON_BGA 2816 -eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25 EUKREA_CPUIMX25 2820 -eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35 EUKREA_CPUIMX35 2821 +eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25SD EUKREA_CPUIMX25SD 2820 +eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821 eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 smdkc210 MACH_SMDKC210 SMDKC210 2838 @@ -1113,3 +1123,5 @@ blissc MACH_BLISSC BLISSC 3491 thales_adc MACH_THALES_ADC THALES_ADC 3492 ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493 atdgp318 MACH_ATDGP318 ATDGP318 3494 +smdk4212 MACH_SMDK4212 SMDK4212 3638 +smdk4412 MACH_SMDK4412 SMDK4412 3765 diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index 6de73aab0195..a81404c09d5d 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,7 +7,7 @@ # ccflags-y := -DDEBUG # asflags-y := -DDEBUG -KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) +KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft) LDFLAGS +=--no-warn-mismatch obj-y += vfp.o diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index c7fd394d28a4..6eba53530d1c 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -158,7 +158,7 @@ sys_call_table: .long sys_sched_rr_get_interval .long sys_nanosleep .long sys_poll - .long sys_nfsservctl /* 145 */ + .long sys_ni_syscall /* 145 was nfsservctl */ .long sys_setresgid .long sys_getresgid .long sys_prctl diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 225d311c9701..e4137297b790 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1543,7 +1543,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* for vm86 */ .long _sys_ni_syscall /* old "query_module" */ .long _sys_ni_syscall /* sys_poll */ - .long _sys_nfsservctl + .long _sys_ni_syscall /* old nfsservctl */ .long _sys_setresgid /* setresgid16 */ /* 170 */ .long _sys_getresgid /* getresgid16 */ .long _sys_prctl diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 17addacb169e..408b055c585f 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -282,8 +282,8 @@ config ETRAX_RTC Enables drivers for the Real-Time Clock battery-backed chips on some products. The kernel reads the time when booting, and the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a - rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc - device. You can check the time with cat /proc/rtc, but + rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the + /dev/rtc device. You can check the time with cat /proc/rtc, but normal time reading should be done using libc function time and friends. diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig index adc164e99339..df9a38b4f18f 100644 --- a/arch/cris/arch-v10/Kconfig +++ b/arch/cris/arch-v10/Kconfig @@ -24,8 +24,8 @@ config ETRAX_PA_LEDS help The ETRAX network driver is responsible for flashing LED's when packets arrive and are sent. It uses macros defined in - <file:include/asm-cris/io.h>, and those macros are defined after what - YOU choose in this option. The actual bits used are configured + <file:arch/cris/include/asm/io.h>, and those macros are defined after + what YOU choose in this option. The actual bits used are configured separately. Select this if the LEDs are on port PA. Some products put the leds on PB or a memory-mapped latch (CSP0) instead. @@ -34,8 +34,8 @@ config ETRAX_PB_LEDS help The ETRAX network driver is responsible for flashing LED's when packets arrive and are sent. It uses macros defined in - <file:include/asm-cris/io.h>, and those macros are defined after what - YOU choose in this option. The actual bits used are configured + <file:arch/cris/include/asm/io.h>, and those macros are defined after + what YOU choose in this option. The actual bits used are configured separately. Select this if the LEDs are on port PB. Some products put the leds on PA or a memory-mapped latch (CSP0) instead. @@ -44,8 +44,8 @@ config ETRAX_CSP0_LEDS help The ETRAX network driver is responsible for flashing LED's when packets arrive and are sent. It uses macros defined in - <file:include/asm-cris/io.h>, and those macros are defined after what - YOU choose in this option. The actual bits used are configured + <file:arch/cris/include/asm/io.h>, and those macros are defined after + what YOU choose in this option. The actual bits used are configured separately. Select this if the LEDs are on a memory-mapped latch using chip select CSP0, this is mapped at 0x90000000. Some products put the leds on PA or PB instead. diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 0d7221779923..32d90867a984 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -4,6 +4,7 @@ config ETRAX_ETHERNET bool "Ethernet support" depends on ETRAX_ARCH_V10 select NET_ETHERNET + select NET_CORE select MII help This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index 1161883eb582..592fbe9dfb62 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S @@ -771,7 +771,7 @@ sys_call_table: .long sys_ni_syscall /* sys_vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index 41a2732e8b9c..e47e9c3401b0 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -4,6 +4,7 @@ config ETRAX_ETHERNET bool "Ethernet support" depends on ETRAX_ARCH_V32 select NET_ETHERNET + select NET_CORE select MII help This option enables the ETRAX FS built-in 10/100Mbit Ethernet diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 84fed7e91ada..c3ea4694fbaf 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -714,7 +714,7 @@ sys_call_table: .long sys_ni_syscall /* sys_vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* Old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/cris/arch-v32/lib/nand_init.S b/arch/cris/arch-v32/lib/nand_init.S deleted file mode 100644 index d671fed451c9..000000000000 --- a/arch/cris/arch-v32/lib/nand_init.S +++ /dev/null @@ -1,178 +0,0 @@ -##============================================================================= -## -## nand_init.S -## -## The bootrom copies data from the NAND flash to the internal RAM but -## due to a bug/feature we can only trust the 256 first bytes. So this -## code copies more data from NAND flash to internal RAM. Obvioulsy this -## code must fit in the first 256 bytes so alter with care. -## -## Some notes about the bug/feature for future reference: -## The bootrom copies the first 127 KB from NAND flash to internal -## memory. The problem is that it does a bytewise copy. NAND flashes -## does autoincrement on the address so for a 16-bite device each -## read/write increases the address by two. So the copy loop in the -## bootrom will discard every second byte. This is solved by inserting -## zeroes in every second byte in the first erase block. -## -## The bootrom also incorrectly assumes that it can read the flash -## linear with only one read command but the flash will actually -## switch between normal area and spare area if you do that so we -## can't trust more than the first 256 bytes. -## -##============================================================================= - -#include <arch/hwregs/asm/reg_map_asm.h> -#include <arch/hwregs/asm/gio_defs_asm.h> -#include <arch/hwregs/asm/pinmux_defs_asm.h> -#include <arch/hwregs/asm/bif_core_defs_asm.h> -#include <arch/hwregs/asm/config_defs_asm.h> - -;; There are 8-bit NAND flashes and 16-bit NAND flashes. -;; We need to treat them slightly different. -#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 -#define PAGE_SIZE 256 -#else -#error 2 -#define PAGE_SIZE 512 -#endif -#define ERASE_BLOCK 16384 - -;; GPIO pins connected to NAND flash -#define CE 4 -#define CLE 5 -#define ALE 6 -#define BY 7 - -;; Address space for NAND flash -#define NAND_RD_ADDR 0x90000000 -#define NAND_WR_ADDR 0x94000000 - -#define READ_CMD 0x00 - -;; Readability macros -#define CSP_MASK \ - REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \ - REG_MASK(bif_core, rw_grp3_cfg, gated_csp1) -#define CSP_VAL \ - REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \ - REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr) - -;;---------------------------------------------------------------------------- -;; Macros to set/clear GPIO bits - -.macro SET x - or.b (1<<\x),$r9 - move.d $r9, [$r2] -.endm - -.macro CLR x - and.b ~(1<<\x),$r9 - move.d $r9, [$r2] -.endm - -;;---------------------------------------------------------------------------- - -nand_boot: - ;; Check if nand boot was selected - move.d REG_ADDR(config, regi_config, r_bootsel), $r0 - move.d [$r0], $r0 - and.d REG_MASK(config, r_bootsel, boot_mode), $r0 - cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0 - bne normal_boot ; No NAND boot - nop - -copy_nand_to_ram: - ;; copy_nand_to_ram - ;; Arguments - ;; r10 - destination - ;; r11 - source offset - ;; r12 - size - ;; r13 - Address to jump to after completion - ;; Note : r10-r12 are clobbered on return - ;; Registers used: - ;; r0 - NAND_RD_ADDR - ;; r1 - NAND_WR_ADDR - ;; r2 - reg_gio_rw_pa_dout - ;; r3 - reg_gio_r_pa_din - ;; r4 - tmp - ;; r5 - byte counter within a page - ;; r6 - reg_pinmux_rw_pa - ;; r7 - reg_gio_rw_pa_oe - ;; r8 - reg_bif_core_rw_grp3_cfg - ;; r9 - reg_gio_rw_pa_dout shadow - move.d 0x90000000, $r0 - move.d 0x94000000, $r1 - move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2 - move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3 - move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6 - move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7 - move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8 - -#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 - lsrq 1, $r11 -#endif - ;; Set up GPIO - move.d [$r2], $r9 - move.d [$r7], $r4 - or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4 - move.d $r4, [$r7] - - ;; Set up bif - move.d [$r8], $r4 - and.d CSP_MASK, $r4 - or.d CSP_VAL, $r4 - move.d $r4, [$r8] - -1: ;; Copy one page - CLR CE - SET CLE - moveq READ_CMD, $r4 - move.b $r4, [$r1] - moveq 20, $r4 -2: bne 2b - subq 1, $r4 - CLR CLE - SET ALE - clear.w [$r1] ; Column address = 0 - move.d $r11, $r4 - lsrq 8, $r4 - move.b $r4, [$r1] ; Row address - lsrq 8, $r4 - move.b $r4, [$r1] ; Row address - moveq 20, $r4 -2: bne 2b - subq 1, $r4 - CLR ALE -2: move.d [$r3], $r4 - and.d 1 << BY, $r4 - beq 2b - movu.w PAGE_SIZE, $r5 -2: ; Copy one byte/word -#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 - move.w [$r0], $r4 -#else - move.b [$r0], $r4 -#endif - subq 1, $r5 - bne 2b -#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 - move.w $r4, [$r10+] - subu.w PAGE_SIZE*2, $r12 -#else - move.b $r4, [$r10+] - subu.w PAGE_SIZE, $r12 -#endif - bpl 1b - addu.w PAGE_SIZE, $r11 - - ;; End of copy - jump $r13 - nop - - ;; This will warn if the code above is too large. If you consider - ;; to remove this you don't understand the bug/feature. - .org 256 - .org ERASE_BLOCK - -normal_boot: diff --git a/arch/cris/include/asm/serial.h b/arch/cris/include/asm/serial.h new file mode 100644 index 000000000000..af7535a955fb --- /dev/null +++ b/arch/cris/include/asm/serial.h @@ -0,0 +1,9 @@ +#ifndef _ASM_SERIAL_H +#define _ASM_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + */ +#define BASE_BAUD (1843200 / 16) + +#endif /* _ASM_SERIAL_H */ diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 017d6d7b784f..5ba23f715ea5 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1358,7 +1358,7 @@ sys_call_table: .long sys_ni_syscall /* for vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* Old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 091ed6192ae8..d1f377f5d3b6 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -160,7 +160,7 @@ config VT_CONSOLE config HW_CONSOLE bool - depends on VT && !S390 && !UM + depends on VT default y comment "Unix98 PTY support" @@ -195,7 +195,7 @@ config UNIX98_PTYS source "drivers/char/pcmcia/Kconfig" -source "drivers/serial/Kconfig" +source "drivers/tty/serial/Kconfig" source "drivers/i2c/Kconfig" diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index f4b2e67bcc34..4be2ea2fbe26 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S @@ -183,7 +183,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_query_module */ .long SYMBOL_NAME(sys_poll) - .long SYMBOL_NAME(sys_nfsservctl) + .long SYMBOL_NAME(sys_ni_syscall) /* old nfsservctl */ .long SYMBOL_NAME(sys_setresgid16) /* 170 */ .long SYMBOL_NAME(sys_getresgid16) .long SYMBOL_NAME(sys_prctl) diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index 0e5cd1405e0e..43ab1cd097a5 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -234,4 +234,4 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_T10DIF=y CONFIG_MISC_DEVICES=y -CONFIG_DMAR=y +CONFIG_INTEL_IOMMU=y diff --git a/arch/ia64/dig/Makefile b/arch/ia64/dig/Makefile index 2f7caddf093e..ae16ec4f6308 100644 --- a/arch/ia64/dig/Makefile +++ b/arch/ia64/dig/Makefile @@ -6,7 +6,7 @@ # obj-y := setup.o -ifeq ($(CONFIG_DMAR), y) +ifeq ($(CONFIG_INTEL_IOMMU), y) obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o else obj-$(CONFIG_IA64_GENERIC) += machvec.o diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index 80241fe03f50..f5f4ef149aac 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -915,7 +915,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) * @dir: R/W or both. * @attrs: optional dma attributes * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static dma_addr_t sba_map_page(struct device *dev, struct page *page, unsigned long poff, size_t size, @@ -1044,7 +1044,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size) * @dir: R/W or both. * @attrs: optional dma attributes * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) @@ -1127,7 +1127,7 @@ void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, * @size: number of bytes mapped in driver buffer. * @dma_handle: IOVA of new buffer. * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void * sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags) @@ -1190,7 +1190,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp * @vaddr: virtual address IOVA of "consistent" buffer. * @dma_handler: IO virtual address of "consistent" buffer. * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) @@ -1453,7 +1453,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, * @dir: R/W or both. * @attrs: optional dma attributes * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction dir, @@ -1549,7 +1549,7 @@ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, * @dir: R/W or both. * @attrs: optional dma attributes * - * See Documentation/PCI/PCI-DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction dir, diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 7e81966ce481..47afcc61f6e5 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -172,7 +172,7 @@ static const struct net_device_ops simeth_netdev_ops = { .ndo_stop = simeth_close, .ndo_start_xmit = simeth_tx, .ndo_get_stats = simeth_get_stats, - .ndo_set_multicast_list = set_multicast_list, /* not yet used */ + .ndo_set_rx_mode = set_multicast_list, /* not yet used */ }; diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h index d66d446b127c..d05e78f6db94 100644 --- a/arch/ia64/include/asm/device.h +++ b/arch/ia64/include/asm/device.h @@ -10,7 +10,7 @@ struct dev_archdata { #ifdef CONFIG_ACPI void *acpi_handle; #endif -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU void *iommu; /* hook for IOMMU specific extension */ #endif }; diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h index 745e095fe82e..105c93b00b1b 100644 --- a/arch/ia64/include/asm/iommu.h +++ b/arch/ia64/include/asm/iommu.h @@ -7,12 +7,14 @@ extern void pci_iommu_shutdown(void); extern void no_iommu_init(void); +#ifdef CONFIG_INTEL_IOMMU extern int force_iommu, no_iommu; -extern int iommu_detected; -#ifdef CONFIG_DMAR extern int iommu_pass_through; +extern int iommu_detected; #else #define iommu_pass_through (0) +#define no_iommu (1) +#define iommu_detected (0) #endif extern void iommu_dma_init(void); extern void machvec_init(const char *name); diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 73b5f785e70c..127dd7be346a 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h @@ -139,7 +139,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); } -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU extern void pci_iommu_alloc(void); #endif #endif /* _ASM_IA64_PCI_H */ diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 395c2f216dd8..d959c84904be 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper endif -obj-$(CONFIG_DMAR) += pci-dma.o +obj-$(CONFIG_INTEL_IOMMU) += pci-dma.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_BINFMT_ELF) += elfcore.o diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 3be485a300b1..bfb4d01e0e51 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -88,7 +88,7 @@ acpi_get_sysname(void) struct acpi_table_rsdp *rsdp; struct acpi_table_xsdt *xsdt; struct acpi_table_header *hdr; -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU u64 i, nentries; #endif @@ -125,7 +125,7 @@ acpi_get_sysname(void) return "xen"; } -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU /* Look for Intel IOMMU */ nentries = (hdr->length - sizeof(*hdr)) / sizeof(xsdt->table_offset_entry[0]); diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 97dd2abdeb1a..198c753d1006 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1614,7 +1614,7 @@ sys_call_table: data8 sys_sched_get_priority_min data8 sys_sched_rr_get_interval data8 sys_nanosleep - data8 sys_nfsservctl + data8 sys_ni_syscall // old nfsservctl data8 sys_prctl // 1170 data8 sys_getpagesize data8 sys_mmap2 diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 009df5434a7a..94e0db72d4a6 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -131,7 +131,7 @@ void arch_teardown_msi_irq(unsigned int irq) return ia64_teardown_msi_irq(irq); } -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU #ifdef CONFIG_SMP static int dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) @@ -210,5 +210,5 @@ int arch_setup_dmar_msi(unsigned int irq) "edge"); return 0; } -#endif /* CONFIG_DMAR */ +#endif /* CONFIG_INTEL_IOMMU */ diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index f6b1ff0aea76..c16162c70860 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -14,7 +14,7 @@ #include <asm/system.h> -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU #include <linux/kernel.h> diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index b92b9445255d..6c4e9aaa70c1 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -10,6 +10,7 @@ config M32R select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_ATOMIC64 config SBUS bool diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S index 528f2e6ad064..f365c19795ef 100644 --- a/arch/m32r/kernel/syscall_table.S +++ b/arch/m32r/kernel/syscall_table.S @@ -168,7 +168,7 @@ ENTRY(sys_call_table) .long sys_tas /* vm86 syscall holder */ .long sys_ni_syscall /* query_module syscall holder */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* was nfsservctl */ .long sys_setresgid /* 170 */ .long sys_getresgid .long sys_prctl diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 9e8ee9d2b8ca..6c28582fb98f 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -21,6 +21,15 @@ config ARCH_HAS_ILOG2_U32 config ARCH_HAS_ILOG2_U64 bool +config GENERIC_CLOCKEVENTS + bool + +config GENERIC_CMOS_UPDATE + def_bool !MMU + +config GENERIC_GPIO + bool + config GENERIC_HWEIGHT bool default y @@ -29,10 +38,16 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_IOMAP + def_bool MMU + config TIME_LOW_RES bool default y +config ARCH_USES_GETTIMEOFFSET + def_bool MMU + config NO_IOPORT def_bool y @@ -62,13 +77,31 @@ config MMU Select if you want MMU-based virtualised addressing space support by paged memory management. If unsure, say 'Y'. -menu "Platform dependent setup" +config MMU_MOTOROLA + bool + +config MMU_SUN3 + bool + depends on MMU && !MMU_MOTOROLA + +menu "Platform setup" + +source arch/m68k/Kconfig.cpu + +source arch/m68k/Kconfig.machine + +source arch/m68k/Kconfig.bus + +endmenu + +menu "Kernel Features" -if MMU -source arch/m68k/Kconfig.mmu +if COLDFIRE +source "kernel/Kconfig.preempt" endif -if !MMU -source arch/m68k/Kconfig.nommu + +if !MMU || COLDFIRE +source "kernel/time/Kconfig" endif source "mm/Kconfig" @@ -85,9 +118,9 @@ if !MMU menu "Power management options" config PM - bool "Power Management support" - help - Support processor power management modes + bool "Power Management support" + help + Support processor power management modes endmenu endif @@ -96,151 +129,7 @@ source "net/Kconfig" source "drivers/Kconfig" -if MMU - -menu "Character devices" - -config ATARI_MFPSER - tristate "Atari MFP serial support" - depends on ATARI - ---help--- - If you like to use the MFP serial ports ("Modem1", "Serial1") under - Linux, say Y. The driver equally supports all kinds of MFP serial - ports and automatically detects whether Serial1 is available. - - To compile this driver as a module, choose M here. - - Note for Falcon users: You also have an MFP port, it's just not - wired to the outside... But you could use the port under Linux. - -config ATARI_MIDI - tristate "Atari MIDI serial support" - depends on ATARI - help - If you want to use your Atari's MIDI port in Linux, say Y. - - To compile this driver as a module, choose M here. - -config ATARI_DSP56K - tristate "Atari DSP56k support (EXPERIMENTAL)" - depends on ATARI && EXPERIMENTAL - help - If you want to be able to use the DSP56001 in Falcons, say Y. This - driver is still experimental, and if you don't know what it is, or - if you don't have this processor, just say N. - - To compile this driver as a module, choose M here. - -config AMIGA_BUILTIN_SERIAL - tristate "Amiga builtin serial support" - depends on AMIGA - help - If you want to use your Amiga's built-in serial port in Linux, - answer Y. - - To compile this driver as a module, choose M here. - -config MULTIFACE_III_TTY - tristate "Multiface Card III serial support" - depends on AMIGA - help - If you want to use a Multiface III card's serial port in Linux, - answer Y. - - To compile this driver as a module, choose M here. - -config GVPIOEXT - tristate "GVP IO-Extender support" - depends on PARPORT=n && ZORRO - help - If you want to use a GVP IO-Extender serial card in Linux, say Y. - Otherwise, say N. - -config GVPIOEXT_LP - tristate "GVP IO-Extender parallel printer support" - depends on GVPIOEXT - help - Say Y to enable driving a printer from the parallel port on your - GVP IO-Extender card, N otherwise. - -config GVPIOEXT_PLIP - tristate "GVP IO-Extender PLIP support" - depends on GVPIOEXT - help - Say Y to enable doing IP over the parallel port on your GVP - IO-Extender card, N otherwise. - -config MAC_HID - bool - depends on INPUT_ADBHID - default y - -config HPDCA - tristate "HP DCA serial support" - depends on DIO && SERIAL_8250 - help - If you want to use the internal "DCA" serial ports on an HP300 - machine, say Y here. - -config HPAPCI - tristate "HP APCI serial support" - depends on HP300 && SERIAL_8250 && EXPERIMENTAL - help - If you want to use the internal "APCI" serial ports on an HP400 - machine, say Y here. - -config MVME147_SCC - bool "SCC support for MVME147 serial ports" - depends on MVME147 && BROKEN - help - This is the driver for the serial ports on the Motorola MVME147 - boards. Everyone using one of these boards should say Y here. - -config MVME162_SCC - bool "SCC support for MVME162 serial ports" - depends on MVME16x && BROKEN - help - This is the driver for the serial ports on the Motorola MVME162 and - 172 boards. Everyone using one of these boards should say Y here. - -config BVME6000_SCC - bool "SCC support for BVME6000 serial ports" - depends on BVME6000 && BROKEN - help - This is the driver for the serial ports on the BVME4000 and BVME6000 - boards from BVM Ltd. Everyone using one of these boards should say - Y here. - -config DN_SERIAL - bool "Support for DN serial port (dummy)" - depends on APOLLO - -config SERIAL_CONSOLE - bool "Support for serial port console" - depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL) - ---help--- - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - If unsure, say N. - -endmenu - -endif +source "arch/m68k/Kconfig.devices" source "fs/Kconfig" diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus new file mode 100644 index 000000000000..8294f0c1785e --- /dev/null +++ b/arch/m68k/Kconfig.bus @@ -0,0 +1,55 @@ +if MMU + +comment "Bus Support" + +config NUBUS + bool + depends on MAC + default y + +config ZORRO + bool "Amiga Zorro (AutoConfig) bus support" + depends on AMIGA + help + This enables support for the Zorro bus in the Amiga. If you have + expansion cards in your Amiga that conform to the Amiga + AutoConfig(tm) specification, say Y, otherwise N. Note that even + expansion cards that do not fit in the Zorro slots but fit in e.g. + the CPU slot may fall in this category, so you have to say Y to let + Linux use these. + +config AMIGA_PCMCIA + bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)" + depends on AMIGA && EXPERIMENTAL + help + Include support in the kernel for pcmcia on Amiga 1200 and Amiga + 600. If you intend to use pcmcia cards say Y; otherwise say N. + +config ISA + bool + depends on Q40 || AMIGA_PCMCIA + default y + help + Find out whether you have ISA slots on your motherboard. ISA is the + name of a bus system, i.e. the way the CPU talks to the other stuff + inside your box. Other bus systems are PCI, EISA, MicroChannel + (MCA) or VESA. ISA is an older system, now being displaced by PCI; + newer boards don't support it. If you have ISA, say Y, otherwise N. + +config GENERIC_ISA_DMA + def_bool ISA + +source "drivers/pci/Kconfig" + +source "drivers/zorro/Kconfig" + +endif + +if !MMU + +config ISA_DMA_API + def_bool !M5272 + +source "drivers/pcmcia/Kconfig" + +endif diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu new file mode 100644 index 000000000000..e632b2d12106 --- /dev/null +++ b/arch/m68k/Kconfig.cpu @@ -0,0 +1,429 @@ +comment "Processor Type" + +config M68000 + bool + select CPU_HAS_NO_BITFIELDS + help + The Freescale (was Motorola) 68000 CPU is the first generation of + the well known M68K family of processors. The CPU core as well as + being available as a stand alone CPU was also used in many + System-On-Chip devices (eg 68328, 68302, etc). It does not contain + a paging MMU. + +config MCPU32 + bool + select CPU_HAS_NO_BITFIELDS + help + The Freescale (was then Motorola) CPU32 is a CPU core that is + based on the 68020 processor. For the most part it is used in + System-On-Chip parts, and does not contain a paging MMU. + +config COLDFIRE + bool + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + select CPU_HAS_NO_BITFIELDS + help + The Freescale ColdFire family of processors is a modern derivitive + of the 68000 processor family. They are mainly targeted at embedded + applications, and are all System-On-Chip (SOC) devices, as opposed + to stand alone CPUs. They implement a subset of the original 68000 + processor instruction set. + +config M68020 + bool "68020 support" + depends on MMU + help + If you anticipate running this kernel on a computer with a MC68020 + processor, say Y. Otherwise, say N. Note that the 68020 requires a + 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the + Sun 3, which provides its own version. + +config M68030 + bool "68030 support" + depends on MMU && !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68030 + processor, say Y. Otherwise, say N. Note that a MC68EC030 will not + work, as it does not include an MMU (Memory Management Unit). + +config M68040 + bool "68040 support" + depends on MMU && !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68LC040 + or MC68040 processor, say Y. Otherwise, say N. Note that an + MC68EC040 will not work, as it does not include an MMU (Memory + Management Unit). + +config M68060 + bool "68060 support" + depends on MMU && !MMU_SUN3 + help + If you anticipate running this kernel on a computer with a MC68060 + processor, say Y. Otherwise, say N. + +config M68328 + bool "MC68328" + depends on !MMU + select M68000 + help + Motorola 68328 processor support. + +config M68EZ328 + bool "MC68EZ328" + depends on !MMU + select M68000 + help + Motorola 68EX328 processor support. + +config M68VZ328 + bool "MC68VZ328" + depends on !MMU + select M68000 + help + Motorola 68VZ328 processor support. + +config M68360 + bool "MC68360" + depends on !MMU + select MCPU32 + help + Motorola 68360 processor support. + +config M5206 + bool "MCF5206" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_MBAR + help + Motorola ColdFire 5206 processor support. + +config M5206e + bool "MCF5206e" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_MBAR + help + Motorola ColdFire 5206e processor support. + +config M520x + bool "MCF520x" + depends on !MMU + select COLDFIRE + select GENERIC_CLOCKEVENTS + select HAVE_CACHE_SPLIT + help + Freescale Coldfire 5207/5208 processor support. + +config M523x + bool "MCF523x" + depends on !MMU + select COLDFIRE + select GENERIC_CLOCKEVENTS + select HAVE_CACHE_SPLIT + select HAVE_IPSBAR + help + Freescale Coldfire 5230/1/2/4/5 processor support + +config M5249 + bool "MCF5249" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_MBAR + help + Motorola ColdFire 5249 processor support. + +config M527x + bool + +config M5271 + bool "MCF5271" + depends on !MMU + select COLDFIRE + select M527x + select HAVE_CACHE_SPLIT + select HAVE_IPSBAR + select GENERIC_CLOCKEVENTS + help + Freescale (Motorola) ColdFire 5270/5271 processor support. + +config M5272 + bool "MCF5272" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_MBAR + help + Motorola ColdFire 5272 processor support. + +config M5275 + bool "MCF5275" + depends on !MMU + select COLDFIRE + select M527x + select HAVE_CACHE_SPLIT + select HAVE_IPSBAR + select GENERIC_CLOCKEVENTS + help + Freescale (Motorola) ColdFire 5274/5275 processor support. + +config M528x + bool "MCF528x" + depends on !MMU + select COLDFIRE + select GENERIC_CLOCKEVENTS + select HAVE_CACHE_SPLIT + select HAVE_IPSBAR + help + Motorola ColdFire 5280/5282 processor support. + +config M5307 + bool "MCF5307" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_CACHE_CB + select HAVE_MBAR + help + Motorola ColdFire 5307 processor support. + +config M532x + bool "MCF532x" + depends on !MMU + select COLDFIRE + select HAVE_CACHE_CB + help + Freescale (Motorola) ColdFire 532x processor support. + +config M5407 + bool "MCF5407" + depends on !MMU + select COLDFIRE + select COLDFIRE_SW_A7 + select HAVE_CACHE_CB + select HAVE_MBAR + help + Motorola ColdFire 5407 processor support. + +config M54xx + bool + +config M547x + bool "MCF547x" + depends on !MMU + select COLDFIRE + select M54xx + select HAVE_CACHE_CB + select HAVE_MBAR + help + Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support. + +config M548x + bool "MCF548x" + depends on !MMU + select COLDFIRE + select M54xx + select HAVE_CACHE_CB + select HAVE_MBAR + help + Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support. + + +comment "Processor Specific Options" + +config M68KFPU_EMU + bool "Math emulation support (EXPERIMENTAL)" + depends on MMU + depends on EXPERIMENTAL + help + At some point in the future, this will cause floating-point math + instructions to be emulated by the kernel on machines that lack a + floating-point math coprocessor. Thrill-seekers and chronically + sleep-deprived psychotic hacker types can say Y now, everyone else + should probably wait a while. + +config M68KFPU_EMU_EXTRAPREC + bool "Math emulation extra precision" + depends on M68KFPU_EMU + help + The fpu uses normally a few bit more during calculations for + correct rounding, the emulator can (often) do the same but this + extra calculation can cost quite some time, so you can disable + it here. The emulator will then "only" calculate with a 64 bit + mantissa and round slightly incorrect, what is more than enough + for normal usage. + +config M68KFPU_EMU_ONLY + bool "Math emulation only kernel" + depends on M68KFPU_EMU + help + This option prevents any floating-point instructions from being + compiled into the kernel, thereby the kernel doesn't save any + floating point context anymore during task switches, so this + kernel will only be usable on machines without a floating-point + math coprocessor. This makes the kernel a bit faster as no tests + needs to be executed whether a floating-point instruction in the + kernel should be executed or not. + +config ADVANCED + bool "Advanced configuration options" + depends on MMU + ---help--- + This gives you access to some advanced options for the CPU. The + defaults should be fine for most users, but these options may make + it possible for you to improve performance somewhat if you know what + you are doing. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about these options. + + Most users should say N to this question. + +config RMW_INSNS + bool "Use read-modify-write instructions" + depends on ADVANCED + ---help--- + This allows to use certain instructions that work with indivisible + read-modify-write bus cycles. While this is faster than the + workaround of disabling interrupts, it can conflict with DMA + ( = direct memory access) on many Amiga systems, and it is also said + to destabilize other machines. It is very likely that this will + cause serious problems on any Amiga or Atari Medusa if set. The only + configuration where it should work are 68030-based Ataris, where it + apparently improves performance. But you've been warned! Unless you + really know what you are doing, say N. Try Y only if you're quite + adventurous. + +config SINGLE_MEMORY_CHUNK + bool "Use one physical chunk of memory only" if ADVANCED && !SUN3 + depends on MMU + default y if SUN3 + select NEED_MULTIPLE_NODES + help + Ignore all but the first contiguous chunk of physical memory for VM + purposes. This will save a few bytes kernel size and may speed up + some operations. Say N if not sure. + +config ARCH_DISCONTIGMEM_ENABLE + def_bool MMU && !SINGLE_MEMORY_CHUNK + +config 060_WRITETHROUGH + bool "Use write-through caching for 68060 supervisor accesses" + depends on ADVANCED && M68060 + ---help--- + The 68060 generally uses copyback caching of recently accessed data. + Copyback caching means that memory writes will be held in an on-chip + cache and only written back to memory some time later. Saying Y + here will force supervisor (kernel) accesses to use writethrough + caching. Writethrough caching means that data is written to memory + straight away, so that cache and memory data always agree. + Writethrough caching is less efficient, but is needed for some + drivers on 68060 based systems where the 68060 bus snooping signal + is hardwired on. The 53c710 SCSI driver is known to suffer from + this problem. + +config M68K_L2_CACHE + bool + depends on MAC + default y + +config NODES_SHIFT + int + default "3" + depends on !SINGLE_MEMORY_CHUNK + +config FPU + bool + +config COLDFIRE_SW_A7 + bool + +config HAVE_CACHE_SPLIT + bool + +config HAVE_CACHE_CB + bool + +config HAVE_MBAR + bool + +config HAVE_IPSBAR + bool + +config CLOCK_SET + bool "Enable setting the CPU clock frequency" + depends on COLDFIRE + default n + help + On some CPU's you do not need to know what the core CPU clock + frequency is. On these you can disable clock setting. On some + traditional 68K parts, and on all ColdFire parts you need to set + the appropriate CPU clock frequency. On these devices many of the + onboard peripherals derive their timing from the master CPU clock + frequency. + +config CLOCK_FREQ + int "Set the core clock frequency" + default "66666666" + depends on CLOCK_SET + help + Define the CPU clock frequency in use. This is the core clock + frequency, it may or may not be the same as the external clock + crystal fitted to your board. Some processors have an internal + PLL and can have their frequency programmed at run time, others + use internal dividers. In general the kernel won't setup a PLL + if it is fitted (there are some exceptions). This value will be + specific to the exact CPU that you are using. + +config OLDMASK + bool "Old mask 5307 (1H55J) silicon" + depends on M5307 + help + Build support for the older revision ColdFire 5307 silicon. + Specifically this is the 1H55J mask revision. + +if HAVE_CACHE_SPLIT +choice + prompt "Split Cache Configuration" + default CACHE_I + +config CACHE_I + bool "Instruction" + help + Use all of the ColdFire CPU cache memory as an instruction cache. + +config CACHE_D + bool "Data" + help + Use all of the ColdFire CPU cache memory as a data cache. + +config CACHE_BOTH + bool "Both" + help + Split the ColdFire CPU cache, and use half as an instruction cache + and half as a data cache. +endchoice +endif + +if HAVE_CACHE_CB +choice + prompt "Data cache mode" + default CACHE_WRITETHRU + +config CACHE_WRITETHRU + bool "Write-through" + help + The ColdFire CPU cache is set into Write-through mode. + +config CACHE_COPYBACK + bool "Copy-back" + help + The ColdFire CPU cache is set into Copy-back mode. +endchoice +endif + diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices new file mode 100644 index 000000000000..d214034be6a6 --- /dev/null +++ b/arch/m68k/Kconfig.devices @@ -0,0 +1,123 @@ +if MMU + +config ARCH_MAY_HAVE_PC_FDC + bool + depends on BROKEN && (Q40 || SUN3X) + default y + +menu "Platform devices" + +config HEARTBEAT + bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 + default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 + help + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. + +# We have a dedicated heartbeat LED. :-) +config PROC_HARDWARE + bool "/proc/hardware support" + help + Say Y here to support the /proc/hardware file, which gives you + access to information about the machine you're running on, + including the model, CPU, MMU, clock speed, BogoMIPS rating, + and memory size. + +endmenu + +menu "Character devices" + +config ATARI_MFPSER + tristate "Atari MFP serial support" + depends on ATARI + ---help--- + If you like to use the MFP serial ports ("Modem1", "Serial1") under + Linux, say Y. The driver equally supports all kinds of MFP serial + ports and automatically detects whether Serial1 is available. + + To compile this driver as a module, choose M here. + + Note for Falcon users: You also have an MFP port, it's just not + wired to the outside... But you could use the port under Linux. + +config ATARI_MIDI + tristate "Atari MIDI serial support" + depends on ATARI + help + If you want to use your Atari's MIDI port in Linux, say Y. + + To compile this driver as a module, choose M here. + +config ATARI_DSP56K + tristate "Atari DSP56k support (EXPERIMENTAL)" + depends on ATARI && EXPERIMENTAL + help + If you want to be able to use the DSP56001 in Falcons, say Y. This + driver is still experimental, and if you don't know what it is, or + if you don't have this processor, just say N. + + To compile this driver as a module, choose M here. + +config AMIGA_BUILTIN_SERIAL + tristate "Amiga builtin serial support" + depends on AMIGA + help + If you want to use your Amiga's built-in serial port in Linux, + answer Y. + + To compile this driver as a module, choose M here. + +config MULTIFACE_III_TTY + tristate "Multiface Card III serial support" + depends on AMIGA + help + If you want to use a Multiface III card's serial port in Linux, + answer Y. + + To compile this driver as a module, choose M here. + +config HPDCA + tristate "HP DCA serial support" + depends on DIO && SERIAL_8250 + help + If you want to use the internal "DCA" serial ports on an HP300 + machine, say Y here. + +config HPAPCI + tristate "HP APCI serial support" + depends on HP300 && SERIAL_8250 && EXPERIMENTAL + help + If you want to use the internal "APCI" serial ports on an HP400 + machine, say Y here. + +config DN_SERIAL + bool "Support for DN serial port (dummy)" + depends on APOLLO + +config SERIAL_CONSOLE + bool "Support for serial port console" + depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || MULTIFACE_III_TTY=y || SERIAL=y || SERIAL167 || DN_SERIAL) + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). This could be useful if some terminal or printer is connected + to that serial port. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyS1". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + + If you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + If unsure, say N. + +endmenu + +endif diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.machine index ff46383112a4..ef4a26aff780 100644 --- a/arch/m68k/Kconfig.nommu +++ b/arch/m68k/Kconfig.machine @@ -1,297 +1,142 @@ -config FPU - bool - default n - -config GENERIC_GPIO - bool - default n - -config GENERIC_CMOS_UPDATE - bool - default y - -config GENERIC_CLOCKEVENTS - bool - default n - -config M68000 - bool - select CPU_HAS_NO_BITFIELDS - help - The Freescale (was Motorola) 68000 CPU is the first generation of - the well known M68K family of processors. The CPU core as well as - being available as a stand alone CPU was also used in many - System-On-Chip devices (eg 68328, 68302, etc). It does not contain - a paging MMU. - -config MCPU32 - bool - select CPU_HAS_NO_BITFIELDS - help - The Freescale (was then Motorola) CPU32 is a CPU core that is - based on the 68020 processor. For the most part it is used in - System-On-Chip parts, and does not contain a paging MMU. - -config COLDFIRE - bool - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB - select CPU_HAS_NO_BITFIELDS - help - The Freescale ColdFire family of processors is a modern derivitive - of the 68000 processor family. They are mainly targeted at embedded - applications, and are all System-On-Chip (SOC) devices, as opposed - to stand alone CPUs. They implement a subset of the original 68000 - processor instruction set. - -config COLDFIRE_SW_A7 - bool - default n - -config HAVE_CACHE_SPLIT - bool - -config HAVE_CACHE_CB - bool - -config HAVE_MBAR - bool - -config HAVE_IPSBAR - bool - -choice - prompt "CPU" - default M68EZ328 - -config M68328 - bool "MC68328" - select M68000 - help - Motorola 68328 processor support. - -config M68EZ328 - bool "MC68EZ328" - select M68000 - help - Motorola 68EX328 processor support. - -config M68VZ328 - bool "MC68VZ328" - select M68000 - help - Motorola 68VZ328 processor support. - -config M68360 - bool "MC68360" - select MCPU32 - help - Motorola 68360 processor support. - -config M5206 - bool "MCF5206" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_MBAR - help - Motorola ColdFire 5206 processor support. +comment "Machine Types" + +config AMIGA + bool "Amiga support" + depends on MMU + select MMU_MOTOROLA if MMU + help + This option enables support for the Amiga series of computers. If + you plan to use this kernel on an Amiga, say Y here and browse the + material available in <file:Documentation/m68k>; otherwise say N. + +config ATARI + bool "Atari support" + depends on MMU + select MMU_MOTOROLA if MMU + help + This option enables support for the 68000-based Atari series of + computers (including the TT, Falcon and Medusa). If you plan to use + this kernel on an Atari, say Y here and browse the material + available in <file:Documentation/m68k>; otherwise say N. + +config MAC + bool "Macintosh support" + depends on MMU + select MMU_MOTOROLA if MMU + help + This option enables support for the Apple Macintosh series of + computers (yes, there is experimental support now, at least for part + of the series). + + Say N unless you're willing to code the remaining necessary support. + ;) + +config APOLLO + bool "Apollo support" + depends on MMU + select MMU_MOTOROLA if MMU + help + Say Y here if you want to run Linux on an MC680x0-based Apollo + Domain workstation such as the DN3500. + +config VME + bool "VME (Motorola and BVM) support" + depends on MMU + select MMU_MOTOROLA if MMU + help + Say Y here if you want to build a kernel for a 680x0 based VME + board. Boards currently supported include Motorola boards MVME147, + MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and + BVME6000 boards from BVM Ltd are also supported. + +config MVME147 + bool "MVME147 support" + depends on MMU + depends on VME + help + Say Y to include support for early Motorola VME boards. This will + build a kernel which can run on MVME147 single-board computers. If + you select this option you will have to select the appropriate + drivers for SCSI, Ethernet and serial ports later on. + +config MVME16x + bool "MVME162, 166 and 167 support" + depends on MMU + depends on VME + help + Say Y to include support for Motorola VME boards. This will build a + kernel which can run on MVME162, MVME166, MVME167, MVME172, and + MVME177 boards. If you select this option you will have to select + the appropriate drivers for SCSI, Ethernet and serial ports later + on. + +config BVME6000 + bool "BVME4000 and BVME6000 support" + depends on MMU + depends on VME + help + Say Y to include support for VME boards from BVM Ltd. This will + build a kernel which can run on BVME4000 and BVME6000 boards. If + you select this option you will have to select the appropriate + drivers for SCSI, Ethernet and serial ports later on. + +config HP300 + bool "HP9000/300 and HP9000/400 support" + depends on MMU + select MMU_MOTOROLA if MMU + help + This option enables support for the HP9000/300 and HP9000/400 series + of workstations. Support for these machines is still somewhat + experimental. If you plan to try to use the kernel on such a machine + say Y here. + Everybody else says N. + +config SUN3X + bool "Sun3x support" + depends on MMU + select MMU_MOTOROLA if MMU + select M68030 + help + This option enables support for the Sun 3x series of workstations. + Be warned that this support is very experimental. + Note that Sun 3x kernels are not compatible with Sun 3 hardware. + General Linux information on the Sun 3x series (now discontinued) + is at <http://www.angelfire.com/ca2/tech68k/sun3.html>. + + If you don't want to compile a kernel for a Sun 3x, say N. + +config Q40 + bool "Q40/Q60 support" + depends on MMU + select MMU_MOTOROLA if MMU + help + The Q40 is a Motorola 68040-based successor to the Sinclair QL + manufactured in Germany. There is an official Q40 home page at + <http://www.q40.de/>. This option enables support for the Q40 and + Q60. Select your CPU below. For 68LC060 don't forget to enable FPU + emulation. + +config SUN3 + bool "Sun3 support" + depends on MMU + depends on !MMU_MOTOROLA + select MMU_SUN3 if MMU + select M68020 + help + This option enables support for the Sun 3 series of workstations + (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires + that all other hardware types must be disabled, as Sun 3 kernels + are incompatible with all other m68k targets (including Sun 3x!). + + If you don't want to compile a kernel exclusively for a Sun 3, say N. -config M5206e - bool "MCF5206e" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_MBAR - help - Motorola ColdFire 5206e processor support. - -config M520x - bool "MCF520x" - select COLDFIRE - select GENERIC_CLOCKEVENTS - select HAVE_CACHE_SPLIT - help - Freescale Coldfire 5207/5208 processor support. - -config M523x - bool "MCF523x" - select COLDFIRE - select GENERIC_CLOCKEVENTS - select HAVE_CACHE_SPLIT - select HAVE_IPSBAR - help - Freescale Coldfire 5230/1/2/4/5 processor support - -config M5249 - bool "MCF5249" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_MBAR - help - Motorola ColdFire 5249 processor support. - -config M5271 - bool "MCF5271" - select COLDFIRE - select HAVE_CACHE_SPLIT - select HAVE_IPSBAR - help - Freescale (Motorola) ColdFire 5270/5271 processor support. - -config M5272 - bool "MCF5272" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_MBAR - help - Motorola ColdFire 5272 processor support. - -config M5275 - bool "MCF5275" - select COLDFIRE - select HAVE_CACHE_SPLIT - select HAVE_IPSBAR - help - Freescale (Motorola) ColdFire 5274/5275 processor support. - -config M528x - bool "MCF528x" - select COLDFIRE - select GENERIC_CLOCKEVENTS - select HAVE_CACHE_SPLIT - select HAVE_IPSBAR - help - Motorola ColdFire 5280/5282 processor support. - -config M5307 - bool "MCF5307" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_CACHE_CB - select HAVE_MBAR - help - Motorola ColdFire 5307 processor support. - -config M532x - bool "MCF532x" - select COLDFIRE - select HAVE_CACHE_CB - help - Freescale (Motorola) ColdFire 532x processor support. - -config M5407 - bool "MCF5407" - select COLDFIRE - select COLDFIRE_SW_A7 - select HAVE_CACHE_CB - select HAVE_MBAR - help - Motorola ColdFire 5407 processor support. - -config M547x - bool "MCF547x" - select COLDFIRE - select HAVE_CACHE_CB - select HAVE_MBAR - help - Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support. - -config M548x - bool "MCF548x" - select COLDFIRE - select HAVE_CACHE_CB - select HAVE_MBAR - help - Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support. - -endchoice - -config M527x - bool - depends on (M5271 || M5275) - select GENERIC_CLOCKEVENTS - default y - -config M54xx +config PILOT bool - depends on (M548x || M547x) - default y - -config CLOCK_SET - bool "Enable setting the CPU clock frequency" - default n - help - On some CPU's you do not need to know what the core CPU clock - frequency is. On these you can disable clock setting. On some - traditional 68K parts, and on all ColdFire parts you need to set - the appropriate CPU clock frequency. On these devices many of the - onboard peripherals derive their timing from the master CPU clock - frequency. - -config CLOCK_FREQ - int "Set the core clock frequency" - default "66666666" - depends on CLOCK_SET - help - Define the CPU clock frequency in use. This is the core clock - frequency, it may or may not be the same as the external clock - crystal fitted to your board. Some processors have an internal - PLL and can have their frequency programmed at run time, others - use internal dividers. In general the kernel won't setup a PLL - if it is fitted (there are some exceptions). This value will be - specific to the exact CPU that you are using. - -config OLDMASK - bool "Old mask 5307 (1H55J) silicon" - depends on M5307 - help - Build support for the older revision ColdFire 5307 silicon. - Specifically this is the 1H55J mask revision. - -if HAVE_CACHE_SPLIT -choice - prompt "Split Cache Configuration" - default CACHE_I - -config CACHE_I - bool "Instruction" - help - Use all of the ColdFire CPU cache memory as an instruction cache. - -config CACHE_D - bool "Data" - help - Use all of the ColdFire CPU cache memory as a data cache. - -config CACHE_BOTH - bool "Both" - help - Split the ColdFire CPU cache, and use half as an instruction cache - and half as a data cache. -endchoice -endif - -if HAVE_CACHE_CB -choice - prompt "Data cache mode" - default CACHE_WRITETHRU - -config CACHE_WRITETHRU - bool "Write-through" - help - The ColdFire CPU cache is set into Write-through mode. - -config CACHE_COPYBACK - bool "Copy-back" - help - The ColdFire CPU cache is set into Copy-back mode. -endchoice -endif - -comment "Platform" config PILOT3 bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support" depends on M68328 + select PILOT help Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII. @@ -302,7 +147,7 @@ config XCOPILOT_BUGS Support the bugs of Xcopilot. config UC5272 - bool 'Arcturus Networks uC5272 dimm board support' + bool "Arcturus Networks uC5272 dimm board support" depends on M5272 help Support for the Arcturus Networks uC5272 dimm board. @@ -356,15 +201,23 @@ config UCQUICC help Support for the Lineo uCquicc board. +config ARNEWSH + bool + config ARN5206 bool "Arnewsh 5206 board support" depends on M5206 + select ARNEWSH help Support for the Arnewsh 5206 board. +config FREESCALE + bool + config M5206eC3 bool "Motorola M5206eC3 board support" depends on M5206e + select FREESCALE help Support for the Motorola M5206eC3 board. @@ -377,75 +230,92 @@ config ELITE config M5208EVB bool "Freescale M5208EVB board support" depends on M520x + select FREESCALE help Support for the Freescale Coldfire M5208EVB. config M5235EVB bool "Freescale M5235EVB support" depends on M523x + select FREESCALE help Support for the Freescale M5235EVB board. config M5249C3 bool "Motorola M5249C3 board support" depends on M5249 + select FREESCALE help Support for the Motorola M5249C3 board. config M5271EVB bool "Freescale (Motorola) M5271EVB board support" depends on M5271 + select FREESCALE help Support for the Freescale (Motorola) M5271EVB board. config M5275EVB bool "Freescale (Motorola) M5275EVB board support" depends on M5275 + select FREESCALE help Support for the Freescale (Motorola) M5275EVB board. config M5272C3 bool "Motorola M5272C3 board support" depends on M5272 + select FREESCALE help Support for the Motorola M5272C3 board. +config senTec + bool + config COBRA5272 bool "senTec COBRA5272 board support" depends on M5272 + select senTec help Support for the senTec COBRA5272 board. +config AVNET + bool + config AVNET5282 bool "Avnet 5282 board support" depends on M528x + select AVNET help - Support for the Avnet 5282 board. - + Support for the Avnet 5282 board. + config M5282EVB bool "Motorola M5282EVB board support" depends on M528x + select FREESCALE help Support for the Motorola M5282EVB board. config COBRA5282 bool "senTec COBRA5282 board support" depends on M528x + select senTec help Support for the senTec COBRA5282 board. - + config SOM5282EM bool "EMAC.Inc SOM5282EM board support" depends on M528x + select EMAC_INC help - Support for the EMAC.Inc SOM5282EM module. - + Support for the EMAC.Inc SOM5282EM module. + config WILDFIRE bool "Intec Automation Inc. WildFire board support" depends on M528x help Support for the Intec Automation Inc. WildFire. - + config WILDFIREMOD bool "Intec Automation Inc. WildFire module support" depends on M528x @@ -455,12 +325,14 @@ config WILDFIREMOD config ARN5307 bool "Arnewsh 5307 board support" depends on M5307 + select ARNEWSH help Support for the Arnewsh 5307 board. config M5307C3 bool "Motorola M5307C3 board support" depends on M5307 + select FREESCALE help Support for the Motorola M5307C3 board. @@ -473,6 +345,7 @@ config SECUREEDGEMP3 config M5329EVB bool "Freescale (Motorola) M5329EVB board support" depends on M532x + select FREESCALE help Support for the Freescale (Motorola) M5329EVB board. @@ -485,6 +358,7 @@ config COBRA5329 config M5407C3 bool "Motorola M5407C3 board support" depends on M5407 + select FREESCALE help Support for the Motorola M5407C3 board. @@ -524,9 +398,13 @@ config SNAPGEAR help Special additional support for SnapGear router boards. +config SNEHA + bool + config CPU16B bool "Sneha Technologies S.L. Sarasvati board support" depends on M5272 + select SNEHA help Support for the SNEHA CPU16B board. @@ -536,63 +414,20 @@ config MOD5272 help Support for the Netburner MOD-5272 board. +config SAVANT + bool + config SAVANTrosie1 bool "Savant Rosie1 board support" depends on M523x + select SAVANT help Support for the Savant Rosie1 board. -config ROMFS_FROM_ROM - bool "ROMFS image not RAM resident" - depends on (NETtel || SNAPGEAR) - help - The ROMfs filesystem will stay resident in the FLASH/ROM, not be - moved into RAM. - -config PILOT - bool - default y - depends on (PILOT3 || PILOT5) - -config ARNEWSH - bool - default y - depends on (ARN5206 || ARN5307) - -config FREESCALE - bool - default y - depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3) - -config HW_FEITH - bool - default y - depends on (CLEOPATRA || CANCam || SCALES) - -config senTec - bool - default y - depends on (COBRA5272 || COBRA5282) - -config EMAC_INC - bool - default y - depends on (SOM5282EM) -config SNEHA - bool - default y - depends on CPU16B +if !MMU || COLDFIRE -config SAVANT - bool - default y - depends on SAVANTrosie1 - -config AVNET - bool - default y - depends on (AVNET5282) +comment "Machine Options" config UBOOT bool "Support for U-Boot command line parameters" @@ -673,33 +508,6 @@ config KERNELBASE a system with the RAM based at address 0, and leaving enough room for the theoretical maximum number of 256 vectors. -choice - prompt "RAM bus width" - default RAMAUTOBIT - -config RAMAUTOBIT - bool "AUTO" - help - Select the physical RAM data bus size. Not needed on most platforms, - so you can generally choose AUTO. - -config RAM8BIT - bool "8bit" - help - Configure RAM bus to be 8 bits wide. - -config RAM16BIT - bool "16bit" - help - Configure RAM bus to be 16 bits wide. - -config RAM32BIT - bool "32bit" - help - Configure RAM bus to be 32 bits wide. - -endchoice - comment "ROM configuration" config ROM @@ -772,16 +580,4 @@ config ROMKERNEL endchoice -if COLDFIRE -source "kernel/Kconfig.preempt" endif - -source "kernel/time/Kconfig" - -config ISA_DMA_API - bool - depends on !M5272 - default y - -source "drivers/pcmcia/Kconfig" - diff --git a/arch/m68k/Kconfig.mmu b/arch/m68k/Kconfig.mmu deleted file mode 100644 index 13e20bbc4079..000000000000 --- a/arch/m68k/Kconfig.mmu +++ /dev/null @@ -1,411 +0,0 @@ -config GENERIC_IOMAP - bool - default y - -config ARCH_MAY_HAVE_PC_FDC - bool - depends on BROKEN && (Q40 || SUN3X) - default y - -config ARCH_USES_GETTIMEOFFSET - def_bool y - -config EISA - bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - <file:Documentation/mca.txt> (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config PCMCIA - tristate - ---help--- - Say Y here if you want to attach PCMCIA- or PC-cards to your Linux - computer. These are credit-card size devices such as network cards, - modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: the older 16 bit PCMCIA cards - and the newer 32 bit CardBus cards. If you want to use CardBus - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> - for location). Please also read the PCMCIA-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. - -config AMIGA - bool "Amiga support" - select MMU_MOTOROLA if MMU - help - This option enables support for the Amiga series of computers. If - you plan to use this kernel on an Amiga, say Y here and browse the - material available in <file:Documentation/m68k>; otherwise say N. - -config ATARI - bool "Atari support" - select MMU_MOTOROLA if MMU - help - This option enables support for the 68000-based Atari series of - computers (including the TT, Falcon and Medusa). If you plan to use - this kernel on an Atari, say Y here and browse the material - available in <file:Documentation/m68k>; otherwise say N. - -config MAC - bool "Macintosh support" - select MMU_MOTOROLA if MMU - help - This option enables support for the Apple Macintosh series of - computers (yes, there is experimental support now, at least for part - of the series). - - Say N unless you're willing to code the remaining necessary support. - ;) - -config NUBUS - bool - depends on MAC - default y - -config M68K_L2_CACHE - bool - depends on MAC - default y - -config APOLLO - bool "Apollo support" - select MMU_MOTOROLA if MMU - help - Say Y here if you want to run Linux on an MC680x0-based Apollo - Domain workstation such as the DN3500. - -config VME - bool "VME (Motorola and BVM) support" - select MMU_MOTOROLA if MMU - help - Say Y here if you want to build a kernel for a 680x0 based VME - board. Boards currently supported include Motorola boards MVME147, - MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and - BVME6000 boards from BVM Ltd are also supported. - -config MVME147 - bool "MVME147 support" - depends on VME - help - Say Y to include support for early Motorola VME boards. This will - build a kernel which can run on MVME147 single-board computers. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -config MVME16x - bool "MVME162, 166 and 167 support" - depends on VME - help - Say Y to include support for Motorola VME boards. This will build a - kernel which can run on MVME162, MVME166, MVME167, MVME172, and - MVME177 boards. If you select this option you will have to select - the appropriate drivers for SCSI, Ethernet and serial ports later - on. - -config BVME6000 - bool "BVME4000 and BVME6000 support" - depends on VME - help - Say Y to include support for VME boards from BVM Ltd. This will - build a kernel which can run on BVME4000 and BVME6000 boards. If - you select this option you will have to select the appropriate - drivers for SCSI, Ethernet and serial ports later on. - -config HP300 - bool "HP9000/300 and HP9000/400 support" - select MMU_MOTOROLA if MMU - help - This option enables support for the HP9000/300 and HP9000/400 series - of workstations. Support for these machines is still somewhat - experimental. If you plan to try to use the kernel on such a machine - say Y here. - Everybody else says N. - -config DIO - bool "DIO bus support" - depends on HP300 - default y - help - Say Y here to enable support for the "DIO" expansion bus used in - HP300 machines. If you are using such a system you almost certainly - want this. - -config SUN3X - bool "Sun3x support" - select MMU_MOTOROLA if MMU - select M68030 - help - This option enables support for the Sun 3x series of workstations. - Be warned that this support is very experimental. - Note that Sun 3x kernels are not compatible with Sun 3 hardware. - General Linux information on the Sun 3x series (now discontinued) - is at <http://www.angelfire.com/ca2/tech68k/sun3.html>. - - If you don't want to compile a kernel for a Sun 3x, say N. - -config Q40 - bool "Q40/Q60 support" - select MMU_MOTOROLA if MMU - help - The Q40 is a Motorola 68040-based successor to the Sinclair QL - manufactured in Germany. There is an official Q40 home page at - <http://www.q40.de/>. This option enables support for the Q40 and - Q60. Select your CPU below. For 68LC060 don't forget to enable FPU - emulation. - -config SUN3 - bool "Sun3 support" - depends on !MMU_MOTOROLA - select MMU_SUN3 if MMU - select M68020 - help - This option enables support for the Sun 3 series of workstations - (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires - that all other hardware types must be disabled, as Sun 3 kernels - are incompatible with all other m68k targets (including Sun 3x!). - - If you don't want to compile a kernel exclusively for a Sun 3, say N. - -config NATFEAT - bool "ARAnyM emulator support" - depends on ATARI - help - This option enables support for ARAnyM native features, such as - access to a disk image as /dev/hda. - -config NFBLOCK - tristate "NatFeat block device support" - depends on BLOCK && NATFEAT - help - Say Y to include support for the ARAnyM NatFeat block device - which allows direct access to the hard drives without using - the hardware emulation. - -config NFCON - tristate "NatFeat console driver" - depends on NATFEAT - help - Say Y to include support for the ARAnyM NatFeat console driver - which allows the console output to be redirected to the stderr - output of ARAnyM. - -config NFETH - tristate "NatFeat Ethernet support" - depends on NET_ETHERNET && NATFEAT - help - Say Y to include support for the ARAnyM NatFeat network device - which will emulate a regular ethernet device while presenting an - ethertap device to the host system. - -comment "Processor type" - -config M68020 - bool "68020 support" - help - If you anticipate running this kernel on a computer with a MC68020 - processor, say Y. Otherwise, say N. Note that the 68020 requires a - 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the - Sun 3, which provides its own version. - -config M68030 - bool "68030 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68030 - processor, say Y. Otherwise, say N. Note that a MC68EC030 will not - work, as it does not include an MMU (Memory Management Unit). - -config M68040 - bool "68040 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68LC040 - or MC68040 processor, say Y. Otherwise, say N. Note that an - MC68EC040 will not work, as it does not include an MMU (Memory - Management Unit). - -config M68060 - bool "68060 support" - depends on !MMU_SUN3 - help - If you anticipate running this kernel on a computer with a MC68060 - processor, say Y. Otherwise, say N. - -config MMU_MOTOROLA - bool - -config MMU_SUN3 - bool - depends on MMU && !MMU_MOTOROLA - -config M68KFPU_EMU - bool "Math emulation support (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - At some point in the future, this will cause floating-point math - instructions to be emulated by the kernel on machines that lack a - floating-point math coprocessor. Thrill-seekers and chronically - sleep-deprived psychotic hacker types can say Y now, everyone else - should probably wait a while. - -config M68KFPU_EMU_EXTRAPREC - bool "Math emulation extra precision" - depends on M68KFPU_EMU - help - The fpu uses normally a few bit more during calculations for - correct rounding, the emulator can (often) do the same but this - extra calculation can cost quite some time, so you can disable - it here. The emulator will then "only" calculate with a 64 bit - mantissa and round slightly incorrect, what is more than enough - for normal usage. - -config M68KFPU_EMU_ONLY - bool "Math emulation only kernel" - depends on M68KFPU_EMU - help - This option prevents any floating-point instructions from being - compiled into the kernel, thereby the kernel doesn't save any - floating point context anymore during task switches, so this - kernel will only be usable on machines without a floating-point - math coprocessor. This makes the kernel a bit faster as no tests - needs to be executed whether a floating-point instruction in the - kernel should be executed or not. - -config ADVANCED - bool "Advanced configuration options" - ---help--- - This gives you access to some advanced options for the CPU. The - defaults should be fine for most users, but these options may make - it possible for you to improve performance somewhat if you know what - you are doing. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these options. - - Most users should say N to this question. - -config RMW_INSNS - bool "Use read-modify-write instructions" - depends on ADVANCED - ---help--- - This allows to use certain instructions that work with indivisible - read-modify-write bus cycles. While this is faster than the - workaround of disabling interrupts, it can conflict with DMA - ( = direct memory access) on many Amiga systems, and it is also said - to destabilize other machines. It is very likely that this will - cause serious problems on any Amiga or Atari Medusa if set. The only - configuration where it should work are 68030-based Ataris, where it - apparently improves performance. But you've been warned! Unless you - really know what you are doing, say N. Try Y only if you're quite - adventurous. - -config SINGLE_MEMORY_CHUNK - bool "Use one physical chunk of memory only" if ADVANCED && !SUN3 - default y if SUN3 - select NEED_MULTIPLE_NODES - help - Ignore all but the first contiguous chunk of physical memory for VM - purposes. This will save a few bytes kernel size and may speed up - some operations. Say N if not sure. - -config 060_WRITETHROUGH - bool "Use write-through caching for 68060 supervisor accesses" - depends on ADVANCED && M68060 - ---help--- - The 68060 generally uses copyback caching of recently accessed data. - Copyback caching means that memory writes will be held in an on-chip - cache and only written back to memory some time later. Saying Y - here will force supervisor (kernel) accesses to use writethrough - caching. Writethrough caching means that data is written to memory - straight away, so that cache and memory data always agree. - Writethrough caching is less efficient, but is needed for some - drivers on 68060 based systems where the 68060 bus snooping signal - is hardwired on. The 53c710 SCSI driver is known to suffer from - this problem. - -config ARCH_DISCONTIGMEM_ENABLE - def_bool !SINGLE_MEMORY_CHUNK - -config NODES_SHIFT - int - default "3" - depends on !SINGLE_MEMORY_CHUNK - -config ZORRO - bool "Amiga Zorro (AutoConfig) bus support" - depends on AMIGA - help - This enables support for the Zorro bus in the Amiga. If you have - expansion cards in your Amiga that conform to the Amiga - AutoConfig(tm) specification, say Y, otherwise N. Note that even - expansion cards that do not fit in the Zorro slots but fit in e.g. - the CPU slot may fall in this category, so you have to say Y to let - Linux use these. - -config AMIGA_PCMCIA - bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)" - depends on AMIGA && EXPERIMENTAL - help - Include support in the kernel for pcmcia on Amiga 1200 and Amiga - 600. If you intend to use pcmcia cards say Y; otherwise say N. - -config HEARTBEAT - bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 - default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 - help - Use the power-on LED on your machine as a load meter. The exact - behavior is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. - -# We have a dedicated heartbeat LED. :-) -config PROC_HARDWARE - bool "/proc/hardware support" - help - Say Y here to support the /proc/hardware file, which gives you - access to information about the machine you're running on, - including the model, CPU, MMU, clock speed, BogoMIPS rating, - and memory size. - -config ISA - bool - depends on Q40 || AMIGA_PCMCIA - default y - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config GENERIC_ISA_DMA - bool - depends on Q40 || AMIGA_PCMCIA - default y - -source "drivers/pci/Kconfig" - -source "drivers/zorro/Kconfig" - diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index be46cadd4017..cf318f20c64d 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -1,7 +1,171 @@ +# +# m68k/Makefile +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# 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. +# +# Copyright (C) 1994 by Hamish Macdonald +# Copyright (C) 2002,2011 Greg Ungerer <gerg@snapgear.com> +# + KBUILD_DEFCONFIG := multi_defconfig +# +# Enable processor type. Ordering of these is important - we want to +# use the minimum processor type of the range we support. The logic +# for 680x0 will only allow use of the -m68060 or -m68040 if no other +# 680x0 type is specified - and no option is specified for 68030 or +# 68020. The other m68k/ColdFire types always specify some type of +# compiler cpu type flag. +# +ifndef CONFIG_M68040 +cpuflags-$(CONFIG_M68060) := -m68060 +endif +ifndef CONFIG_M68060 +cpuflags-$(CONFIG_M68040) := -m68040 +endif +cpuflags-$(CONFIG_M68030) := +cpuflags-$(CONFIG_M68020) := +cpuflags-$(CONFIG_M68360) := -m68332 +cpuflags-$(CONFIG_M68000) := -m68000 +cpuflags-$(CONFIG_M54xx) := $(call cc-option,-mcpu=5475,-m5200) +cpuflags-$(CONFIG_M5407) := $(call cc-option,-mcpu=5407,-m5200) +cpuflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307) +cpuflags-$(CONFIG_M5307) := $(call cc-option,-mcpu=5307,-m5200) +cpuflags-$(CONFIG_M528x) := $(call cc-option,-mcpu=528x,-m5307) +cpuflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307) +cpuflags-$(CONFIG_M5272) := $(call cc-option,-mcpu=5272,-m5307) +cpuflags-$(CONFIG_M5271) := $(call cc-option,-mcpu=5271,-m5307) +cpuflags-$(CONFIG_M523x) := $(call cc-option,-mcpu=523x,-m5307) +cpuflags-$(CONFIG_M5249) := $(call cc-option,-mcpu=5249,-m5200) +cpuflags-$(CONFIG_M520x) := $(call cc-option,-mcpu=5208,-m5200) +cpuflags-$(CONFIG_M5206e) := $(call cc-option,-mcpu=5206e,-m5200) +cpuflags-$(CONFIG_M5206) := $(call cc-option,-mcpu=5206,-m5200) + +KBUILD_AFLAGS += $(cpuflags-y) +KBUILD_CFLAGS += $(cpuflags-y) -pipe ifdef CONFIG_MMU -include $(srctree)/arch/m68k/Makefile_mm +# without -fno-strength-reduce the 53c7xx.c driver fails ;-( +KBUILD_CFLAGS += -fno-strength-reduce -ffixed-a2 +else +# we can use a m68k-linux-gcc toolchain with these in place +KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" +KBUILD_CFLAGS += -D__uClinux__ +KBUILD_AFLAGS += -D__uClinux__ +endif + +LDFLAGS := -m m68kelf +KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds +ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, \ + m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-) + endif +endif + +ifdef CONFIG_SUN3 +LDFLAGS_vmlinux = -N +endif + +CHECKFLAGS += -D__mc68000__ + + +ifdef CONFIG_KGDB +# If configured for kgdb support, include debugging infos and keep the +# frame pointer +KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g +endif + +# +# Select the assembler head startup code. Order is important. The default +# head code is first, processor specific selections can override it after. +# +head-y := arch/m68k/kernel/head.o +head-$(CONFIG_SUN3) := arch/m68k/kernel/sun3-head.o +head-$(CONFIG_M68360) := arch/m68k/platform/68360/head.o +head-$(CONFIG_M68000) := arch/m68k/platform/68328/head.o +head-$(CONFIG_COLDFIRE) := arch/m68k/platform/coldfire/head.o + +core-y += arch/m68k/kernel/ arch/m68k/mm/ +libs-y += arch/m68k/lib/ + +core-$(CONFIG_Q40) += arch/m68k/q40/ +core-$(CONFIG_AMIGA) += arch/m68k/amiga/ +core-$(CONFIG_ATARI) += arch/m68k/atari/ +core-$(CONFIG_MAC) += arch/m68k/mac/ +core-$(CONFIG_HP300) += arch/m68k/hp300/ +core-$(CONFIG_APOLLO) += arch/m68k/apollo/ +core-$(CONFIG_MVME147) += arch/m68k/mvme147/ +core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/ +core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ +core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ +core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ +core-$(CONFIG_NATFEAT) += arch/m68k/emu/ +core-$(CONFIG_M68040) += arch/m68k/fpsp040/ +core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ +core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ +core-$(CONFIG_M68360) += arch/m68k/platform/68360/ +core-$(CONFIG_M68000) += arch/m68k/platform/68328/ +core-$(CONFIG_M68EZ328) += arch/m68k/platform/68EZ328/ +core-$(CONFIG_M68VZ328) += arch/m68k/platform/68VZ328/ +core-$(CONFIG_COLDFIRE) += arch/m68k/platform/coldfire/ +core-$(CONFIG_M5206) += arch/m68k/platform/5206/ +core-$(CONFIG_M5206e) += arch/m68k/platform/5206/ +core-$(CONFIG_M520x) += arch/m68k/platform/520x/ +core-$(CONFIG_M523x) += arch/m68k/platform/523x/ +core-$(CONFIG_M5249) += arch/m68k/platform/5249/ +core-$(CONFIG_M527x) += arch/m68k/platform/527x/ +core-$(CONFIG_M5272) += arch/m68k/platform/5272/ +core-$(CONFIG_M528x) += arch/m68k/platform/528x/ +core-$(CONFIG_M5307) += arch/m68k/platform/5307/ +core-$(CONFIG_M532x) += arch/m68k/platform/532x/ +core-$(CONFIG_M5407) += arch/m68k/platform/5407/ +core-$(CONFIG_M54xx) += arch/m68k/platform/54xx/ + + +all: zImage + +lilo: vmlinux + if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi + if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi + cat vmlinux > $(INSTALL_PATH)/vmlinux + cp System.map $(INSTALL_PATH)/System.map + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + +zImage compressed: vmlinux.gz + +vmlinux.gz: vmlinux + +ifndef CONFIG_KGDB + cp vmlinux vmlinux.tmp + $(STRIP) vmlinux.tmp + gzip -9c vmlinux.tmp >vmlinux.gz + rm vmlinux.tmp else -include $(srctree)/arch/m68k/Makefile_no + gzip -9c vmlinux >vmlinux.gz endif + +bzImage: vmlinux.bz2 + +vmlinux.bz2: vmlinux + +ifndef CONFIG_KGDB + cp vmlinux vmlinux.tmp + $(STRIP) vmlinux.tmp + bzip2 -1c vmlinux.tmp >vmlinux.bz2 + rm vmlinux.tmp +else + bzip2 -1c vmlinux >vmlinux.bz2 +endif + +archclean: + rm -f vmlinux.gz vmlinux.bz2 + +install: + sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" diff --git a/arch/m68k/Makefile_mm b/arch/m68k/Makefile_mm deleted file mode 100644 index d449b6d5aecf..000000000000 --- a/arch/m68k/Makefile_mm +++ /dev/null @@ -1,121 +0,0 @@ -# -# m68k/Makefile -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture -# -# 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. -# -# Copyright (C) 1994 by Hamish Macdonald -# - -# override top level makefile -AS += -m68020 -LDFLAGS := -m m68kelf -KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds -ifneq ($(SUBARCH),$(ARCH)) - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, \ - m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-) - endif -endif - -ifdef CONFIG_SUN3 -LDFLAGS_vmlinux = -N -endif - -CHECKFLAGS += -D__mc68000__ - -# without -fno-strength-reduce the 53c7xx.c driver fails ;-( -KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 - -# enable processor switch if compiled only for a single cpu -ifndef CONFIG_M68020 -ifndef CONFIG_M68030 - -ifndef CONFIG_M68060 -KBUILD_CFLAGS += -m68040 -endif - -ifndef CONFIG_M68040 -KBUILD_CFLAGS += -m68060 -endif - -endif -endif - -ifdef CONFIG_KGDB -# If configured for kgdb support, include debugging infos and keep the -# frame pointer -KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g -endif - -ifndef CONFIG_SUN3 -head-y := arch/m68k/kernel/head.o -else -head-y := arch/m68k/kernel/sun3-head.o -endif - -core-y += arch/m68k/kernel/ arch/m68k/mm/ -libs-y += arch/m68k/lib/ - -core-$(CONFIG_Q40) += arch/m68k/q40/ -core-$(CONFIG_AMIGA) += arch/m68k/amiga/ -core-$(CONFIG_ATARI) += arch/m68k/atari/ -core-$(CONFIG_MAC) += arch/m68k/mac/ -core-$(CONFIG_HP300) += arch/m68k/hp300/ -core-$(CONFIG_APOLLO) += arch/m68k/apollo/ -core-$(CONFIG_MVME147) += arch/m68k/mvme147/ -core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/ -core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/ -core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/ -core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/ -core-$(CONFIG_NATFEAT) += arch/m68k/emu/ -core-$(CONFIG_M68040) += arch/m68k/fpsp040/ -core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ -core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ - -all: zImage - -lilo: vmlinux - if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi - if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi - cat vmlinux > $(INSTALL_PATH)/vmlinux - cp System.map $(INSTALL_PATH)/System.map - if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi - -zImage compressed: vmlinux.gz - -vmlinux.gz: vmlinux - -ifndef CONFIG_KGDB - cp vmlinux vmlinux.tmp - $(STRIP) vmlinux.tmp - gzip -9c vmlinux.tmp >vmlinux.gz - rm vmlinux.tmp -else - gzip -9c vmlinux >vmlinux.gz -endif - -bzImage: vmlinux.bz2 - -vmlinux.bz2: vmlinux - -ifndef CONFIG_KGDB - cp vmlinux vmlinux.tmp - $(STRIP) vmlinux.tmp - bzip2 -1c vmlinux.tmp >vmlinux.bz2 - rm vmlinux.tmp -else - bzip2 -1c vmlinux >vmlinux.bz2 -endif - -archclean: - rm -f vmlinux.gz vmlinux.bz2 - -install: - sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" diff --git a/arch/m68k/Makefile_no b/arch/m68k/Makefile_no deleted file mode 100644 index 844d3f172264..000000000000 --- a/arch/m68k/Makefile_no +++ /dev/null @@ -1,124 +0,0 @@ -# -# arch/m68k/Makefile -# -# 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. -# -# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com> -# - -platform-$(CONFIG_M68328) := 68328 -platform-$(CONFIG_M68EZ328) := 68EZ328 -platform-$(CONFIG_M68VZ328) := 68VZ328 -platform-$(CONFIG_M68360) := 68360 -platform-$(CONFIG_M5206) := 5206 -platform-$(CONFIG_M5206e) := 5206 -platform-$(CONFIG_M520x) := 520x -platform-$(CONFIG_M523x) := 523x -platform-$(CONFIG_M5249) := 5249 -platform-$(CONFIG_M527x) := 527x -platform-$(CONFIG_M5272) := 5272 -platform-$(CONFIG_M528x) := 528x -platform-$(CONFIG_M5307) := 5307 -platform-$(CONFIG_M532x) := 532x -platform-$(CONFIG_M5407) := 5407 -platform-$(CONFIG_M54xx) := 54xx -PLATFORM := $(platform-y) - -board-$(CONFIG_PILOT) := pilot -board-$(CONFIG_UC5272) := UC5272 -board-$(CONFIG_UC5282) := UC5282 -board-$(CONFIG_UCSIMM) := ucsimm -board-$(CONFIG_UCDIMM) := ucdimm -board-$(CONFIG_UCQUICC) := uCquicc -board-$(CONFIG_DRAGEN2) := de2 -board-$(CONFIG_ARNEWSH) := ARNEWSH -board-$(CONFIG_FREESCALE) := FREESCALE -board-$(CONFIG_M5235EVB) := M5235EVB -board-$(CONFIG_M5271EVB) := M5271EVB -board-$(CONFIG_M5275EVB) := M5275EVB -board-$(CONFIG_M5282EVB) := M5282EVB -board-$(CONFIG_ELITE) := eLITE -board-$(CONFIG_NETtel) := NETtel -board-$(CONFIG_SECUREEDGEMP3) := MP3 -board-$(CONFIG_CLEOPATRA) := CLEOPATRA -board-$(CONFIG_senTec) := senTec -board-$(CONFIG_SNEHA) := SNEHA -board-$(CONFIG_M5208EVB) := M5208EVB -board-$(CONFIG_MOD5272) := MOD5272 -board-$(CONFIG_AVNET) := AVNET -board-$(CONFIG_SAVANT) := SAVANT -BOARD := $(board-y) - -model-$(CONFIG_RAMKERNEL) := ram -model-$(CONFIG_ROMKERNEL) := rom -MODEL := $(model-y) - -# -# Some code support is grouped together for a common cpu-subclass (for -# example all ColdFire cpu's are very similar). Determine the sub-class -# for the selected cpu. ONLY need to define this for the non-base member -# of the family. -# -cpuclass-$(CONFIG_M5206) := coldfire -cpuclass-$(CONFIG_M5206e) := coldfire -cpuclass-$(CONFIG_M520x) := coldfire -cpuclass-$(CONFIG_M523x) := coldfire -cpuclass-$(CONFIG_M5249) := coldfire -cpuclass-$(CONFIG_M527x) := coldfire -cpuclass-$(CONFIG_M5272) := coldfire -cpuclass-$(CONFIG_M528x) := coldfire -cpuclass-$(CONFIG_M5307) := coldfire -cpuclass-$(CONFIG_M532x) := coldfire -cpuclass-$(CONFIG_M5407) := coldfire -cpuclass-$(CONFIG_M54xx) := coldfire -cpuclass-$(CONFIG_M68328) := 68328 -cpuclass-$(CONFIG_M68EZ328) := 68328 -cpuclass-$(CONFIG_M68VZ328) := 68328 -cpuclass-$(CONFIG_M68360) := 68360 -CPUCLASS := $(cpuclass-y) - -ifneq ($(CPUCLASS),$(PLATFORM)) -CLASSDIR := arch/m68k/platform/$(cpuclass-y)/ -endif - -export PLATFORM BOARD MODEL CPUCLASS - -# -# Some CFLAG additions based on specific CPU type. -# -cflags-$(CONFIG_M5206) := $(call cc-option,-mcpu=5206,-m5200) -cflags-$(CONFIG_M5206e) := $(call cc-option,-mcpu=5206e,-m5200) -cflags-$(CONFIG_M520x) := $(call cc-option,-mcpu=5208,-m5200) -cflags-$(CONFIG_M523x) := $(call cc-option,-mcpu=523x,-m5307) -cflags-$(CONFIG_M5249) := $(call cc-option,-mcpu=5249,-m5200) -cflags-$(CONFIG_M5271) := $(call cc-option,-mcpu=5271,-m5307) -cflags-$(CONFIG_M5272) := $(call cc-option,-mcpu=5272,-m5307) -cflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307) -cflags-$(CONFIG_M528x) := $(call cc-option,-mcpu=528x,-m5307) -cflags-$(CONFIG_M5307) := $(call cc-option,-mcpu=5307,-m5200) -cflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307) -cflags-$(CONFIG_M5407) := $(call cc-option,-mcpu=5407,-m5200) -cflags-$(CONFIG_M54xx) := $(call cc-option,-mcpu=5475,-m5200) -cflags-$(CONFIG_M68328) := -m68000 -cflags-$(CONFIG_M68EZ328) := -m68000 -cflags-$(CONFIG_M68VZ328) := -m68000 -cflags-$(CONFIG_M68360) := -m68332 - -KBUILD_AFLAGS += $(cflags-y) - -KBUILD_CFLAGS += $(cflags-y) -KBUILD_CFLAGS += -D__linux__ -KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" - -head-y := arch/m68k/platform/$(cpuclass-y)/head.o - -core-y += arch/m68k/kernel/ \ - arch/m68k/mm/ \ - $(CLASSDIR) \ - arch/m68k/platform/$(PLATFORM)/ -libs-y += arch/m68k/lib/ - -archclean: - diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h index 876eec6f2b52..c3c5a8643e15 100644 --- a/arch/m68k/include/asm/entry.h +++ b/arch/m68k/include/asm/entry.h @@ -1,5 +1,254 @@ -#ifdef __uClinux__ -#include "entry_no.h" +#ifndef __M68K_ENTRY_H +#define __M68K_ENTRY_H + +#include <asm/setup.h> +#include <asm/page.h> +#ifdef __ASSEMBLY__ +#include <asm/thread_info.h> +#endif + +/* + * Stack layout in 'ret_from_exception': + * + * This allows access to the syscall arguments in registers d1-d5 + * + * 0(sp) - d1 + * 4(sp) - d2 + * 8(sp) - d3 + * C(sp) - d4 + * 10(sp) - d5 + * 14(sp) - a0 + * 18(sp) - a1 + * 1C(sp) - a2 + * 20(sp) - d0 + * 24(sp) - orig_d0 + * 28(sp) - stack adjustment + * 2C(sp) - [ sr ] [ format & vector ] + * 2E(sp) - [ pc-hiword ] [ sr ] + * 30(sp) - [ pc-loword ] [ pc-hiword ] + * 32(sp) - [ format & vector ] [ pc-loword ] + * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ + * M68K COLDFIRE + */ + +/* the following macro is used when enabling interrupts */ +#if defined(MACH_ATARI_ONLY) + /* block out HSYNC on the atari */ +#define ALLOWINT (~0x400) +#define MAX_NOINT_IPL 3 #else -#include "entry_mm.h" + /* portable version */ +#define ALLOWINT (~0x700) +#define MAX_NOINT_IPL 0 +#endif /* machine compilation types */ + +#ifdef __ASSEMBLY__ +/* + * This defines the normal kernel pt-regs layout. + * + * regs a3-a6 and d6-d7 are preserved by C code + * the kernel doesn't mess with usp unless it needs to + */ +#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */ + +#ifdef CONFIG_COLDFIRE +#ifdef CONFIG_COLDFIRE_SW_A7 +/* + * This is made a little more tricky on older ColdFires. There is no + * separate supervisor and user stack pointers. Need to artificially + * construct a usp in software... When doing this we need to disable + * interrupts, otherwise bad things will happen. + */ +.globl sw_usp +.globl sw_ksp + +.macro SAVE_ALL_SYS + move #0x2700,%sr /* disable intrs */ + btst #5,%sp@(2) /* from user? */ + bnes 6f /* no, skip */ + movel %sp,sw_usp /* save user sp */ + addql #8,sw_usp /* remove exception */ + movel sw_ksp,%sp /* kernel sp */ + subql #8,%sp /* room for exception */ + clrl %sp@- /* stkadj */ + movel %d0,%sp@- /* orig d0 */ + movel %d0,%sp@- /* d0 */ + lea %sp@(-32),%sp /* space for 8 regs */ + moveml %d1-%d5/%a0-%a2,%sp@ + movel sw_usp,%a0 /* get usp */ + movel %a0@-,%sp@(PT_OFF_PC) /* copy exception program counter */ + movel %a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */ + bra 7f + 6: + clrl %sp@- /* stkadj */ + movel %d0,%sp@- /* orig d0 */ + movel %d0,%sp@- /* d0 */ + lea %sp@(-32),%sp /* space for 8 regs */ + moveml %d1-%d5/%a0-%a2,%sp@ + 7: +.endm + +.macro SAVE_ALL_INT + SAVE_ALL_SYS + moveq #-1,%d0 /* not system call entry */ + movel %d0,%sp@(PT_OFF_ORIG_D0) +.endm + +.macro RESTORE_USER + move #0x2700,%sr /* disable intrs */ + movel sw_usp,%a0 /* get usp */ + movel %sp@(PT_OFF_PC),%a0@- /* copy exception program counter */ + movel %sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */ + moveml %sp@,%d1-%d5/%a0-%a2 + lea %sp@(32),%sp /* space for 8 regs */ + movel %sp@+,%d0 + addql #4,%sp /* orig d0 */ + addl %sp@+,%sp /* stkadj */ + addql #8,%sp /* remove exception */ + movel %sp,sw_ksp /* save ksp */ + subql #8,sw_usp /* set exception */ + movel sw_usp,%sp /* restore usp */ + rte +.endm + +.macro RDUSP + movel sw_usp,%a3 +.endm + +.macro WRUSP + movel %a3,sw_usp +.endm + +#else /* !CONFIG_COLDFIRE_SW_A7 */ +/* + * Modern ColdFire parts have separate supervisor and user stack + * pointers. Simple load and restore macros for this case. + */ +.macro SAVE_ALL_SYS + move #0x2700,%sr /* disable intrs */ + clrl %sp@- /* stkadj */ + movel %d0,%sp@- /* orig d0 */ + movel %d0,%sp@- /* d0 */ + lea %sp@(-32),%sp /* space for 8 regs */ + moveml %d1-%d5/%a0-%a2,%sp@ +.endm + +.macro SAVE_ALL_INT + move #0x2700,%sr /* disable intrs */ + clrl %sp@- /* stkadj */ + pea -1:w /* orig d0 */ + movel %d0,%sp@- /* d0 */ + lea %sp@(-32),%sp /* space for 8 regs */ + moveml %d1-%d5/%a0-%a2,%sp@ +.endm + +.macro RESTORE_USER + moveml %sp@,%d1-%d5/%a0-%a2 + lea %sp@(32),%sp /* space for 8 regs */ + movel %sp@+,%d0 + addql #4,%sp /* orig d0 */ + addl %sp@+,%sp /* stkadj */ + rte +.endm + +.macro RDUSP + /*move %usp,%a3*/ + .word 0x4e6b +.endm + +.macro WRUSP + /*move %a3,%usp*/ + .word 0x4e63 +.endm + +#endif /* !CONFIG_COLDFIRE_SW_A7 */ + +.macro SAVE_SWITCH_STACK + lea %sp@(-24),%sp /* 6 regs */ + moveml %a3-%a6/%d6-%d7,%sp@ +.endm + +.macro RESTORE_SWITCH_STACK + moveml %sp@,%a3-%a6/%d6-%d7 + lea %sp@(24),%sp /* 6 regs */ +.endm + +#else /* !CONFIG_COLDFIRE */ + +/* + * All other types of m68k parts (68000, 680x0, CPU32) have the same + * entry and exit code. + */ + +/* + * a -1 in the orig_d0 field signifies + * that the stack frame is NOT for syscall + */ +.macro SAVE_ALL_INT + clrl %sp@- /* stk_adj */ + pea -1:w /* orig d0 */ + movel %d0,%sp@- /* d0 */ + moveml %d1-%d5/%a0-%a2,%sp@- +.endm + +.macro SAVE_ALL_SYS + clrl %sp@- /* stk_adj */ + movel %d0,%sp@- /* orig d0 */ + movel %d0,%sp@- /* d0 */ + moveml %d1-%d5/%a0-%a2,%sp@- +.endm + +.macro RESTORE_ALL + moveml %sp@+,%a0-%a2/%d1-%d5 + movel %sp@+,%d0 + addql #4,%sp /* orig d0 */ + addl %sp@+,%sp /* stk adj */ + rte +.endm + + +.macro SAVE_SWITCH_STACK + moveml %a3-%a6/%d6-%d7,%sp@- +.endm + +.macro RESTORE_SWITCH_STACK + moveml %sp@+,%a3-%a6/%d6-%d7 +.endm + +#endif /* !CONFIG_COLDFIRE */ + +/* + * Register %a2 is reserved and set to current task on MMU enabled systems. + * Non-MMU systems do not reserve %a2 in this way, and this definition is + * not used for them. + */ +#define curptr a2 + +#define GET_CURRENT(tmp) get_current tmp +.macro get_current reg=%d0 + movel %sp,\reg + andw #-THREAD_SIZE,\reg + movel \reg,%curptr + movel %curptr@,%curptr +.endm + +#else /* C source */ + +#define STR(X) STR1(X) +#define STR1(X) #X + +#define SAVE_ALL_INT \ + "clrl %%sp@-;" /* stk_adj */ \ + "pea -1:w;" /* orig d0 = -1 */ \ + "movel %%d0,%%sp@-;" /* d0 */ \ + "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-" + +#define GET_CURRENT(tmp) \ + "movel %%sp,"#tmp"\n\t" \ + "andw #-"STR(THREAD_SIZE)","#tmp"\n\t" \ + "movel "#tmp",%%a2\n\t" \ + "movel %%a2@,%%a2" + #endif + +#endif /* __M68K_ENTRY_H */ diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h deleted file mode 100644 index 73b8c8fbed9c..000000000000 --- a/arch/m68k/include/asm/entry_mm.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef __M68K_ENTRY_H -#define __M68K_ENTRY_H - -#include <asm/setup.h> -#include <asm/page.h> -#ifdef __ASSEMBLY__ -#include <asm/thread_info.h> -#endif - -/* - * Stack layout in 'ret_from_exception': - * - * This allows access to the syscall arguments in registers d1-d5 - * - * 0(sp) - d1 - * 4(sp) - d2 - * 8(sp) - d3 - * C(sp) - d4 - * 10(sp) - d5 - * 14(sp) - a0 - * 18(sp) - a1 - * 1C(sp) - a2 - * 20(sp) - d0 - * 24(sp) - orig_d0 - * 28(sp) - stack adjustment - * 2C(sp) - sr - * 2E(sp) - pc - * 32(sp) - format & vector - */ - -/* - * 97/05/14 Andreas: Register %a2 is now set to the current task throughout - * the whole kernel. - */ - -/* the following macro is used when enabling interrupts */ -#if defined(MACH_ATARI_ONLY) - /* block out HSYNC on the atari */ -#define ALLOWINT (~0x400) -#define MAX_NOINT_IPL 3 -#else - /* portable version */ -#define ALLOWINT (~0x700) -#define MAX_NOINT_IPL 0 -#endif /* machine compilation types */ - -#ifdef __ASSEMBLY__ - -#define curptr a2 - -LFLUSH_I_AND_D = 0x00000808 - -#define SAVE_ALL_INT save_all_int -#define SAVE_ALL_SYS save_all_sys -#define RESTORE_ALL restore_all -/* - * This defines the normal kernel pt-regs layout. - * - * regs a3-a6 and d6-d7 are preserved by C code - * the kernel doesn't mess with usp unless it needs to - */ - -/* - * a -1 in the orig_d0 field signifies - * that the stack frame is NOT for syscall - */ -.macro save_all_int - clrl %sp@- | stk_adj - pea -1:w | orig d0 - movel %d0,%sp@- | d0 - moveml %d1-%d5/%a0-%a1/%curptr,%sp@- -.endm - -.macro save_all_sys - clrl %sp@- | stk_adj - movel %d0,%sp@- | orig d0 - movel %d0,%sp@- | d0 - moveml %d1-%d5/%a0-%a1/%curptr,%sp@- -.endm - -.macro restore_all - moveml %sp@+,%a0-%a1/%curptr/%d1-%d5 - movel %sp@+,%d0 - addql #4,%sp | orig d0 - addl %sp@+,%sp | stk adj - rte -.endm - -#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */ - -#define SAVE_SWITCH_STACK save_switch_stack -#define RESTORE_SWITCH_STACK restore_switch_stack -#define GET_CURRENT(tmp) get_current tmp - -.macro save_switch_stack - moveml %a3-%a6/%d6-%d7,%sp@- -.endm - -.macro restore_switch_stack - moveml %sp@+,%a3-%a6/%d6-%d7 -.endm - -.macro get_current reg=%d0 - movel %sp,\reg - andw #-THREAD_SIZE,\reg - movel \reg,%curptr - movel %curptr@,%curptr -.endm - -#else /* C source */ - -#define STR(X) STR1(X) -#define STR1(X) #X - -#define SAVE_ALL_INT \ - "clrl %%sp@-;" /* stk_adj */ \ - "pea -1:w;" /* orig d0 = -1 */ \ - "movel %%d0,%%sp@-;" /* d0 */ \ - "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-" -#define GET_CURRENT(tmp) \ - "movel %%sp,"#tmp"\n\t" \ - "andw #-"STR(THREAD_SIZE)","#tmp"\n\t" \ - "movel "#tmp",%%a2\n\t" \ - "movel %%a2@,%%a2" - -#endif - -#endif /* __M68K_ENTRY_H */ diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h deleted file mode 100644 index 68611e3dbb1d..000000000000 --- a/arch/m68k/include/asm/entry_no.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef __M68KNOMMU_ENTRY_H -#define __M68KNOMMU_ENTRY_H - -#include <asm/setup.h> -#include <asm/page.h> - -/* - * Stack layout in 'ret_from_exception': - * - * This allows access to the syscall arguments in registers d1-d5 - * - * 0(sp) - d1 - * 4(sp) - d2 - * 8(sp) - d3 - * C(sp) - d4 - * 10(sp) - d5 - * 14(sp) - a0 - * 18(sp) - a1 - * 1C(sp) - a2 - * 20(sp) - d0 - * 24(sp) - orig_d0 - * 28(sp) - stack adjustment - * 2C(sp) - [ sr ] [ format & vector ] - * 2E(sp) - [ pc-hiword ] [ sr ] - * 30(sp) - [ pc-loword ] [ pc-hiword ] - * 32(sp) - [ format & vector ] [ pc-loword ] - * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ - * M68K COLDFIRE - */ - -#define ALLOWINT (~0x700) - -#ifdef __ASSEMBLY__ - -#define SWITCH_STACK_SIZE (6*4+4) /* Includes return address */ - -/* - * This defines the normal kernel pt-regs layout. - * - * regs are a2-a6 and d6-d7 preserved by C code - * the kernel doesn't mess with usp unless it needs to - */ - -#ifdef CONFIG_COLDFIRE -#ifdef CONFIG_COLDFIRE_SW_A7 -/* - * This is made a little more tricky on older ColdFires. There is no - * separate supervisor and user stack pointers. Need to artificially - * construct a usp in software... When doing this we need to disable - * interrupts, otherwise bad things will happen. - */ -.globl sw_usp -.globl sw_ksp - -.macro SAVE_ALL - move #0x2700,%sr /* disable intrs */ - btst #5,%sp@(2) /* from user? */ - bnes 6f /* no, skip */ - movel %sp,sw_usp /* save user sp */ - addql #8,sw_usp /* remove exception */ - movel sw_ksp,%sp /* kernel sp */ - subql #8,%sp /* room for exception */ - clrl %sp@- /* stkadj */ - movel %d0,%sp@- /* orig d0 */ - movel %d0,%sp@- /* d0 */ - lea %sp@(-32),%sp /* space for 8 regs */ - moveml %d1-%d5/%a0-%a2,%sp@ - movel sw_usp,%a0 /* get usp */ - movel %a0@-,%sp@(PT_OFF_PC) /* copy exception program counter */ - movel %a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */ - bra 7f - 6: - clrl %sp@- /* stkadj */ - movel %d0,%sp@- /* orig d0 */ - movel %d0,%sp@- /* d0 */ - lea %sp@(-32),%sp /* space for 8 regs */ - moveml %d1-%d5/%a0-%a2,%sp@ - 7: -.endm - -.macro RESTORE_USER - move #0x2700,%sr /* disable intrs */ - movel sw_usp,%a0 /* get usp */ - movel %sp@(PT_OFF_PC),%a0@- /* copy exception program counter */ - movel %sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */ - moveml %sp@,%d1-%d5/%a0-%a2 - lea %sp@(32),%sp /* space for 8 regs */ - movel %sp@+,%d0 - addql #4,%sp /* orig d0 */ - addl %sp@+,%sp /* stkadj */ - addql #8,%sp /* remove exception */ - movel %sp,sw_ksp /* save ksp */ - subql #8,sw_usp /* set exception */ - movel sw_usp,%sp /* restore usp */ - rte -.endm - -.macro RDUSP - movel sw_usp,%a3 -.endm - -.macro WRUSP - movel %a3,sw_usp -.endm - -#else /* !CONFIG_COLDFIRE_SW_A7 */ -/* - * Modern ColdFire parts have separate supervisor and user stack - * pointers. Simple load and restore macros for this case. - */ -.macro SAVE_ALL - move #0x2700,%sr /* disable intrs */ - clrl %sp@- /* stkadj */ - movel %d0,%sp@- /* orig d0 */ - movel %d0,%sp@- /* d0 */ - lea %sp@(-32),%sp /* space for 8 regs */ - moveml %d1-%d5/%a0-%a2,%sp@ -.endm - -.macro RESTORE_USER - moveml %sp@,%d1-%d5/%a0-%a2 - lea %sp@(32),%sp /* space for 8 regs */ - movel %sp@+,%d0 - addql #4,%sp /* orig d0 */ - addl %sp@+,%sp /* stkadj */ - rte -.endm - -.macro RDUSP - /*move %usp,%a3*/ - .word 0x4e6b -.endm - -.macro WRUSP - /*move %a3,%usp*/ - .word 0x4e63 -.endm - -#endif /* !CONFIG_COLDFIRE_SW_A7 */ - -.macro SAVE_SWITCH_STACK - lea %sp@(-24),%sp /* 6 regs */ - moveml %a3-%a6/%d6-%d7,%sp@ -.endm - -.macro RESTORE_SWITCH_STACK - moveml %sp@,%a3-%a6/%d6-%d7 - lea %sp@(24),%sp /* 6 regs */ -.endm - -#else /* !CONFIG_COLDFIRE */ - -/* - * Standard 68k interrupt entry and exit macros. - */ -.macro SAVE_ALL - clrl %sp@- /* stkadj */ - movel %d0,%sp@- /* orig d0 */ - movel %d0,%sp@- /* d0 */ - moveml %d1-%d5/%a0-%a2,%sp@- -.endm - -.macro RESTORE_ALL - moveml %sp@+,%a0-%a2/%d1-%d5 - movel %sp@+,%d0 - addql #4,%sp /* orig d0 */ - addl %sp@+,%sp /* stkadj */ - rte -.endm - -.macro SAVE_SWITCH_STACK - moveml %a3-%a6/%d6-%d7,%sp@- -.endm - -.macro RESTORE_SWITCH_STACK - moveml %sp@+,%a3-%a6/%d6-%d7 -.endm - -#endif /* !COLDFIRE_SW_A7 */ -#endif /* __ASSEMBLY__ */ -#endif /* __M68KNOMMU_ENTRY_H */ diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h index b6bf2c518bac..eda62de7e607 100644 --- a/arch/m68k/include/asm/m520xsim.h +++ b/arch/m68k/include/asm/m520xsim.h @@ -90,15 +90,13 @@ #define MCFGPIO_PDDR_FECH 0xFC0A4013 #define MCFGPIO_PDDR_FECL 0xFC0A4014 -#define MCFGPIO_PPDSDR_BUSCTL 0xFC0A401A -#define MCFGPIO_PPDSDR_BE 0xFC0A401B -#define MCFGPIO_PPDSDR_CS 0xFC0A401C -#define MCFGPIO_PPDSDR_FECI2C 0xFC0A401D -#define MCFGPIO_PPDSDR_QSPI 0xFC0A401E -#define MCFGPIO_PPDSDR_TIMER 0xFC0A401F -#define MCFGPIO_PPDSDR_UART 0xFC0A4021 -#define MCFGPIO_PPDSDR_FECH 0xFC0A4021 -#define MCFGPIO_PPDSDR_FECL 0xFC0A4022 +#define MCFGPIO_PPDSDR_CS 0xFC0A401A +#define MCFGPIO_PPDSDR_FECI2C 0xFC0A401B +#define MCFGPIO_PPDSDR_QSPI 0xFC0A401C +#define MCFGPIO_PPDSDR_TIMER 0xFC0A401D +#define MCFGPIO_PPDSDR_UART 0xFC0A401E +#define MCFGPIO_PPDSDR_FECH 0xFC0A401F +#define MCFGPIO_PPDSDR_FECL 0xFC0A4020 #define MCFGPIO_PCLRR_BUSCTL 0xFC0A4024 #define MCFGPIO_PCLRR_BE 0xFC0A4025 @@ -113,11 +111,11 @@ /* * Generic GPIO support */ -#define MCFGPIO_PODR MCFGPIO_PODR_BUSCTL -#define MCFGPIO_PDDR MCFGPIO_PDDR_BUSCTL -#define MCFGPIO_PPDR MCFGPIO_PPDSDR_BUSCTL -#define MCFGPIO_SETR MCFGPIO_PPDSDR_BUSCTL -#define MCFGPIO_CLRR MCFGPIO_PCLRR_BUSCTL +#define MCFGPIO_PODR MCFGPIO_PODR_CS +#define MCFGPIO_PDDR MCFGPIO_PDDR_CS +#define MCFGPIO_PPDR MCFGPIO_PPDSDR_CS +#define MCFGPIO_SETR MCFGPIO_PPDSDR_CS +#define MCFGPIO_CLRR MCFGPIO_PCLRR_CS #define MCFGPIO_PIN_MAX 80 #define MCFGPIO_IRQ_MAX 8 diff --git a/arch/m68k/include/asm/mcfqspi.h b/arch/m68k/include/asm/mcfqspi.h index 39d90d51111d..7fe631972f1f 100644 --- a/arch/m68k/include/asm/mcfqspi.h +++ b/arch/m68k/include/asm/mcfqspi.h @@ -24,9 +24,11 @@ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) #define MCFQSPI_IOBASE (MCF_IPSBAR + 0x340) #elif defined(CONFIG_M5249) -#define MCFQSPI_IOBASE (MCF_MBAR + 0x300) -#elif defined(CONFIG_M520x) || defined(CONFIG_M532x) -#define MCFQSPI_IOBASE 0xFC058000 +#define MCFQSPI_IOBASE (MCF_MBAR + 0x300) +#elif defined(CONFIG_M520x) +#define MCFQSPI_IOBASE 0xFC05C000 +#elif defined(CONFIG_M532x) +#define MCFQSPI_IOBASE 0xFC058000 #endif #define MCFQSPI_IOSIZE 0x40 diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h index 31d5570d6567..89f201434b5a 100644 --- a/arch/m68k/include/asm/page_mm.h +++ b/arch/m68k/include/asm/page_mm.h @@ -162,7 +162,7 @@ static inline __attribute_const__ int __virt_to_node_shift(void) pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn); \ }) #define page_to_pfn(_page) ({ \ - struct page *__p = (_page); \ + const struct page *__p = (_page); \ struct pglist_data *pgdat; \ pgdat = &pg_data_map[page_to_nid(__p)]; \ ((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn; \ diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h index 90595721185f..a8d1c60eb9ce 100644 --- a/arch/m68k/include/asm/page_no.h +++ b/arch/m68k/include/asm/page_no.h @@ -5,6 +5,9 @@ extern unsigned long memory_start; extern unsigned long memory_end; +extern unsigned long _rambase; +extern unsigned long _ramstart; +extern unsigned long _ramend; #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) #define free_user_page(page, addr) free_page(addr) diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index d8ef53ac03f9..568facf30276 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h @@ -135,6 +135,12 @@ do { \ wrusp(_usp); \ } while(0) +static inline int handle_kernel_fault(struct pt_regs *regs) +{ + /* Any fault in kernel is fatal on non-mmu */ + return 0; +} + #endif /* Forward declaration, a strange C thing */ diff --git a/arch/m68k/include/asm/sections.h b/arch/m68k/include/asm/sections.h index d64967ecfec6..5277e52715ec 100644 --- a/arch/m68k/include/asm/sections.h +++ b/arch/m68k/include/asm/sections.h @@ -3,4 +3,6 @@ #include <asm-generic/sections.h> +extern char _sbss[], _ebss[]; + #endif /* _ASM_M68K_SECTIONS_H */ diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index c482ebc9dd54..e7f0f2e5ad44 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -1,5 +1,21 @@ -ifdef CONFIG_MMU -include arch/m68k/kernel/Makefile_mm -else -include arch/m68k/kernel/Makefile_no +# +# Makefile for the linux kernel. +# + +extra-$(CONFIG_MMU) := head.o +extra-$(CONFIG_SUN3) := sun3-head.o +extra-y += vmlinux.lds + +obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ + sys_m68k.o syscalltable.o time.o traps.o + +obj-$(CONFIG_MMU) += ints.o devres.o vectors.o +devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o + +ifndef CONFIG_MMU_SUN3 +obj-y += dma.o endif +ifndef CONFIG_MMU +obj-y += init_task.o irq.o +endif + diff --git a/arch/m68k/kernel/Makefile_mm b/arch/m68k/kernel/Makefile_mm deleted file mode 100644 index aced67804579..000000000000 --- a/arch/m68k/kernel/Makefile_mm +++ /dev/null @@ -1,17 +0,0 @@ -# -# Makefile for the linux kernel. -# - -ifndef CONFIG_SUN3 - extra-y := head.o -else - extra-y := sun3-head.o -endif -extra-y += vmlinux.lds - -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ - sys_m68k.o time.o setup.o m68k_ksyms.o devres.o syscalltable.o - -devres-y = ../../../kernel/irq/devres.o - -obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo diff --git a/arch/m68k/kernel/Makefile_no b/arch/m68k/kernel/Makefile_no deleted file mode 100644 index 37c3fc074c0a..000000000000 --- a/arch/m68k/kernel/Makefile_no +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for arch/m68knommu/kernel. -# - -extra-y := vmlinux.lds - -obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \ - setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o - -obj-$(CONFIG_MODULES) += module.o diff --git a/arch/m68k/kernel/entry_no.S b/arch/m68k/kernel/entry_no.S index 5f0f6b598b5a..1b4289061a64 100644 --- a/arch/m68k/kernel/entry_no.S +++ b/arch/m68k/kernel/entry_no.S @@ -43,7 +43,7 @@ .globl sys_vfork ENTRY(buserr) - SAVE_ALL + SAVE_ALL_INT moveq #-1,%d0 movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ @@ -52,7 +52,7 @@ ENTRY(buserr) jra ret_from_exception ENTRY(trap) - SAVE_ALL + SAVE_ALL_INT moveq #-1,%d0 movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ @@ -64,7 +64,7 @@ ENTRY(trap) .globl dbginterrupt ENTRY(dbginterrupt) - SAVE_ALL + SAVE_ALL_INT moveq #-1,%d0 movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 16b2de7f5101..2ed8c0fb1517 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -36,6 +36,7 @@ #include <asm/irq.h> #include <asm/machdep.h> #include <asm/pgtable.h> +#include <asm/sections.h> unsigned long memory_start; unsigned long memory_end; @@ -80,9 +81,6 @@ void (*mach_power_off)(void); #define CPU_INSTR_PER_JIFFY 16 #endif -extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; -extern int _ramstart, _ramend; - #if defined(CONFIG_UBOOT) /* * parse_uboot_commandline diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index 00d1452f9571..c468f2edaa85 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -189,7 +189,7 @@ ENTRY(sys_call_table) .long sys_getpagesize .long sys_ni_syscall /* old "query_module" */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index c98add3f5f0f..89362f2bb56a 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -1,5 +1,1107 @@ -#ifdef CONFIG_MMU -#include "traps_mm.c" +/* + * linux/arch/m68k/kernel/traps.c + * + * Copyright (C) 1993, 1994 by Hamish Macdonald + * + * 68040 fixes by Michael Rausch + * 68040 fixes by Martin Apel + * 68040 fixes and writeback by Richard Zidlicky + * 68060 fixes by Roman Hodek + * 68060 fixes by Jesper Skov + * + * 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. + */ + +/* + * Sets up all exception vectors + */ + +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/user.h> +#include <linux/string.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/ptrace.h> +#include <linux/kallsyms.h> + +#include <asm/setup.h> +#include <asm/fpu.h> +#include <asm/system.h> +#include <asm/uaccess.h> +#include <asm/traps.h> +#include <asm/pgalloc.h> +#include <asm/machdep.h> +#include <asm/siginfo.h> + + +static const char *vec_names[] = { + [VEC_RESETSP] = "RESET SP", + [VEC_RESETPC] = "RESET PC", + [VEC_BUSERR] = "BUS ERROR", + [VEC_ADDRERR] = "ADDRESS ERROR", + [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION", + [VEC_ZERODIV] = "ZERO DIVIDE", + [VEC_CHK] = "CHK", + [VEC_TRAP] = "TRAPcc", + [VEC_PRIV] = "PRIVILEGE VIOLATION", + [VEC_TRACE] = "TRACE", + [VEC_LINE10] = "LINE 1010", + [VEC_LINE11] = "LINE 1111", + [VEC_RESV12] = "UNASSIGNED RESERVED 12", + [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION", + [VEC_FORMAT] = "FORMAT ERROR", + [VEC_UNINT] = "UNINITIALIZED INTERRUPT", + [VEC_RESV16] = "UNASSIGNED RESERVED 16", + [VEC_RESV17] = "UNASSIGNED RESERVED 17", + [VEC_RESV18] = "UNASSIGNED RESERVED 18", + [VEC_RESV19] = "UNASSIGNED RESERVED 19", + [VEC_RESV20] = "UNASSIGNED RESERVED 20", + [VEC_RESV21] = "UNASSIGNED RESERVED 21", + [VEC_RESV22] = "UNASSIGNED RESERVED 22", + [VEC_RESV23] = "UNASSIGNED RESERVED 23", + [VEC_SPUR] = "SPURIOUS INTERRUPT", + [VEC_INT1] = "LEVEL 1 INT", + [VEC_INT2] = "LEVEL 2 INT", + [VEC_INT3] = "LEVEL 3 INT", + [VEC_INT4] = "LEVEL 4 INT", + [VEC_INT5] = "LEVEL 5 INT", + [VEC_INT6] = "LEVEL 6 INT", + [VEC_INT7] = "LEVEL 7 INT", + [VEC_SYS] = "SYSCALL", + [VEC_TRAP1] = "TRAP #1", + [VEC_TRAP2] = "TRAP #2", + [VEC_TRAP3] = "TRAP #3", + [VEC_TRAP4] = "TRAP #4", + [VEC_TRAP5] = "TRAP #5", + [VEC_TRAP6] = "TRAP #6", + [VEC_TRAP7] = "TRAP #7", + [VEC_TRAP8] = "TRAP #8", + [VEC_TRAP9] = "TRAP #9", + [VEC_TRAP10] = "TRAP #10", + [VEC_TRAP11] = "TRAP #11", + [VEC_TRAP12] = "TRAP #12", + [VEC_TRAP13] = "TRAP #13", + [VEC_TRAP14] = "TRAP #14", + [VEC_TRAP15] = "TRAP #15", + [VEC_FPBRUC] = "FPCP BSUN", + [VEC_FPIR] = "FPCP INEXACT", + [VEC_FPDIVZ] = "FPCP DIV BY 0", + [VEC_FPUNDER] = "FPCP UNDERFLOW", + [VEC_FPOE] = "FPCP OPERAND ERROR", + [VEC_FPOVER] = "FPCP OVERFLOW", + [VEC_FPNAN] = "FPCP SNAN", + [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION", + [VEC_MMUCFG] = "MMU CONFIGURATION ERROR", + [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR", + [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR", + [VEC_RESV59] = "UNASSIGNED RESERVED 59", + [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60", + [VEC_UNIMPII] = "UNASSIGNED RESERVED 61", + [VEC_RESV62] = "UNASSIGNED RESERVED 62", + [VEC_RESV63] = "UNASSIGNED RESERVED 63", +}; + +static const char *space_names[] = { + [0] = "Space 0", + [USER_DATA] = "User Data", + [USER_PROGRAM] = "User Program", +#ifndef CONFIG_SUN3 + [3] = "Space 3", #else -#include "traps_no.c" + [FC_CONTROL] = "Control", +#endif + [4] = "Space 4", + [SUPER_DATA] = "Super Data", + [SUPER_PROGRAM] = "Super Program", + [CPU_SPACE] = "CPU" +}; + +void die_if_kernel(char *,struct pt_regs *,int); +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code); +int send_fault_sig(struct pt_regs *regs); + +asmlinkage void trap_c(struct frame *fp); + +#if defined (CONFIG_M68060) +static inline void access_error060 (struct frame *fp) +{ + unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ + +#ifdef DEBUG + printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); +#endif + + if (fslw & MMU060_BPE) { + /* branch prediction error -> clear branch cache */ + __asm__ __volatile__ ("movec %/cacr,%/d0\n\t" + "orl #0x00400000,%/d0\n\t" + "movec %/d0,%/cacr" + : : : "d0" ); + /* return if there's no other error */ + if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) + return; + } + + if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { + unsigned long errorcode; + unsigned long addr = fp->un.fmt4.effaddr; + + if (fslw & MMU060_MA) + addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; + + errorcode = 1; + if (fslw & MMU060_DESC_ERR) { + __flush_tlb040_one(addr); + errorcode = 0; + } + if (fslw & MMU060_W) + errorcode |= 2; +#ifdef DEBUG + printk("errorcode = %d\n", errorcode ); +#endif + do_page_fault(&fp->ptregs, addr, errorcode); + } else if (fslw & (MMU060_SEE)){ + /* Software Emulation Error. + * fault during mem_read/mem_write in ifpsp060/os.S + */ + send_fault_sig(&fp->ptregs); + } else if (!(fslw & (MMU060_RE|MMU060_WE)) || + send_fault_sig(&fp->ptregs) > 0) { + printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); + printk( "68060 access error, fslw=%lx\n", fslw ); + trap_c( fp ); + } +} +#endif /* CONFIG_M68060 */ + +#if defined (CONFIG_M68040) +static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) +{ + unsigned long mmusr; + mm_segment_t old_fs = get_fs(); + + set_fs(MAKE_MM_SEG(wbs)); + + if (iswrite) + asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); + else + asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); + + asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); + + set_fs(old_fs); + + return mmusr; +} + +static inline int do_040writeback1(unsigned short wbs, unsigned long wba, + unsigned long wbd) +{ + int res = 0; + mm_segment_t old_fs = get_fs(); + + /* set_fs can not be moved, otherwise put_user() may oops */ + set_fs(MAKE_MM_SEG(wbs)); + + switch (wbs & WBSIZ_040) { + case BA_SIZE_BYTE: + res = put_user(wbd & 0xff, (char __user *)wba); + break; + case BA_SIZE_WORD: + res = put_user(wbd & 0xffff, (short __user *)wba); + break; + case BA_SIZE_LONG: + res = put_user(wbd, (int __user *)wba); + break; + } + + /* set_fs can not be moved, otherwise put_user() may oops */ + set_fs(old_fs); + + +#ifdef DEBUG + printk("do_040writeback1, res=%d\n",res); +#endif + + return res; +} + +/* after an exception in a writeback the stack frame corresponding + * to that exception is discarded, set a few bits in the old frame + * to simulate what it should look like + */ +static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs) +{ + fp->un.fmt7.faddr = wba; + fp->un.fmt7.ssw = wbs & 0xff; + if (wba != current->thread.faddr) + fp->un.fmt7.ssw |= MA_040; +} + +static inline void do_040writebacks(struct frame *fp) +{ + int res = 0; +#if 0 + if (fp->un.fmt7.wb1s & WBV_040) + printk("access_error040: cannot handle 1st writeback. oops.\n"); +#endif + + if ((fp->un.fmt7.wb2s & WBV_040) && + !(fp->un.fmt7.wb2s & WBTT_040)) { + res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, + fp->un.fmt7.wb2d); + if (res) + fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); + else + fp->un.fmt7.wb2s = 0; + } + + /* do the 2nd wb only if the first one was successful (except for a kernel wb) */ + if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { + res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, + fp->un.fmt7.wb3d); + if (res) + { + fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); + + fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; + fp->un.fmt7.wb3s &= (~WBV_040); + fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; + fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; + } + else + fp->un.fmt7.wb3s = 0; + } + + if (res) + send_fault_sig(&fp->ptregs); +} + +/* + * called from sigreturn(), must ensure userspace code didn't + * manipulate exception frame to circumvent protection, then complete + * pending writebacks + * we just clear TM2 to turn it into a userspace access + */ +asmlinkage void berr_040cleanup(struct frame *fp) +{ + fp->un.fmt7.wb2s &= ~4; + fp->un.fmt7.wb3s &= ~4; + + do_040writebacks(fp); +} + +static inline void access_error040(struct frame *fp) +{ + unsigned short ssw = fp->un.fmt7.ssw; + unsigned long mmusr; + +#ifdef DEBUG + printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); + printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, + fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); + printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", + fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, + fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); +#endif + + if (ssw & ATC_040) { + unsigned long addr = fp->un.fmt7.faddr; + unsigned long errorcode; + + /* + * The MMU status has to be determined AFTER the address + * has been corrected if there was a misaligned access (MA). + */ + if (ssw & MA_040) + addr = (addr + 7) & -8; + + /* MMU error, get the MMUSR info for this access */ + mmusr = probe040(!(ssw & RW_040), addr, ssw); +#ifdef DEBUG + printk("mmusr = %lx\n", mmusr); +#endif + errorcode = 1; + if (!(mmusr & MMU_R_040)) { + /* clear the invalid atc entry */ + __flush_tlb040_one(addr); + errorcode = 0; + } + + /* despite what documentation seems to say, RMW + * accesses have always both the LK and RW bits set */ + if (!(ssw & RW_040) || (ssw & LK_040)) + errorcode |= 2; + + if (do_page_fault(&fp->ptregs, addr, errorcode)) { +#ifdef DEBUG + printk("do_page_fault() !=0\n"); +#endif + if (user_mode(&fp->ptregs)){ + /* delay writebacks after signal delivery */ +#ifdef DEBUG + printk(".. was usermode - return\n"); +#endif + return; + } + /* disable writeback into user space from kernel + * (if do_page_fault didn't fix the mapping, + * the writeback won't do good) + */ +disable_wb: +#ifdef DEBUG + printk(".. disabling wb2\n"); +#endif + if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) + fp->un.fmt7.wb2s &= ~WBV_040; + if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) + fp->un.fmt7.wb3s &= ~WBV_040; + } + } else { + /* In case of a bus error we either kill the process or expect + * the kernel to catch the fault, which then is also responsible + * for cleaning up the mess. + */ + current->thread.signo = SIGBUS; + current->thread.faddr = fp->un.fmt7.faddr; + if (send_fault_sig(&fp->ptregs) >= 0) + printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, + fp->un.fmt7.faddr); + goto disable_wb; + } + + do_040writebacks(fp); +} +#endif /* CONFIG_M68040 */ + +#if defined(CONFIG_SUN3) +#include <asm/sun3mmu.h> + +extern int mmu_emu_handle_fault (unsigned long, int, int); + +/* sun3 version of bus_error030 */ + +static inline void bus_error030 (struct frame *fp) +{ + unsigned char buserr_type = sun3_get_buserr (); + unsigned long addr, errorcode; + unsigned short ssw = fp->un.fmtb.ssw; + extern unsigned long _sun3_map_test_start, _sun3_map_test_end; + +#ifdef DEBUG + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + ssw & FC ? + fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 + : + fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); +#endif + + /* + * Check if this page should be demand-mapped. This needs to go before + * the testing for a bad kernel-space access (demand-mapping applies + * to kernel accesses too). + */ + + if ((ssw & DF) + && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) { + if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0)) + return; + } + + /* Check for kernel-space pagefault (BAD). */ + if (fp->ptregs.sr & PS_S) { + /* kernel fault must be a data fault to user space */ + if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { + // try checking the kernel mappings before surrender + if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1)) + return; + /* instruction fault or kernel data fault! */ + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + fp->ptregs.pc); + if (ssw & DF) { + /* was this fault incurred testing bus mappings? */ + if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && + (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { + send_fault_sig(&fp->ptregs); + return; + } + + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); + } + printk ("BAD KERNEL BUSERR\n"); + + die_if_kernel("Oops", &fp->ptregs,0); + force_sig(SIGKILL, current); + return; + } + } else { + /* user fault */ + if (!(ssw & (FC | FB)) && !(ssw & DF)) + /* not an instruction fault or data fault! BAD */ + panic ("USER BUSERR w/o instruction or data fault"); + } + + + /* First handle the data fault, if any. */ + if (ssw & DF) { + addr = fp->un.fmtb.daddr; + +// errorcode bit 0: 0 -> no page 1 -> protection fault +// errorcode bit 1: 0 -> read fault 1 -> write fault + +// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault +// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault + + if (buserr_type & SUN3_BUSERR_PROTERR) + errorcode = 0x01; + else if (buserr_type & SUN3_BUSERR_INVALID) + errorcode = 0x00; + else { +#ifdef DEBUG + printk ("*** unexpected busfault type=%#04x\n", buserr_type); + printk ("invalid %s access at %#lx from pc %#lx\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc); +#endif + die_if_kernel ("Oops", &fp->ptregs, buserr_type); + force_sig (SIGBUS, current); + return; + } + +//todo: wtf is RM bit? --m + if (!(ssw & RW) || ssw & RM) + errorcode |= 0x02; + + /* Handle page fault. */ + do_page_fault (&fp->ptregs, addr, errorcode); + + /* Retry the data fault now. */ + return; + } + + /* Now handle the instruction fault. */ + + /* Get the fault address. */ + if (fp->ptregs.format == 0xA) + addr = fp->ptregs.pc + 4; + else + addr = fp->un.fmtb.baddr; + if (ssw & FC) + addr -= 2; + + if (buserr_type & SUN3_BUSERR_INVALID) { + if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) + do_page_fault (&fp->ptregs, addr, 0); + } else { +#ifdef DEBUG + printk ("protection fault on insn access (segv).\n"); +#endif + force_sig (SIGSEGV, current); + } +} +#else +#if defined(CPU_M68020_OR_M68030) +static inline void bus_error030 (struct frame *fp) +{ + volatile unsigned short temp; + unsigned short mmusr; + unsigned long addr, errorcode; + unsigned short ssw = fp->un.fmtb.ssw; +#ifdef DEBUG + unsigned long desc; + + printk ("pid = %x ", current->pid); + printk ("SSW=%#06x ", ssw); + + if (ssw & (FC | FB)) + printk ("Instruction fault at %#010lx\n", + ssw & FC ? + fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 + : + fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); +#endif + + /* ++andreas: If a data fault and an instruction fault happen + at the same time map in both pages. */ + + /* First handle the data fault, if any. */ + if (ssw & DF) { + addr = fp->un.fmtb.daddr; + +#ifdef DEBUG + asm volatile ("ptestr %3,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr), "d" (ssw)); +#else + asm volatile ("ptestr %2,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr), "d" (ssw)); +#endif + mmusr = temp; + +#ifdef DEBUG + printk("mmusr is %#x for addr %#lx in task %p\n", + mmusr, addr, current); + printk("descriptor address is %#lx, contents %#lx\n", + __va(desc), *(unsigned long *)__va(desc)); +#endif + + errorcode = (mmusr & MMU_I) ? 0 : 1; + if (!(ssw & RW) || (ssw & RM)) + errorcode |= 2; + + if (mmusr & (MMU_I | MMU_WP)) { + if (ssw & 4) { + printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); + goto buserr; + } + /* Don't try to do anything further if an exception was + handled. */ + if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) + return; + } else if (!(mmusr & MMU_I)) { + /* probably a 020 cas fault */ + if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) + printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); + } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { + printk("invalid %s access at %#lx from pc %#lx\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc); + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } else { +#if 0 + static volatile long tlong; +#endif + + printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc, ssw); + asm volatile ("ptestr #1,%1@,#0\n\t" + "pmove %%psr,%0@" + : /* no outputs */ + : "a" (&temp), "a" (addr)); + mmusr = temp; + + printk ("level 0 mmusr is %#x\n", mmusr); +#if 0 + asm volatile ("pmove %%tt0,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt0 is %#lx, ", tlong); + asm volatile ("pmove %%tt1,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt1 is %#lx\n", tlong); +#endif +#ifdef DEBUG + printk("Unknown SIGSEGV - 1\n"); +#endif + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } + + /* setup an ATC entry for the access about to be retried */ + if (!(ssw & RW) || (ssw & RM)) + asm volatile ("ploadw %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + else + asm volatile ("ploadr %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + } + + /* Now handle the instruction fault. */ + + if (!(ssw & (FC|FB))) + return; + + if (fp->ptregs.sr & PS_S) { + printk("Instruction fault at %#010lx\n", + fp->ptregs.pc); + buserr: + printk ("BAD KERNEL BUSERR\n"); + die_if_kernel("Oops",&fp->ptregs,0); + force_sig(SIGKILL, current); + return; + } + + /* get the fault address */ + if (fp->ptregs.format == 10) + addr = fp->ptregs.pc + 4; + else + addr = fp->un.fmtb.baddr; + if (ssw & FC) + addr -= 2; + + if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0) + /* Insn fault on same page as data fault. But we + should still create the ATC entry. */ + goto create_atc_entry; + +#ifdef DEBUG + asm volatile ("ptestr #1,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr)); +#else + asm volatile ("ptestr #1,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr)); +#endif + mmusr = temp; + +#ifdef DEBUG + printk ("mmusr is %#x for addr %#lx in task %p\n", + mmusr, addr, current); + printk ("descriptor address is %#lx, contents %#lx\n", + __va(desc), *(unsigned long *)__va(desc)); +#endif + + if (mmusr & MMU_I) + do_page_fault (&fp->ptregs, addr, 0); + else if (mmusr & (MMU_B|MMU_L|MMU_S)) { + printk ("invalid insn access at %#lx from pc %#lx\n", + addr, fp->ptregs.pc); +#ifdef DEBUG + printk("Unknown SIGSEGV - 2\n"); +#endif + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } + +create_atc_entry: + /* setup an ATC entry for the access about to be retried */ + asm volatile ("ploadr #2,%0@" : /* no outputs */ + : "a" (addr)); +} +#endif /* CPU_M68020_OR_M68030 */ +#endif /* !CONFIG_SUN3 */ + +asmlinkage void buserr_c(struct frame *fp) +{ + /* Only set esp0 if coming from user mode */ + if (user_mode(&fp->ptregs)) + current->thread.esp0 = (unsigned long) fp; + +#ifdef DEBUG + printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); +#endif + + switch (fp->ptregs.format) { +#if defined (CONFIG_M68060) + case 4: /* 68060 access error */ + access_error060 (fp); + break; +#endif +#if defined (CONFIG_M68040) + case 0x7: /* 68040 access error */ + access_error040 (fp); + break; +#endif +#if defined (CPU_M68020_OR_M68030) + case 0xa: + case 0xb: + bus_error030 (fp); + break; +#endif + default: + die_if_kernel("bad frame format",&fp->ptregs,0); +#ifdef DEBUG + printk("Unknown SIGSEGV - 4\n"); +#endif + force_sig(SIGSEGV, current); + } +} + + +static int kstack_depth_to_print = 48; + +void show_trace(unsigned long *stack) +{ + unsigned long *endstack; + unsigned long addr; + int i; + + printk("Call Trace:"); + addr = (unsigned long)stack + THREAD_SIZE - 1; + endstack = (unsigned long *)(addr & -THREAD_SIZE); + i = 0; + while (stack + 1 <= endstack) { + addr = *stack++; + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (__kernel_text_address(addr)) { +#ifndef CONFIG_KALLSYMS + if (i % 5 == 0) + printk("\n "); +#endif + printk(" [<%08lx>] %pS\n", addr, (void *)addr); + i++; + } + } + printk("\n"); +} + +void show_registers(struct pt_regs *regs) +{ + struct frame *fp = (struct frame *)regs; + mm_segment_t old_fs = get_fs(); + u16 c, *cp; + unsigned long addr; + int i; + + print_modules(); + printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); + printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + regs->d0, regs->d1, regs->d2, regs->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + regs->d4, regs->d5, regs->a0, regs->a1); + + printk("Process %s (pid: %d, task=%p)\n", + current->comm, task_pid_nr(current), current); + addr = (unsigned long)&fp->un; + printk("Frame format=%X ", regs->format); + switch (regs->format) { + case 0x2: + printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); + addr += sizeof(fp->un.fmt2); + break; + case 0x3: + printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); + addr += sizeof(fp->un.fmt3); + break; + case 0x4: + printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" + : "eff addr=%08lx pc=%08lx\n"), + fp->un.fmt4.effaddr, fp->un.fmt4.pc); + addr += sizeof(fp->un.fmt4); + break; + case 0x7: + printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", + fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); + printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); + printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); + printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); + printk("push data: %08lx %08lx %08lx %08lx\n", + fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, + fp->un.fmt7.pd3); + addr += sizeof(fp->un.fmt7); + break; + case 0x9: + printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); + addr += sizeof(fp->un.fmt9); + break; + case 0xa: + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, + fp->un.fmta.daddr, fp->un.fmta.dobuf); + addr += sizeof(fp->un.fmta); + break; + case 0xb: + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, + fp->un.fmtb.daddr, fp->un.fmtb.dobuf); + printk("baddr=%08lx dibuf=%08lx ver=%x\n", + fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); + addr += sizeof(fp->un.fmtb); + break; + default: + printk("\n"); + } + show_stack(NULL, (unsigned long *)addr); + + printk("Code:"); + set_fs(KERNEL_DS); + cp = (u16 *)regs->pc; + for (i = -8; i < 16; i++) { + if (get_user(c, cp + i) && i >= 0) { + printk(" Bad PC value."); + break; + } + printk(i ? " %04x" : " <%04x>", c); + } + set_fs(old_fs); + printk ("\n"); +} + +void show_stack(struct task_struct *task, unsigned long *stack) +{ + unsigned long *p; + unsigned long *endstack; + int i; + + if (!stack) { + if (task) + stack = (unsigned long *)task->thread.esp0; + else + stack = (unsigned long *)&stack; + } + endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); + + printk("Stack from %08lx:", (unsigned long)stack); + p = stack; + for (i = 0; i < kstack_depth_to_print; i++) { + if (p + 1 > endstack) + break; + if (i % 8 == 0) + printk("\n "); + printk(" %08lx", *p++); + } + printk("\n"); + show_trace(stack); +} + +/* + * The architecture-independent backtrace generator + */ +void dump_stack(void) +{ + unsigned long stack; + + show_trace(&stack); +} + +EXPORT_SYMBOL(dump_stack); + +/* + * The vector number returned in the frame pointer may also contain + * the "fs" (Fault Status) bits on ColdFire. These are in the bottom + * 2 bits, and upper 2 bits. So we need to mask out the real vector + * number before using it in comparisons. You don't need to do this on + * real 68k parts, but it won't hurt either. + */ + +void bad_super_trap (struct frame *fp) +{ + int vector = (fp->ptregs.vector >> 2) & 0xff; + + console_verbose(); + if (vector < ARRAY_SIZE(vec_names)) + printk ("*** %s *** FORMAT=%X\n", + vec_names[vector], + fp->ptregs.format); + else + printk ("*** Exception %d *** FORMAT=%X\n", + vector, fp->ptregs.format); + if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) { + unsigned short ssw = fp->un.fmtb.ssw; + + printk ("SSW=%#06x ", ssw); + + if (ssw & RC) + printk ("Pipe stage C instruction fault at %#010lx\n", + (fp->ptregs.format) == 0xA ? + fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); + if (ssw & RB) + printk ("Pipe stage B instruction fault at %#010lx\n", + (fp->ptregs.format) == 0xA ? + fp->ptregs.pc + 4 : fp->un.fmtb.baddr); + if (ssw & DF) + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, space_names[ssw & DFC], + fp->ptregs.pc); + } + printk ("Current process id is %d\n", task_pid_nr(current)); + die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); +} + +asmlinkage void trap_c(struct frame *fp) +{ + int sig; + int vector = (fp->ptregs.vector >> 2) & 0xff; + siginfo_t info; + + if (fp->ptregs.sr & PS_S) { + if (vector == VEC_TRACE) { + /* traced a trapping instruction on a 68020/30, + * real exception will be executed afterwards. + */ + } else if (!handle_kernel_fault(&fp->ptregs)) + bad_super_trap(fp); + return; + } + + /* send the appropriate signal to the user program */ + switch (vector) { + case VEC_ADDRERR: + info.si_code = BUS_ADRALN; + sig = SIGBUS; + break; + case VEC_ILLEGAL: + case VEC_LINE10: + case VEC_LINE11: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + case VEC_PRIV: + info.si_code = ILL_PRVOPC; + sig = SIGILL; + break; + case VEC_COPROC: + info.si_code = ILL_COPROC; + sig = SIGILL; + break; + case VEC_TRAP1: + case VEC_TRAP2: + case VEC_TRAP3: + case VEC_TRAP4: + case VEC_TRAP5: + case VEC_TRAP6: + case VEC_TRAP7: + case VEC_TRAP8: + case VEC_TRAP9: + case VEC_TRAP10: + case VEC_TRAP11: + case VEC_TRAP12: + case VEC_TRAP13: + case VEC_TRAP14: + info.si_code = ILL_ILLTRP; + sig = SIGILL; + break; + case VEC_FPBRUC: + case VEC_FPOE: + case VEC_FPNAN: + info.si_code = FPE_FLTINV; + sig = SIGFPE; + break; + case VEC_FPIR: + info.si_code = FPE_FLTRES; + sig = SIGFPE; + break; + case VEC_FPDIVZ: + info.si_code = FPE_FLTDIV; + sig = SIGFPE; + break; + case VEC_FPUNDER: + info.si_code = FPE_FLTUND; + sig = SIGFPE; + break; + case VEC_FPOVER: + info.si_code = FPE_FLTOVF; + sig = SIGFPE; + break; + case VEC_ZERODIV: + info.si_code = FPE_INTDIV; + sig = SIGFPE; + break; + case VEC_CHK: + case VEC_TRAP: + info.si_code = FPE_INTOVF; + sig = SIGFPE; + break; + case VEC_TRACE: /* ptrace single step */ + info.si_code = TRAP_TRACE; + sig = SIGTRAP; + break; + case VEC_TRAP15: /* breakpoint */ + info.si_code = TRAP_BRKPT; + sig = SIGTRAP; + break; + default: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + } + info.si_signo = sig; + info.si_errno = 0; + switch (fp->ptregs.format) { + default: + info.si_addr = (void *) fp->ptregs.pc; + break; + case 2: + info.si_addr = (void *) fp->un.fmt2.iaddr; + break; + case 7: + info.si_addr = (void *) fp->un.fmt7.effaddr; + break; + case 9: + info.si_addr = (void *) fp->un.fmt9.iaddr; + break; + case 10: + info.si_addr = (void *) fp->un.fmta.daddr; + break; + case 11: + info.si_addr = (void *) fp->un.fmtb.daddr; + break; + } + force_sig_info (sig, &info, current); +} + +void die_if_kernel (char *str, struct pt_regs *fp, int nr) +{ + if (!(fp->sr & PS_S)) + return; + + console_verbose(); + printk("%s: %08x\n",str,nr); + show_registers(fp); + add_taint(TAINT_DIE); + do_exit(SIGSEGV); +} + +asmlinkage void set_esp0(unsigned long ssp) +{ + current->thread.esp0 = ssp; +} + +/* + * This function is called if an error occur while accessing + * user-space from the fpsp040 code. + */ +asmlinkage void fpsp040_die(void) +{ + do_exit(SIGSEGV); +} + +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpemu_signal(int signal, int code, void *addr) +{ + siginfo_t info; + + info.si_signo = signal; + info.si_errno = 0; + info.si_code = code; + info.si_addr = addr; + force_sig_info(signal, &info, current); +} #endif diff --git a/arch/m68k/kernel/traps_mm.c b/arch/m68k/kernel/traps_mm.c deleted file mode 100644 index 4022bbc28878..000000000000 --- a/arch/m68k/kernel/traps_mm.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * linux/arch/m68k/kernel/traps.c - * - * Copyright (C) 1993, 1994 by Hamish Macdonald - * - * 68040 fixes by Michael Rausch - * 68040 fixes by Martin Apel - * 68040 fixes and writeback by Richard Zidlicky - * 68060 fixes by Roman Hodek - * 68060 fixes by Jesper Skov - * - * 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. - */ - -/* - * Sets up all exception vectors - */ - -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/user.h> -#include <linux/string.h> -#include <linux/linkage.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/kallsyms.h> - -#include <asm/setup.h> -#include <asm/fpu.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/traps.h> -#include <asm/pgalloc.h> -#include <asm/machdep.h> -#include <asm/siginfo.h> - -/* assembler routines */ -asmlinkage void system_call(void); -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void nmihandler(void); -#ifdef CONFIG_M68KFPU_EMU -asmlinkage void fpu_emu(void); -#endif - -e_vector vectors[256]; - -/* nmi handler for the Amiga */ -asm(".text\n" - __ALIGN_STR "\n" - "nmihandler: rte"); - -/* - * this must be called very early as the kernel might - * use some instruction that are emulated on the 060 - * and so we're prepared for early probe attempts (e.g. nf_init). - */ -void __init base_trap_init(void) -{ - if (MACH_IS_SUN3X) { - extern e_vector *sun3x_prom_vbr; - - __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); - } - - /* setup the exception vector table */ - __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); - - if (CPU_IS_060) { - /* set up ISP entry points */ - asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); - - vectors[VEC_UNIMPII] = unimp_vec; - } - - vectors[VEC_BUSERR] = buserr; - vectors[VEC_ILLEGAL] = trap; - vectors[VEC_SYS] = system_call; -} - -void __init trap_init (void) -{ - int i; - - for (i = VEC_SPUR; i <= VEC_INT7; i++) - vectors[i] = bad_inthandler; - - for (i = 0; i < VEC_USER; i++) - if (!vectors[i]) - vectors[i] = trap; - - for (i = VEC_USER; i < 256; i++) - vectors[i] = bad_inthandler; - -#ifdef CONFIG_M68KFPU_EMU - if (FPU_IS_EMU) - vectors[VEC_LINE11] = fpu_emu; -#endif - - if (CPU_IS_040 && !FPU_IS_EMU) { - /* set up FPSP entry points */ - asmlinkage void dz_vec(void) asm ("dz"); - asmlinkage void inex_vec(void) asm ("inex"); - asmlinkage void ovfl_vec(void) asm ("ovfl"); - asmlinkage void unfl_vec(void) asm ("unfl"); - asmlinkage void snan_vec(void) asm ("snan"); - asmlinkage void operr_vec(void) asm ("operr"); - asmlinkage void bsun_vec(void) asm ("bsun"); - asmlinkage void fline_vec(void) asm ("fline"); - asmlinkage void unsupp_vec(void) asm ("unsupp"); - - vectors[VEC_FPDIVZ] = dz_vec; - vectors[VEC_FPIR] = inex_vec; - vectors[VEC_FPOVER] = ovfl_vec; - vectors[VEC_FPUNDER] = unfl_vec; - vectors[VEC_FPNAN] = snan_vec; - vectors[VEC_FPOE] = operr_vec; - vectors[VEC_FPBRUC] = bsun_vec; - vectors[VEC_LINE11] = fline_vec; - vectors[VEC_FPUNSUP] = unsupp_vec; - } - - if (CPU_IS_060 && !FPU_IS_EMU) { - /* set up IFPSP entry points */ - asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); - asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); - asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); - asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); - asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); - asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); - asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); - asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); - asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); - - vectors[VEC_FPNAN] = snan_vec6; - vectors[VEC_FPOE] = operr_vec6; - vectors[VEC_FPOVER] = ovfl_vec6; - vectors[VEC_FPUNDER] = unfl_vec6; - vectors[VEC_FPDIVZ] = dz_vec6; - vectors[VEC_FPIR] = inex_vec6; - vectors[VEC_LINE11] = fline_vec6; - vectors[VEC_FPUNSUP] = unsupp_vec6; - vectors[VEC_UNIMPEA] = effadd_vec6; - } - - /* if running on an amiga, make the NMI interrupt do nothing */ - if (MACH_IS_AMIGA) { - vectors[VEC_INT7] = nmihandler; - } -} - - -static const char *vec_names[] = { - [VEC_RESETSP] = "RESET SP", - [VEC_RESETPC] = "RESET PC", - [VEC_BUSERR] = "BUS ERROR", - [VEC_ADDRERR] = "ADDRESS ERROR", - [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION", - [VEC_ZERODIV] = "ZERO DIVIDE", - [VEC_CHK] = "CHK", - [VEC_TRAP] = "TRAPcc", - [VEC_PRIV] = "PRIVILEGE VIOLATION", - [VEC_TRACE] = "TRACE", - [VEC_LINE10] = "LINE 1010", - [VEC_LINE11] = "LINE 1111", - [VEC_RESV12] = "UNASSIGNED RESERVED 12", - [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION", - [VEC_FORMAT] = "FORMAT ERROR", - [VEC_UNINT] = "UNINITIALIZED INTERRUPT", - [VEC_RESV16] = "UNASSIGNED RESERVED 16", - [VEC_RESV17] = "UNASSIGNED RESERVED 17", - [VEC_RESV18] = "UNASSIGNED RESERVED 18", - [VEC_RESV19] = "UNASSIGNED RESERVED 19", - [VEC_RESV20] = "UNASSIGNED RESERVED 20", - [VEC_RESV21] = "UNASSIGNED RESERVED 21", - [VEC_RESV22] = "UNASSIGNED RESERVED 22", - [VEC_RESV23] = "UNASSIGNED RESERVED 23", - [VEC_SPUR] = "SPURIOUS INTERRUPT", - [VEC_INT1] = "LEVEL 1 INT", - [VEC_INT2] = "LEVEL 2 INT", - [VEC_INT3] = "LEVEL 3 INT", - [VEC_INT4] = "LEVEL 4 INT", - [VEC_INT5] = "LEVEL 5 INT", - [VEC_INT6] = "LEVEL 6 INT", - [VEC_INT7] = "LEVEL 7 INT", - [VEC_SYS] = "SYSCALL", - [VEC_TRAP1] = "TRAP #1", - [VEC_TRAP2] = "TRAP #2", - [VEC_TRAP3] = "TRAP #3", - [VEC_TRAP4] = "TRAP #4", - [VEC_TRAP5] = "TRAP #5", - [VEC_TRAP6] = "TRAP #6", - [VEC_TRAP7] = "TRAP #7", - [VEC_TRAP8] = "TRAP #8", - [VEC_TRAP9] = "TRAP #9", - [VEC_TRAP10] = "TRAP #10", - [VEC_TRAP11] = "TRAP #11", - [VEC_TRAP12] = "TRAP #12", - [VEC_TRAP13] = "TRAP #13", - [VEC_TRAP14] = "TRAP #14", - [VEC_TRAP15] = "TRAP #15", - [VEC_FPBRUC] = "FPCP BSUN", - [VEC_FPIR] = "FPCP INEXACT", - [VEC_FPDIVZ] = "FPCP DIV BY 0", - [VEC_FPUNDER] = "FPCP UNDERFLOW", - [VEC_FPOE] = "FPCP OPERAND ERROR", - [VEC_FPOVER] = "FPCP OVERFLOW", - [VEC_FPNAN] = "FPCP SNAN", - [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION", - [VEC_MMUCFG] = "MMU CONFIGURATION ERROR", - [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR", - [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR", - [VEC_RESV59] = "UNASSIGNED RESERVED 59", - [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60", - [VEC_UNIMPII] = "UNASSIGNED RESERVED 61", - [VEC_RESV62] = "UNASSIGNED RESERVED 62", - [VEC_RESV63] = "UNASSIGNED RESERVED 63", -}; - -static const char *space_names[] = { - [0] = "Space 0", - [USER_DATA] = "User Data", - [USER_PROGRAM] = "User Program", -#ifndef CONFIG_SUN3 - [3] = "Space 3", -#else - [FC_CONTROL] = "Control", -#endif - [4] = "Space 4", - [SUPER_DATA] = "Super Data", - [SUPER_PROGRAM] = "Super Program", - [CPU_SPACE] = "CPU" -}; - -void die_if_kernel(char *,struct pt_regs *,int); -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); -int send_fault_sig(struct pt_regs *regs); - -asmlinkage void trap_c(struct frame *fp); - -#if defined (CONFIG_M68060) -static inline void access_error060 (struct frame *fp) -{ - unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ - -#ifdef DEBUG - printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); -#endif - - if (fslw & MMU060_BPE) { - /* branch prediction error -> clear branch cache */ - __asm__ __volatile__ ("movec %/cacr,%/d0\n\t" - "orl #0x00400000,%/d0\n\t" - "movec %/d0,%/cacr" - : : : "d0" ); - /* return if there's no other error */ - if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) - return; - } - - if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { - unsigned long errorcode; - unsigned long addr = fp->un.fmt4.effaddr; - - if (fslw & MMU060_MA) - addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; - - errorcode = 1; - if (fslw & MMU060_DESC_ERR) { - __flush_tlb040_one(addr); - errorcode = 0; - } - if (fslw & MMU060_W) - errorcode |= 2; -#ifdef DEBUG - printk("errorcode = %d\n", errorcode ); -#endif - do_page_fault(&fp->ptregs, addr, errorcode); - } else if (fslw & (MMU060_SEE)){ - /* Software Emulation Error. - * fault during mem_read/mem_write in ifpsp060/os.S - */ - send_fault_sig(&fp->ptregs); - } else if (!(fslw & (MMU060_RE|MMU060_WE)) || - send_fault_sig(&fp->ptregs) > 0) { - printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); - printk( "68060 access error, fslw=%lx\n", fslw ); - trap_c( fp ); - } -} -#endif /* CONFIG_M68060 */ - -#if defined (CONFIG_M68040) -static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) -{ - unsigned long mmusr; - mm_segment_t old_fs = get_fs(); - - set_fs(MAKE_MM_SEG(wbs)); - - if (iswrite) - asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); - else - asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); - - asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); - - set_fs(old_fs); - - return mmusr; -} - -static inline int do_040writeback1(unsigned short wbs, unsigned long wba, - unsigned long wbd) -{ - int res = 0; - mm_segment_t old_fs = get_fs(); - - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(MAKE_MM_SEG(wbs)); - - switch (wbs & WBSIZ_040) { - case BA_SIZE_BYTE: - res = put_user(wbd & 0xff, (char __user *)wba); - break; - case BA_SIZE_WORD: - res = put_user(wbd & 0xffff, (short __user *)wba); - break; - case BA_SIZE_LONG: - res = put_user(wbd, (int __user *)wba); - break; - } - - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(old_fs); - - -#ifdef DEBUG - printk("do_040writeback1, res=%d\n",res); -#endif - - return res; -} - -/* after an exception in a writeback the stack frame corresponding - * to that exception is discarded, set a few bits in the old frame - * to simulate what it should look like - */ -static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs) -{ - fp->un.fmt7.faddr = wba; - fp->un.fmt7.ssw = wbs & 0xff; - if (wba != current->thread.faddr) - fp->un.fmt7.ssw |= MA_040; -} - -static inline void do_040writebacks(struct frame *fp) -{ - int res = 0; -#if 0 - if (fp->un.fmt7.wb1s & WBV_040) - printk("access_error040: cannot handle 1st writeback. oops.\n"); -#endif - - if ((fp->un.fmt7.wb2s & WBV_040) && - !(fp->un.fmt7.wb2s & WBTT_040)) { - res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, - fp->un.fmt7.wb2d); - if (res) - fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); - else - fp->un.fmt7.wb2s = 0; - } - - /* do the 2nd wb only if the first one was successful (except for a kernel wb) */ - if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { - res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, - fp->un.fmt7.wb3d); - if (res) - { - fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); - - fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; - fp->un.fmt7.wb3s &= (~WBV_040); - fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; - fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; - } - else - fp->un.fmt7.wb3s = 0; - } - - if (res) - send_fault_sig(&fp->ptregs); -} - -/* - * called from sigreturn(), must ensure userspace code didn't - * manipulate exception frame to circumvent protection, then complete - * pending writebacks - * we just clear TM2 to turn it into a userspace access - */ -asmlinkage void berr_040cleanup(struct frame *fp) -{ - fp->un.fmt7.wb2s &= ~4; - fp->un.fmt7.wb3s &= ~4; - - do_040writebacks(fp); -} - -static inline void access_error040(struct frame *fp) -{ - unsigned short ssw = fp->un.fmt7.ssw; - unsigned long mmusr; - -#ifdef DEBUG - printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); - printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, - fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); - printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", - fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, - fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); -#endif - - if (ssw & ATC_040) { - unsigned long addr = fp->un.fmt7.faddr; - unsigned long errorcode; - - /* - * The MMU status has to be determined AFTER the address - * has been corrected if there was a misaligned access (MA). - */ - if (ssw & MA_040) - addr = (addr + 7) & -8; - - /* MMU error, get the MMUSR info for this access */ - mmusr = probe040(!(ssw & RW_040), addr, ssw); -#ifdef DEBUG - printk("mmusr = %lx\n", mmusr); -#endif - errorcode = 1; - if (!(mmusr & MMU_R_040)) { - /* clear the invalid atc entry */ - __flush_tlb040_one(addr); - errorcode = 0; - } - - /* despite what documentation seems to say, RMW - * accesses have always both the LK and RW bits set */ - if (!(ssw & RW_040) || (ssw & LK_040)) - errorcode |= 2; - - if (do_page_fault(&fp->ptregs, addr, errorcode)) { -#ifdef DEBUG - printk("do_page_fault() !=0\n"); -#endif - if (user_mode(&fp->ptregs)){ - /* delay writebacks after signal delivery */ -#ifdef DEBUG - printk(".. was usermode - return\n"); -#endif - return; - } - /* disable writeback into user space from kernel - * (if do_page_fault didn't fix the mapping, - * the writeback won't do good) - */ -disable_wb: -#ifdef DEBUG - printk(".. disabling wb2\n"); -#endif - if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) - fp->un.fmt7.wb2s &= ~WBV_040; - if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) - fp->un.fmt7.wb3s &= ~WBV_040; - } - } else { - /* In case of a bus error we either kill the process or expect - * the kernel to catch the fault, which then is also responsible - * for cleaning up the mess. - */ - current->thread.signo = SIGBUS; - current->thread.faddr = fp->un.fmt7.faddr; - if (send_fault_sig(&fp->ptregs) >= 0) - printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, - fp->un.fmt7.faddr); - goto disable_wb; - } - - do_040writebacks(fp); -} -#endif /* CONFIG_M68040 */ - -#if defined(CONFIG_SUN3) -#include <asm/sun3mmu.h> - -extern int mmu_emu_handle_fault (unsigned long, int, int); - -/* sun3 version of bus_error030 */ - -static inline void bus_error030 (struct frame *fp) -{ - unsigned char buserr_type = sun3_get_buserr (); - unsigned long addr, errorcode; - unsigned short ssw = fp->un.fmtb.ssw; - extern unsigned long _sun3_map_test_start, _sun3_map_test_end; - -#ifdef DEBUG - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - ssw & FC ? - fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 - : - fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); -#endif - - /* - * Check if this page should be demand-mapped. This needs to go before - * the testing for a bad kernel-space access (demand-mapping applies - * to kernel accesses too). - */ - - if ((ssw & DF) - && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) { - if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0)) - return; - } - - /* Check for kernel-space pagefault (BAD). */ - if (fp->ptregs.sr & PS_S) { - /* kernel fault must be a data fault to user space */ - if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { - // try checking the kernel mappings before surrender - if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1)) - return; - /* instruction fault or kernel data fault! */ - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - fp->ptregs.pc); - if (ssw & DF) { - /* was this fault incurred testing bus mappings? */ - if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && - (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { - send_fault_sig(&fp->ptregs); - return; - } - - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); - } - printk ("BAD KERNEL BUSERR\n"); - - die_if_kernel("Oops", &fp->ptregs,0); - force_sig(SIGKILL, current); - return; - } - } else { - /* user fault */ - if (!(ssw & (FC | FB)) && !(ssw & DF)) - /* not an instruction fault or data fault! BAD */ - panic ("USER BUSERR w/o instruction or data fault"); - } - - - /* First handle the data fault, if any. */ - if (ssw & DF) { - addr = fp->un.fmtb.daddr; - -// errorcode bit 0: 0 -> no page 1 -> protection fault -// errorcode bit 1: 0 -> read fault 1 -> write fault - -// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault -// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault - - if (buserr_type & SUN3_BUSERR_PROTERR) - errorcode = 0x01; - else if (buserr_type & SUN3_BUSERR_INVALID) - errorcode = 0x00; - else { -#ifdef DEBUG - printk ("*** unexpected busfault type=%#04x\n", buserr_type); - printk ("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc); -#endif - die_if_kernel ("Oops", &fp->ptregs, buserr_type); - force_sig (SIGBUS, current); - return; - } - -//todo: wtf is RM bit? --m - if (!(ssw & RW) || ssw & RM) - errorcode |= 0x02; - - /* Handle page fault. */ - do_page_fault (&fp->ptregs, addr, errorcode); - - /* Retry the data fault now. */ - return; - } - - /* Now handle the instruction fault. */ - - /* Get the fault address. */ - if (fp->ptregs.format == 0xA) - addr = fp->ptregs.pc + 4; - else - addr = fp->un.fmtb.baddr; - if (ssw & FC) - addr -= 2; - - if (buserr_type & SUN3_BUSERR_INVALID) { - if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) - do_page_fault (&fp->ptregs, addr, 0); - } else { -#ifdef DEBUG - printk ("protection fault on insn access (segv).\n"); -#endif - force_sig (SIGSEGV, current); - } -} -#else -#if defined(CPU_M68020_OR_M68030) -static inline void bus_error030 (struct frame *fp) -{ - volatile unsigned short temp; - unsigned short mmusr; - unsigned long addr, errorcode; - unsigned short ssw = fp->un.fmtb.ssw; -#ifdef DEBUG - unsigned long desc; - - printk ("pid = %x ", current->pid); - printk ("SSW=%#06x ", ssw); - - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - ssw & FC ? - fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 - : - fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); -#endif - - /* ++andreas: If a data fault and an instruction fault happen - at the same time map in both pages. */ - - /* First handle the data fault, if any. */ - if (ssw & DF) { - addr = fp->un.fmtb.daddr; - -#ifdef DEBUG - asm volatile ("ptestr %3,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr), "d" (ssw)); -#else - asm volatile ("ptestr %2,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr), "d" (ssw)); -#endif - mmusr = temp; - -#ifdef DEBUG - printk("mmusr is %#x for addr %#lx in task %p\n", - mmusr, addr, current); - printk("descriptor address is %#lx, contents %#lx\n", - __va(desc), *(unsigned long *)__va(desc)); -#endif - - errorcode = (mmusr & MMU_I) ? 0 : 1; - if (!(ssw & RW) || (ssw & RM)) - errorcode |= 2; - - if (mmusr & (MMU_I | MMU_WP)) { - if (ssw & 4) { - printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); - goto buserr; - } - /* Don't try to do anything further if an exception was - handled. */ - if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) - return; - } else if (!(mmusr & MMU_I)) { - /* probably a 020 cas fault */ - if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) - printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); - } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { - printk("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc); - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } else { -#if 0 - static volatile long tlong; -#endif - - printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc, ssw); - asm volatile ("ptestr #1,%1@,#0\n\t" - "pmove %%psr,%0@" - : /* no outputs */ - : "a" (&temp), "a" (addr)); - mmusr = temp; - - printk ("level 0 mmusr is %#x\n", mmusr); -#if 0 - asm volatile ("pmove %%tt0,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk("tt0 is %#lx, ", tlong); - asm volatile ("pmove %%tt1,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk("tt1 is %#lx\n", tlong); -#endif -#ifdef DEBUG - printk("Unknown SIGSEGV - 1\n"); -#endif - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } - - /* setup an ATC entry for the access about to be retried */ - if (!(ssw & RW) || (ssw & RM)) - asm volatile ("ploadw %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - else - asm volatile ("ploadr %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - } - - /* Now handle the instruction fault. */ - - if (!(ssw & (FC|FB))) - return; - - if (fp->ptregs.sr & PS_S) { - printk("Instruction fault at %#010lx\n", - fp->ptregs.pc); - buserr: - printk ("BAD KERNEL BUSERR\n"); - die_if_kernel("Oops",&fp->ptregs,0); - force_sig(SIGKILL, current); - return; - } - - /* get the fault address */ - if (fp->ptregs.format == 10) - addr = fp->ptregs.pc + 4; - else - addr = fp->un.fmtb.baddr; - if (ssw & FC) - addr -= 2; - - if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0) - /* Insn fault on same page as data fault. But we - should still create the ATC entry. */ - goto create_atc_entry; - -#ifdef DEBUG - asm volatile ("ptestr #1,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr)); -#else - asm volatile ("ptestr #1,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr)); -#endif - mmusr = temp; - -#ifdef DEBUG - printk ("mmusr is %#x for addr %#lx in task %p\n", - mmusr, addr, current); - printk ("descriptor address is %#lx, contents %#lx\n", - __va(desc), *(unsigned long *)__va(desc)); -#endif - - if (mmusr & MMU_I) - do_page_fault (&fp->ptregs, addr, 0); - else if (mmusr & (MMU_B|MMU_L|MMU_S)) { - printk ("invalid insn access at %#lx from pc %#lx\n", - addr, fp->ptregs.pc); -#ifdef DEBUG - printk("Unknown SIGSEGV - 2\n"); -#endif - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } - -create_atc_entry: - /* setup an ATC entry for the access about to be retried */ - asm volatile ("ploadr #2,%0@" : /* no outputs */ - : "a" (addr)); -} -#endif /* CPU_M68020_OR_M68030 */ -#endif /* !CONFIG_SUN3 */ - -asmlinkage void buserr_c(struct frame *fp) -{ - /* Only set esp0 if coming from user mode */ - if (user_mode(&fp->ptregs)) - current->thread.esp0 = (unsigned long) fp; - -#ifdef DEBUG - printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); -#endif - - switch (fp->ptregs.format) { -#if defined (CONFIG_M68060) - case 4: /* 68060 access error */ - access_error060 (fp); - break; -#endif -#if defined (CONFIG_M68040) - case 0x7: /* 68040 access error */ - access_error040 (fp); - break; -#endif -#if defined (CPU_M68020_OR_M68030) - case 0xa: - case 0xb: - bus_error030 (fp); - break; -#endif - default: - die_if_kernel("bad frame format",&fp->ptregs,0); -#ifdef DEBUG - printk("Unknown SIGSEGV - 4\n"); -#endif - force_sig(SIGSEGV, current); - } -} - - -static int kstack_depth_to_print = 48; - -void show_trace(unsigned long *stack) -{ - unsigned long *endstack; - unsigned long addr; - int i; - - printk("Call Trace:"); - addr = (unsigned long)stack + THREAD_SIZE - 1; - endstack = (unsigned long *)(addr & -THREAD_SIZE); - i = 0; - while (stack + 1 <= endstack) { - addr = *stack++; - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ - if (__kernel_text_address(addr)) { -#ifndef CONFIG_KALLSYMS - if (i % 5 == 0) - printk("\n "); -#endif - printk(" [<%08lx>] %pS\n", addr, (void *)addr); - i++; - } - } - printk("\n"); -} - -void show_registers(struct pt_regs *regs) -{ - struct frame *fp = (struct frame *)regs; - mm_segment_t old_fs = get_fs(); - u16 c, *cp; - unsigned long addr; - int i; - - print_modules(); - printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); - printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); - printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - regs->d0, regs->d1, regs->d2, regs->d3); - printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - regs->d4, regs->d5, regs->a0, regs->a1); - - printk("Process %s (pid: %d, task=%p)\n", - current->comm, task_pid_nr(current), current); - addr = (unsigned long)&fp->un; - printk("Frame format=%X ", regs->format); - switch (regs->format) { - case 0x2: - printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); - addr += sizeof(fp->un.fmt2); - break; - case 0x3: - printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); - addr += sizeof(fp->un.fmt3); - break; - case 0x4: - printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" - : "eff addr=%08lx pc=%08lx\n"), - fp->un.fmt4.effaddr, fp->un.fmt4.pc); - addr += sizeof(fp->un.fmt4); - break; - case 0x7: - printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", - fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); - printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); - printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); - printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); - printk("push data: %08lx %08lx %08lx %08lx\n", - fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, - fp->un.fmt7.pd3); - addr += sizeof(fp->un.fmt7); - break; - case 0x9: - printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); - addr += sizeof(fp->un.fmt9); - break; - case 0xa: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, - fp->un.fmta.daddr, fp->un.fmta.dobuf); - addr += sizeof(fp->un.fmta); - break; - case 0xb: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, - fp->un.fmtb.daddr, fp->un.fmtb.dobuf); - printk("baddr=%08lx dibuf=%08lx ver=%x\n", - fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); - addr += sizeof(fp->un.fmtb); - break; - default: - printk("\n"); - } - show_stack(NULL, (unsigned long *)addr); - - printk("Code:"); - set_fs(KERNEL_DS); - cp = (u16 *)regs->pc; - for (i = -8; i < 16; i++) { - if (get_user(c, cp + i) && i >= 0) { - printk(" Bad PC value."); - break; - } - printk(i ? " %04x" : " <%04x>", c); - } - set_fs(old_fs); - printk ("\n"); -} - -void show_stack(struct task_struct *task, unsigned long *stack) -{ - unsigned long *p; - unsigned long *endstack; - int i; - - if (!stack) { - if (task) - stack = (unsigned long *)task->thread.esp0; - else - stack = (unsigned long *)&stack; - } - endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); - - printk("Stack from %08lx:", (unsigned long)stack); - p = stack; - for (i = 0; i < kstack_depth_to_print; i++) { - if (p + 1 > endstack) - break; - if (i % 8 == 0) - printk("\n "); - printk(" %08lx", *p++); - } - printk("\n"); - show_trace(stack); -} - -/* - * The architecture-independent backtrace generator - */ -void dump_stack(void) -{ - unsigned long stack; - - show_trace(&stack); -} - -EXPORT_SYMBOL(dump_stack); - -void bad_super_trap (struct frame *fp) -{ - console_verbose(); - if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names)) - printk ("*** %s *** FORMAT=%X\n", - vec_names[(fp->ptregs.vector) >> 2], - fp->ptregs.format); - else - printk ("*** Exception %d *** FORMAT=%X\n", - (fp->ptregs.vector) >> 2, - fp->ptregs.format); - if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) { - unsigned short ssw = fp->un.fmtb.ssw; - - printk ("SSW=%#06x ", ssw); - - if (ssw & RC) - printk ("Pipe stage C instruction fault at %#010lx\n", - (fp->ptregs.format) == 0xA ? - fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); - if (ssw & RB) - printk ("Pipe stage B instruction fault at %#010lx\n", - (fp->ptregs.format) == 0xA ? - fp->ptregs.pc + 4 : fp->un.fmtb.baddr); - if (ssw & DF) - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, space_names[ssw & DFC], - fp->ptregs.pc); - } - printk ("Current process id is %d\n", task_pid_nr(current)); - die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); -} - -asmlinkage void trap_c(struct frame *fp) -{ - int sig; - siginfo_t info; - - if (fp->ptregs.sr & PS_S) { - if (fp->ptregs.vector == VEC_TRACE << 2) { - /* traced a trapping instruction on a 68020/30, - * real exception will be executed afterwards. - */ - } else if (!handle_kernel_fault(&fp->ptregs)) - bad_super_trap(fp); - return; - } - - /* send the appropriate signal to the user program */ - switch ((fp->ptregs.vector) >> 2) { - case VEC_ADDRERR: - info.si_code = BUS_ADRALN; - sig = SIGBUS; - break; - case VEC_ILLEGAL: - case VEC_LINE10: - case VEC_LINE11: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - case VEC_PRIV: - info.si_code = ILL_PRVOPC; - sig = SIGILL; - break; - case VEC_COPROC: - info.si_code = ILL_COPROC; - sig = SIGILL; - break; - case VEC_TRAP1: - case VEC_TRAP2: - case VEC_TRAP3: - case VEC_TRAP4: - case VEC_TRAP5: - case VEC_TRAP6: - case VEC_TRAP7: - case VEC_TRAP8: - case VEC_TRAP9: - case VEC_TRAP10: - case VEC_TRAP11: - case VEC_TRAP12: - case VEC_TRAP13: - case VEC_TRAP14: - info.si_code = ILL_ILLTRP; - sig = SIGILL; - break; - case VEC_FPBRUC: - case VEC_FPOE: - case VEC_FPNAN: - info.si_code = FPE_FLTINV; - sig = SIGFPE; - break; - case VEC_FPIR: - info.si_code = FPE_FLTRES; - sig = SIGFPE; - break; - case VEC_FPDIVZ: - info.si_code = FPE_FLTDIV; - sig = SIGFPE; - break; - case VEC_FPUNDER: - info.si_code = FPE_FLTUND; - sig = SIGFPE; - break; - case VEC_FPOVER: - info.si_code = FPE_FLTOVF; - sig = SIGFPE; - break; - case VEC_ZERODIV: - info.si_code = FPE_INTDIV; - sig = SIGFPE; - break; - case VEC_CHK: - case VEC_TRAP: - info.si_code = FPE_INTOVF; - sig = SIGFPE; - break; - case VEC_TRACE: /* ptrace single step */ - info.si_code = TRAP_TRACE; - sig = SIGTRAP; - break; - case VEC_TRAP15: /* breakpoint */ - info.si_code = TRAP_BRKPT; - sig = SIGTRAP; - break; - default: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - } - info.si_signo = sig; - info.si_errno = 0; - switch (fp->ptregs.format) { - default: - info.si_addr = (void *) fp->ptregs.pc; - break; - case 2: - info.si_addr = (void *) fp->un.fmt2.iaddr; - break; - case 7: - info.si_addr = (void *) fp->un.fmt7.effaddr; - break; - case 9: - info.si_addr = (void *) fp->un.fmt9.iaddr; - break; - case 10: - info.si_addr = (void *) fp->un.fmta.daddr; - break; - case 11: - info.si_addr = (void *) fp->un.fmtb.daddr; - break; - } - force_sig_info (sig, &info, current); -} - -void die_if_kernel (char *str, struct pt_regs *fp, int nr) -{ - if (!(fp->sr & PS_S)) - return; - - console_verbose(); - printk("%s: %08x\n",str,nr); - show_registers(fp); - add_taint(TAINT_DIE); - do_exit(SIGSEGV); -} - -/* - * This function is called if an error occur while accessing - * user-space from the fpsp040 code. - */ -asmlinkage void fpsp040_die(void) -{ - do_exit(SIGSEGV); -} - -#ifdef CONFIG_M68KFPU_EMU -asmlinkage void fpemu_signal(int signal, int code, void *addr) -{ - siginfo_t info; - - info.si_signo = signal; - info.si_errno = 0; - info.si_code = code; - info.si_addr = addr; - force_sig_info(signal, &info, current); -} -#endif diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c deleted file mode 100644 index e67b8c806959..000000000000 --- a/arch/m68k/kernel/traps_no.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * linux/arch/m68knommu/kernel/traps.c - * - * Copyright (C) 1993, 1994 by Hamish Macdonald - * - * 68040 fixes by Michael Rausch - * 68040 fixes by Martin Apel - * 68060 fixes by Roman Hodek - * 68060 fixes by Jesper Skov - * - * 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. - */ - -/* - * Sets up all exception vectors - */ -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/user.h> -#include <linux/string.h> -#include <linux/linkage.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/kallsyms.h> - -#include <asm/setup.h> -#include <asm/fpu.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/traps.h> -#include <asm/pgtable.h> -#include <asm/machdep.h> -#include <asm/siginfo.h> - -static char const * const vec_names[] = { - "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", - "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", - "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", - "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION", - "FORMAT ERROR", "UNINITIALIZED INTERRUPT", - "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17", - "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19", - "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21", - "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23", - "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT", - "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT", - "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3", - "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7", - "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11", - "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15", - "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW", - "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN", - "FPCP UNSUPPORTED OPERATION", - "MMU CONFIGURATION ERROR" -}; - -void die_if_kernel(char *str, struct pt_regs *fp, int nr) -{ - if (!(fp->sr & PS_S)) - return; - - console_verbose(); - printk(KERN_EMERG "%s: %08x\n",str,nr); - printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n", - fp->pc, fp->sr, fp, fp->a2); - printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - fp->d0, fp->d1, fp->d2, fp->d3); - printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - fp->d4, fp->d5, fp->a0, fp->a1); - - printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, PAGE_SIZE+(unsigned long)current); - show_stack(NULL, (unsigned long *)(fp + 1)); - add_taint(TAINT_DIE); - do_exit(SIGSEGV); -} - -asmlinkage void buserr_c(struct frame *fp) -{ - /* Only set esp0 if coming from user mode */ - if (user_mode(&fp->ptregs)) - current->thread.esp0 = (unsigned long) fp; - -#if defined(DEBUG) - printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format); -#endif - - die_if_kernel("bad frame format",&fp->ptregs,0); -#if defined(DEBUG) - printk(KERN_DEBUG "Unknown SIGSEGV - 4\n"); -#endif - force_sig(SIGSEGV, current); -} - -static void print_this_address(unsigned long addr, int i) -{ -#ifdef CONFIG_KALLSYMS - printk(KERN_EMERG " [%08lx] ", addr); - print_symbol(KERN_CONT "%s\n", addr); -#else - if (i % 5) - printk(KERN_CONT " [%08lx] ", addr); - else - printk(KERN_EMERG " [%08lx] ", addr); - i++; -#endif -} - -int kstack_depth_to_print = 48; - -static void __show_stack(struct task_struct *task, unsigned long *stack) -{ - unsigned long *endstack, addr; -#ifdef CONFIG_FRAME_POINTER - unsigned long *last_stack; -#endif - int i; - - if (!stack) - stack = (unsigned long *)task->thread.ksp; - - addr = (unsigned long) stack; - endstack = (unsigned long *) PAGE_ALIGN(addr); - - printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); - for (i = 0; i < kstack_depth_to_print; i++) { - if (stack + 1 + i > endstack) - break; - if (i % 8 == 0) - printk(KERN_EMERG " "); - printk(KERN_CONT " %08lx", *(stack + i)); - } - printk("\n"); - i = 0; - -#ifdef CONFIG_FRAME_POINTER - printk(KERN_EMERG "Call Trace:\n"); - - last_stack = stack - 1; - while (stack <= endstack && stack > last_stack) { - - addr = *(stack + 1); - print_this_address(addr, i); - i++; - - last_stack = stack; - stack = (unsigned long *)*stack; - } - printk("\n"); -#else - printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n"); - while (stack <= endstack) { - addr = *stack++; - /* - * If the address is either in the text segment of the kernel, - * or in a region which is occupied by a module then it *may* - * be the address of a calling routine; if so, print it so that - * someone tracing down the cause of the crash will be able to - * figure out the call path that was taken. - */ - if (__kernel_text_address(addr)) { - print_this_address(addr, i); - i++; - } - } - printk(KERN_CONT "\n"); -#endif -} - -void bad_super_trap(struct frame *fp) -{ - int vector = (fp->ptregs.vector >> 2) & 0xff; - - console_verbose(); - if (vector < ARRAY_SIZE(vec_names)) - printk (KERN_WARNING "*** %s *** FORMAT=%X\n", - vec_names[vector], - fp->ptregs.format); - else - printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n", - vector, - fp->ptregs.format); - printk (KERN_WARNING "Current process id is %d\n", current->pid); - die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); -} - -asmlinkage void trap_c(struct frame *fp) -{ - int sig; - int vector = (fp->ptregs.vector >> 2) & 0xff; - siginfo_t info; - - if (fp->ptregs.sr & PS_S) { - if (vector == VEC_TRACE) { - /* traced a trapping instruction */ - } else - bad_super_trap(fp); - return; - } - - /* send the appropriate signal to the user program */ - switch (vector) { - case VEC_ADDRERR: - info.si_code = BUS_ADRALN; - sig = SIGBUS; - break; - case VEC_ILLEGAL: - case VEC_LINE10: - case VEC_LINE11: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - case VEC_PRIV: - info.si_code = ILL_PRVOPC; - sig = SIGILL; - break; - case VEC_COPROC: - info.si_code = ILL_COPROC; - sig = SIGILL; - break; - case VEC_TRAP1: /* gdbserver breakpoint */ - fp->ptregs.pc -= 2; - info.si_code = TRAP_TRACE; - sig = SIGTRAP; - break; - case VEC_TRAP2: - case VEC_TRAP3: - case VEC_TRAP4: - case VEC_TRAP5: - case VEC_TRAP6: - case VEC_TRAP7: - case VEC_TRAP8: - case VEC_TRAP9: - case VEC_TRAP10: - case VEC_TRAP11: - case VEC_TRAP12: - case VEC_TRAP13: - case VEC_TRAP14: - info.si_code = ILL_ILLTRP; - sig = SIGILL; - break; - case VEC_FPBRUC: - case VEC_FPOE: - case VEC_FPNAN: - info.si_code = FPE_FLTINV; - sig = SIGFPE; - break; - case VEC_FPIR: - info.si_code = FPE_FLTRES; - sig = SIGFPE; - break; - case VEC_FPDIVZ: - info.si_code = FPE_FLTDIV; - sig = SIGFPE; - break; - case VEC_FPUNDER: - info.si_code = FPE_FLTUND; - sig = SIGFPE; - break; - case VEC_FPOVER: - info.si_code = FPE_FLTOVF; - sig = SIGFPE; - break; - case VEC_ZERODIV: - info.si_code = FPE_INTDIV; - sig = SIGFPE; - break; - case VEC_CHK: - case VEC_TRAP: - info.si_code = FPE_INTOVF; - sig = SIGFPE; - break; - case VEC_TRACE: /* ptrace single step */ - info.si_code = TRAP_TRACE; - sig = SIGTRAP; - break; - case VEC_TRAP15: /* breakpoint */ - info.si_code = TRAP_BRKPT; - sig = SIGTRAP; - break; - default: - info.si_code = ILL_ILLOPC; - sig = SIGILL; - break; - } - info.si_signo = sig; - info.si_errno = 0; - switch (fp->ptregs.format) { - default: - info.si_addr = (void *) fp->ptregs.pc; - break; - case 2: - info.si_addr = (void *) fp->un.fmt2.iaddr; - break; - case 7: - info.si_addr = (void *) fp->un.fmt7.effaddr; - break; - case 9: - info.si_addr = (void *) fp->un.fmt9.iaddr; - break; - case 10: - info.si_addr = (void *) fp->un.fmta.daddr; - break; - case 11: - info.si_addr = (void *) fp->un.fmtb.daddr; - break; - } - force_sig_info (sig, &info, current); -} - -asmlinkage void set_esp0(unsigned long ssp) -{ - current->thread.esp0 = ssp; -} - -/* - * The architecture-independent backtrace generator - */ -void dump_stack(void) -{ - /* - * We need frame pointers for this little trick, which works as follows: - * - * +------------+ 0x00 - * | Next SP | -> 0x0c - * +------------+ 0x04 - * | Caller | - * +------------+ 0x08 - * | Local vars | -> our stack var - * +------------+ 0x0c - * | Next SP | -> 0x18, that is what we pass to show_stack() - * +------------+ 0x10 - * | Caller | - * +------------+ 0x14 - * | Local vars | - * +------------+ 0x18 - * | ... | - * +------------+ - */ - - unsigned long *stack; - - stack = (unsigned long *)&stack; - stack++; - __show_stack(current, stack); -} -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *task, unsigned long *stack) -{ - if (!stack && !task) - dump_stack(); - else - __show_stack(task, stack); -} diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c new file mode 100644 index 000000000000..147b03fbc71e --- /dev/null +++ b/arch/m68k/kernel/vectors.c @@ -0,0 +1,145 @@ +/* + * vectors.c + * + * Copyright (C) 1993, 1994 by Hamish Macdonald + * + * 68040 fixes by Michael Rausch + * 68040 fixes by Martin Apel + * 68040 fixes and writeback by Richard Zidlicky + * 68060 fixes by Roman Hodek + * 68060 fixes by Jesper Skov + * + * 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. + */ + +/* + * Sets up all exception vectors + */ +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/kallsyms.h> + +#include <asm/setup.h> +#include <asm/fpu.h> +#include <asm/system.h> +#include <asm/traps.h> + +/* assembler routines */ +asmlinkage void system_call(void); +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void nmihandler(void); +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpu_emu(void); +#endif + +e_vector vectors[256]; + +/* nmi handler for the Amiga */ +asm(".text\n" + __ALIGN_STR "\n" + "nmihandler: rte"); + +/* + * this must be called very early as the kernel might + * use some instruction that are emulated on the 060 + * and so we're prepared for early probe attempts (e.g. nf_init). + */ +void __init base_trap_init(void) +{ + if (MACH_IS_SUN3X) { + extern e_vector *sun3x_prom_vbr; + + __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); + } + + /* setup the exception vector table */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + + if (CPU_IS_060) { + /* set up ISP entry points */ + asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); + + vectors[VEC_UNIMPII] = unimp_vec; + } + + vectors[VEC_BUSERR] = buserr; + vectors[VEC_ILLEGAL] = trap; + vectors[VEC_SYS] = system_call; +} + +void __init trap_init (void) +{ + int i; + + for (i = VEC_SPUR; i <= VEC_INT7; i++) + vectors[i] = bad_inthandler; + + for (i = 0; i < VEC_USER; i++) + if (!vectors[i]) + vectors[i] = trap; + + for (i = VEC_USER; i < 256; i++) + vectors[i] = bad_inthandler; + +#ifdef CONFIG_M68KFPU_EMU + if (FPU_IS_EMU) + vectors[VEC_LINE11] = fpu_emu; +#endif + + if (CPU_IS_040 && !FPU_IS_EMU) { + /* set up FPSP entry points */ + asmlinkage void dz_vec(void) asm ("dz"); + asmlinkage void inex_vec(void) asm ("inex"); + asmlinkage void ovfl_vec(void) asm ("ovfl"); + asmlinkage void unfl_vec(void) asm ("unfl"); + asmlinkage void snan_vec(void) asm ("snan"); + asmlinkage void operr_vec(void) asm ("operr"); + asmlinkage void bsun_vec(void) asm ("bsun"); + asmlinkage void fline_vec(void) asm ("fline"); + asmlinkage void unsupp_vec(void) asm ("unsupp"); + + vectors[VEC_FPDIVZ] = dz_vec; + vectors[VEC_FPIR] = inex_vec; + vectors[VEC_FPOVER] = ovfl_vec; + vectors[VEC_FPUNDER] = unfl_vec; + vectors[VEC_FPNAN] = snan_vec; + vectors[VEC_FPOE] = operr_vec; + vectors[VEC_FPBRUC] = bsun_vec; + vectors[VEC_LINE11] = fline_vec; + vectors[VEC_FPUNSUP] = unsupp_vec; + } + + if (CPU_IS_060 && !FPU_IS_EMU) { + /* set up IFPSP entry points */ + asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan"); + asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr"); + asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl"); + asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl"); + asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz"); + asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex"); + asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline"); + asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp"); + asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd"); + + vectors[VEC_FPNAN] = snan_vec6; + vectors[VEC_FPOE] = operr_vec6; + vectors[VEC_FPOVER] = ovfl_vec6; + vectors[VEC_FPUNDER] = unfl_vec6; + vectors[VEC_FPDIVZ] = dz_vec6; + vectors[VEC_FPIR] = inex_vec6; + vectors[VEC_LINE11] = fline_vec6; + vectors[VEC_FPUNSUP] = unsupp_vec6; + vectors[VEC_UNIMPEA] = effadd_vec6; + } + + /* if running on an amiga, make the NMI interrupt do nothing */ + if (MACH_IS_AMIGA) { + vectors[VEC_INT7] = nmihandler; + } +} + diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux.lds_no.S index 7dc4087a9545..4e2389340837 100644 --- a/arch/m68k/kernel/vmlinux.lds_no.S +++ b/arch/m68k/kernel/vmlinux.lds_no.S @@ -77,7 +77,6 @@ SECTIONS { *(.rodata) *(.rodata.*) *(__vermagic) /* Kernel version magic */ - *(__markers_strings) *(.rodata1) *(.rodata.str1.1) diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c index 064889316974..10ca051d56b8 100644 --- a/arch/m68k/lib/memcpy.c +++ b/arch/m68k/lib/memcpy.c @@ -22,6 +22,15 @@ void *memcpy(void *to, const void *from, size_t n) from = cfrom; n--; } +#if defined(CONFIG_M68000) + if ((long)from & 1) { + char *cto = to; + const char *cfrom = from; + for (; n; n--) + *cto++ = *cfrom++; + return xto; + } +#endif if (n > 2 && (long)to & 2) { short *sto = to; const short *sfrom = from; diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index 900d899f3323..f92190c159b4 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -370,7 +370,7 @@ int mac_irq_pending(unsigned int irq) break; case 4: if (psc_present) - psc_irq_pending(irq); + return psc_irq_pending(irq); break; } return 0; diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index e023fc6b37e5..eb915551de69 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -304,35 +304,41 @@ static void via_write_pram(int offset, __u8 data) static long via_read_time(void) { union { - __u8 cdata[4]; - long idata; + __u8 cdata[4]; + long idata; } result, last_result; - int ct; + int count = 1; + + via_pram_command(0x81, &last_result.cdata[3]); + via_pram_command(0x85, &last_result.cdata[2]); + via_pram_command(0x89, &last_result.cdata[1]); + via_pram_command(0x8D, &last_result.cdata[0]); /* * The NetBSD guys say to loop until you get the same reading * twice in a row. */ - ct = 0; - do { - if (++ct > 10) { - printk("via_read_time: couldn't get valid time, " - "last read = 0x%08lx and 0x%08lx\n", - last_result.idata, result.idata); - break; - } - - last_result.idata = result.idata; - result.idata = 0; - + while (1) { via_pram_command(0x81, &result.cdata[3]); via_pram_command(0x85, &result.cdata[2]); via_pram_command(0x89, &result.cdata[1]); via_pram_command(0x8D, &result.cdata[0]); - } while (result.idata != last_result.idata); - return result.idata - RTC_OFFSET; + if (result.idata == last_result.idata) + return result.idata - RTC_OFFSET; + + if (++count > 10) + break; + + last_result.idata = result.idata; + } + + pr_err("via_read_time: failed to read a stable value; " + "got 0x%08lx then 0x%08lx\n", + last_result.idata, result.idata); + + return 0; } /* diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c index 50cd12cf28d9..1e33d39ca9a0 100644 --- a/arch/m68k/mm/init_no.c +++ b/arch/m68k/mm/init_no.c @@ -32,6 +32,7 @@ #include <linux/gfp.h> #include <asm/setup.h> +#include <asm/sections.h> #include <asm/segment.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -44,9 +45,6 @@ */ void *empty_zero_page; -extern unsigned long memory_start; -extern unsigned long memory_end; - /* * paging_init() continues the virtual memory environment setup which * was begun by the code in arch/head.S. @@ -78,8 +76,6 @@ void __init mem_init(void) { int codek = 0, datak = 0, initk = 0; unsigned long tmp; - extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end; - extern unsigned int _ramend, _rambase; unsigned long len = _ramend - _rambase; unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */ unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */ @@ -95,9 +91,9 @@ void __init mem_init(void) /* this will put all memory onto the freelists */ totalram_pages = free_all_bootmem(); - codek = (&_etext - &_stext) >> 10; - datak = (&_ebss - &_sdata) >> 10; - initk = (&__init_begin - &__init_end) >> 10; + codek = (_etext - _stext) >> 10; + datak = (_ebss - _sdata) >> 10; + initk = (__init_begin - __init_end) >> 10; tmp = nr_free_pages() << PAGE_SHIFT; printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n", @@ -129,22 +125,21 @@ void free_initmem(void) { #ifdef CONFIG_RAMKERNEL unsigned long addr; - extern char __init_begin, __init_end; /* * The following code should be cool even if these sections * are not page aligned. */ - addr = PAGE_ALIGN((unsigned long)(&__init_begin)); + addr = PAGE_ALIGN((unsigned long) __init_begin); /* next to check that the page we free is not a partial page */ - for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { + for (; addr + PAGE_SIZE < ((unsigned long) __init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n", - (addr - PAGE_ALIGN((long) &__init_begin)) >> 10, - (int)(PAGE_ALIGN((unsigned long)(&__init_begin))), + (addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10, + (int)(PAGE_ALIGN((unsigned long) __init_begin)), (int)(addr - PAGE_SIZE)); #endif } diff --git a/arch/m68k/platform/520x/config.c b/arch/m68k/platform/520x/config.c index 621238f1a219..8a98683f1b15 100644 --- a/arch/m68k/platform/520x/config.c +++ b/arch/m68k/platform/520x/config.c @@ -91,9 +91,9 @@ static struct resource m520x_qspi_resources[] = { }, }; -#define MCFQSPI_CS0 62 -#define MCFQSPI_CS1 63 -#define MCFQSPI_CS2 44 +#define MCFQSPI_CS0 46 +#define MCFQSPI_CS1 47 +#define MCFQSPI_CS2 27 static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control) { diff --git a/arch/m68k/platform/520x/gpio.c b/arch/m68k/platform/520x/gpio.c index d757328563d1..9bcc3e4b60c5 100644 --- a/arch/m68k/platform/520x/gpio.c +++ b/arch/m68k/platform/520x/gpio.c @@ -38,42 +38,6 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { }, { .gpio_chip = { - .label = "BUSCTL", - .request = mcf_gpio_request, - .free = mcf_gpio_free, - .direction_input = mcf_gpio_direction_input, - .direction_output = mcf_gpio_direction_output, - .get = mcf_gpio_get_value, - .set = mcf_gpio_set_value_fast, - .base = 8, - .ngpio = 4, - }, - .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL, - .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL, - .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL, - .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL, - .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL, - }, - { - .gpio_chip = { - .label = "BE", - .request = mcf_gpio_request, - .free = mcf_gpio_free, - .direction_input = mcf_gpio_direction_input, - .direction_output = mcf_gpio_direction_output, - .get = mcf_gpio_get_value, - .set = mcf_gpio_set_value_fast, - .base = 16, - .ngpio = 4, - }, - .pddr = (void __iomem *) MCFGPIO_PDDR_BE, - .podr = (void __iomem *) MCFGPIO_PODR_BE, - .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BE, - .setr = (void __iomem *) MCFGPIO_PPDSDR_BE, - .clrr = (void __iomem *) MCFGPIO_PCLRR_BE, - }, - { - .gpio_chip = { .label = "CS", .request = mcf_gpio_request, .free = mcf_gpio_free, @@ -81,7 +45,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 25, + .base = 9, .ngpio = 3, }, .pddr = (void __iomem *) MCFGPIO_PDDR_CS, @@ -99,7 +63,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 32, + .base = 16, .ngpio = 4, }, .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C, @@ -117,7 +81,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 40, + .base = 24, .ngpio = 4, }, .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI, @@ -135,7 +99,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 48, + .base = 32, .ngpio = 4, }, .pddr = (void __iomem *) MCFGPIO_PDDR_TIMER, @@ -153,7 +117,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 56, + .base = 40, .ngpio = 8, }, .pddr = (void __iomem *) MCFGPIO_PDDR_UART, @@ -171,7 +135,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 64, + .base = 48, .ngpio = 8, }, .pddr = (void __iomem *) MCFGPIO_PDDR_FECH, @@ -189,7 +153,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = { .direction_output = mcf_gpio_direction_output, .get = mcf_gpio_get_value, .set = mcf_gpio_set_value_fast, - .base = 72, + .base = 56, .ngpio = 8, }, .pddr = (void __iomem *) MCFGPIO_PDDR_FECL, diff --git a/arch/m68k/platform/68328/Makefile b/arch/m68k/platform/68328/Makefile index 5e5435552d56..e4dfd8fde068 100644 --- a/arch/m68k/platform/68328/Makefile +++ b/arch/m68k/platform/68328/Makefile @@ -2,7 +2,10 @@ # Makefile for arch/m68knommu/platform/68328. # -head-y = head-$(MODEL).o +model-y := ram +model-$(CONFIG_ROMKERNEL) := rom + +head-y = head-$(model-y).o head-$(CONFIG_PILOT) = head-pilot.o head-$(CONFIG_DRAGEN2) = head-de2.o diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S index 293e1eba9acc..5c39b80ed7de 100644 --- a/arch/m68k/platform/68328/entry.S +++ b/arch/m68k/platform/68328/entry.S @@ -67,7 +67,7 @@ ret_from_signal: jra ret_from_exception ENTRY(system_call) - SAVE_ALL + SAVE_ALL_SYS /* save top of frame*/ pea %sp@ @@ -129,7 +129,7 @@ Lsignal_return: * This is the main interrupt handler, responsible for calling process_int() */ inthandler1: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -140,7 +140,7 @@ inthandler1: bra ret_from_interrupt inthandler2: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -151,7 +151,7 @@ inthandler2: bra ret_from_interrupt inthandler3: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -162,7 +162,7 @@ inthandler3: bra ret_from_interrupt inthandler4: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -173,7 +173,7 @@ inthandler4: bra ret_from_interrupt inthandler5: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -184,7 +184,7 @@ inthandler5: bra ret_from_interrupt inthandler6: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -195,7 +195,7 @@ inthandler6: bra ret_from_interrupt inthandler7: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 @@ -206,7 +206,7 @@ inthandler7: bra ret_from_interrupt inthandler: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and #0x3ff, %d0 diff --git a/arch/m68k/platform/68360/Makefile b/arch/m68k/platform/68360/Makefile index cf5af73a5789..f6f434383049 100644 --- a/arch/m68k/platform/68360/Makefile +++ b/arch/m68k/platform/68360/Makefile @@ -1,10 +1,12 @@ # # Makefile for arch/m68knommu/platform/68360. # +model-y := ram +model-$(CONFIG_ROMKERNEL) := rom obj-y := config.o commproc.o entry.o ints.o extra-y := head.o -$(obj)/head.o: $(obj)/head-$(MODEL).o - ln -sf head-$(MODEL).o $(obj)/head.o +$(obj)/head.o: $(obj)/head-$(model-y).o + ln -sf head-$(model-y).o $(obj)/head.o diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S index abbb89672ea0..aa47d1d49929 100644 --- a/arch/m68k/platform/68360/entry.S +++ b/arch/m68k/platform/68360/entry.S @@ -63,7 +63,7 @@ ret_from_signal: jra ret_from_exception ENTRY(system_call) - SAVE_ALL + SAVE_ALL_SYS /* save top of frame*/ pea %sp@ @@ -125,7 +125,7 @@ Lsignal_return: * This is the main interrupt handler, responsible for calling do_IRQ() */ inthandler: - SAVE_ALL + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC), %d0 and.l #0x3ff, %d0 lsr.l #0x02, %d0 diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S index bd27242c2f43..3157461a8d1d 100644 --- a/arch/m68k/platform/coldfire/entry.S +++ b/arch/m68k/platform/coldfire/entry.S @@ -61,7 +61,7 @@ enosys: bra 1f ENTRY(system_call) - SAVE_ALL + SAVE_ALL_SYS move #0x2000,%sr /* enable intrs again */ cmpl #NR_syscalls,%d0 @@ -165,9 +165,7 @@ Lsignal_return: * sources). Calls up to high level code to do all the work. */ ENTRY(inthandler) - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(PT_OFF_ORIG_D0) + SAVE_ALL_INT movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */ andl #0x03fc,%d0 /* mask out vector only */ diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README index b26d5f55e91d..93f4c4cd3c45 100644 --- a/arch/m68k/q40/README +++ b/arch/m68k/q40/README @@ -31,7 +31,7 @@ drivers used by the Q40, apart from the very obvious (console etc.): char/joystick/* # most of this should work, not # in default config.in block/q40ide.c # startup for ide - ide* # see Documentation/ide.txt + ide* # see Documentation/ide/ide.txt floppy.c # normal PC driver, DMA emu in asm/floppy.h # and arch/m68k/kernel/entry.S # see drivers/block/README.fd diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h index 8fbb0ec10233..a569514cf19f 100644 --- a/arch/microblaze/include/asm/dma-mapping.h +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -16,7 +16,7 @@ #define _ASM_MICROBLAZE_DMA_MAPPING_H /* - * See Documentation/PCI/PCI-DMA-mapping.txt and + * See Documentation/DMA-API-HOWTO.txt and * Documentation/DMA-API.txt for documentation. */ diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index d915a122c865..8789daa2a346 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -173,7 +173,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* sys_vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* old nfsservctl */ .long sys_setresgid /* 170 */ .long sys_getresgid .long sys_prctl diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 213f2d671669..36a133e5ee35 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -304,11 +304,11 @@ asmlinkage void __init mmu_init(void) /* Map in all of RAM starting at CONFIG_KERNEL_START */ mapin_ram(); -#ifdef HIGHMEM_START_BOOL - ioremap_base = HIGHMEM_START; +#ifdef CONFIG_HIGHMEM_START_BOOL + ioremap_base = CONFIG_HIGHMEM_START; #else ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */ -#endif /* CONFIG_HIGHMEM */ +#endif /* CONFIG_HIGHMEM_START_BOOL */ ioremap_bot = ioremap_base; /* Initialize the context management stuff */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 177cdaf83564..4cbc6d8de210 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -24,6 +24,7 @@ config MIPS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW select HAVE_ARCH_JUMP_LABEL + select IRQ_FORCED_THREADING menu "Machine selection" @@ -91,15 +92,8 @@ config BCM47XX select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU - select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN - select SSB - select SSB_DRIVER_MIPS - select SSB_DRIVER_EXTIF - select SSB_EMBEDDED - select SSB_B43_PCI_BRIDGE if PCI - select SSB_PCICORE_HOSTMODE if PCI select GENERIC_GPIO select SYS_HAS_EARLY_PRINTK select CFE @@ -722,6 +716,7 @@ config CAVIUM_OCTEON_SIMULATOR select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_HOTPLUG_CPU select SYS_HAS_CPU_CAVIUM_OCTEON + select HOLES_IN_ZONE help The Octeon simulator is software performance model of the Cavium Octeon Processor. It supports simulating Octeon processors on x86 @@ -744,6 +739,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD select ZONE_DMA32 select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_EHCI + select HOLES_IN_ZONE help This option supports all of the Octeon reference boards from Cavium Networks. It builds a kernel that dynamically determines the Octeon @@ -788,6 +784,7 @@ endchoice source "arch/mips/alchemy/Kconfig" source "arch/mips/ath79/Kconfig" +source "arch/mips/bcm47xx/Kconfig" source "arch/mips/bcm63xx/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/jz4740/Kconfig" @@ -973,6 +970,9 @@ config ISA_DMA_API config GENERIC_GPIO bool +config HOLES_IN_ZONE + bool + # # Endianess selection. Sufficiently obscure so many users don't know what to # answer,so we try hard to limit the available choices. Also the use of a diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 3b2c18b14341..f72c48d4804c 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -492,7 +492,7 @@ static void __init alchemy_setup_macs(int ctype) memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); ret = platform_device_register(&au1xxx_eth0_device); - if (!ret) + if (ret) printk(KERN_INFO "Alchemy: failed to register MAC0\n"); diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c index 647e518c90bc..b86324a42601 100644 --- a/arch/mips/alchemy/common/power.c +++ b/arch/mips/alchemy/common/power.c @@ -158,15 +158,21 @@ static void restore_core_regs(void) void au_sleep(void) { - int cpuid = alchemy_get_cputype(); - if (cpuid != ALCHEMY_CPU_UNKNOWN) { - save_core_regs(); - if (cpuid <= ALCHEMY_CPU_AU1500) - alchemy_sleep_au1000(); - else if (cpuid <= ALCHEMY_CPU_AU1200) - alchemy_sleep_au1550(); - restore_core_regs(); + save_core_regs(); + + switch (alchemy_get_cputype()) { + case ALCHEMY_CPU_AU1000: + case ALCHEMY_CPU_AU1500: + case ALCHEMY_CPU_AU1100: + alchemy_sleep_au1000(); + break; + case ALCHEMY_CPU_AU1550: + case ALCHEMY_CPU_AU1200: + alchemy_sleep_au1550(); + break; } + + restore_core_regs(); } #endif /* CONFIG_PM */ diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c index 596ad00e7f05..463d2c4d9441 100644 --- a/arch/mips/alchemy/devboards/bcsr.c +++ b/arch/mips/alchemy/devboards/bcsr.c @@ -89,8 +89,12 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) { unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT); + disable_irq_nosync(irq); + for ( ; bisr; bisr &= bisr - 1) generic_handle_irq(bcsr_csc_base + __ffs(bisr)); + + enable_irq(irq); } /* NOTE: both the enable and mask bits must be cleared, otherwise the diff --git a/arch/mips/alchemy/devboards/db1200/setup.c b/arch/mips/alchemy/devboards/db1200/setup.c index 1dac4f27d334..4a8980027ecf 100644 --- a/arch/mips/alchemy/devboards/db1200/setup.c +++ b/arch/mips/alchemy/devboards/db1200/setup.c @@ -23,13 +23,6 @@ void __init board_setup(void) unsigned long freq0, clksrc, div, pfc; unsigned short whoami; - /* Set Config[OD] (disable overlapping bus transaction): - * This gets rid of a _lot_ of spurious interrupts (especially - * wrt. IDE); but incurs ~10% performance hit in some - * cpu-bound applications. - */ - set_c0_config(1 << 19); - bcsr_init(DB1200_BCSR_PHYS_ADDR, DB1200_BCSR_PHYS_ADDR + DB1200_BCSR_HEXLED_OFS); diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c index 03db3daadbd8..88c4babfdb5d 100644 --- a/arch/mips/ar7/irq.c +++ b/arch/mips/ar7/irq.c @@ -98,7 +98,8 @@ static struct irq_chip ar7_sec_irq_type = { static struct irqaction ar7_cascade_action = { .handler = no_action, - .name = "AR7 cascade interrupt" + .name = "AR7 cascade interrupt", + .flags = IRQF_NO_THREAD, }; static void __init ar7_irq_init(int base) diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig new file mode 100644 index 000000000000..6210b8d84109 --- /dev/null +++ b/arch/mips/bcm47xx/Kconfig @@ -0,0 +1,31 @@ +if BCM47XX + +config BCM47XX_SSB + bool "SSB Support for Broadcom BCM47XX" + select SYS_HAS_CPU_MIPS32_R1 + select SSB + select SSB_DRIVER_MIPS + select SSB_DRIVER_EXTIF + select SSB_EMBEDDED + select SSB_B43_PCI_BRIDGE if PCI + select SSB_PCICORE_HOSTMODE if PCI + default y + help + Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support. + + This will generate an image with support for SSB and MIPS32 R1 instruction set. + +config BCM47XX_BCMA + bool "BCMA Support for Broadcom BCM47XX" + select SYS_HAS_CPU_MIPS32_R2 + select BCMA + select BCMA_HOST_SOC + select BCMA_DRIVER_MIPS + select BCMA_DRIVER_PCI_HOSTMODE if PCI + default y + help + Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. + + This will generate an image with support for BCMA and MIPS32 R2 instruction set. + +endif diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index 7465e8a72d9a..4add17349ff9 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile @@ -3,4 +3,5 @@ # under Linux. # -obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o +obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o +obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c index e4a5ee9c9721..57b425fd4d41 100644 --- a/arch/mips/bcm47xx/gpio.c +++ b/arch/mips/bcm47xx/gpio.c @@ -20,42 +20,82 @@ static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES); int gpio_request(unsigned gpio, const char *tag) { - if (ssb_chipco_available(&ssb_bcm47xx.chipco) && - ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) - return -EINVAL; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) + return -EINVAL; - if (ssb_extif_available(&ssb_bcm47xx.extif) && - ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) - return -EINVAL; + if (ssb_extif_available(&bcm47xx_bus.ssb.extif) && + ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) + return -EINVAL; - if (test_and_set_bit(gpio, gpio_in_use)) - return -EBUSY; + if (test_and_set_bit(gpio, gpio_in_use)) + return -EBUSY; - return 0; + return 0; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + if (gpio >= BCM47XX_CHIPCO_GPIO_LINES) + return -EINVAL; + + if (test_and_set_bit(gpio, gpio_in_use)) + return -EBUSY; + + return 0; +#endif + } + return -EINVAL; } EXPORT_SYMBOL(gpio_request); void gpio_free(unsigned gpio) { - if (ssb_chipco_available(&ssb_bcm47xx.chipco) && - ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) - return; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) + return; + + if (ssb_extif_available(&bcm47xx_bus.ssb.extif) && + ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) + return; - if (ssb_extif_available(&ssb_bcm47xx.extif) && - ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) + clear_bit(gpio, gpio_in_use); return; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + if (gpio >= BCM47XX_CHIPCO_GPIO_LINES) + return; - clear_bit(gpio, gpio_in_use); + clear_bit(gpio, gpio_in_use); + return; +#endif + } } EXPORT_SYMBOL(gpio_free); int gpio_to_irq(unsigned gpio) { - if (ssb_chipco_available(&ssb_bcm47xx.chipco)) - return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2; - else if (ssb_extif_available(&ssb_bcm47xx.extif)) - return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2; - else - return -EINVAL; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco)) + return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2; + else if (ssb_extif_available(&bcm47xx_bus.ssb.extif)) + return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2; + else + return -EINVAL; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2; +#endif + } + return -EINVAL; } EXPORT_SYMBOL_GPL(gpio_to_irq); diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c index 325757acd020..8cf3833b2d29 100644 --- a/arch/mips/bcm47xx/irq.c +++ b/arch/mips/bcm47xx/irq.c @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <asm/irq_cpu.h> +#include <bcm47xx.h> void plat_irq_dispatch(void) { @@ -51,5 +52,16 @@ void plat_irq_dispatch(void) void __init arch_init_irq(void) { +#ifdef CONFIG_BCM47XX_BCMA + if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { + bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, + BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31); + /* + * the kernel reads the timer irq from some register and thinks + * it's #5, but we offset it by 2 and route to #7 + */ + cp0_compare_irq = 7; + } +#endif mips_cpu_irq_init(); } diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 54db815bc86c..a84e3bb7387f 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -26,14 +26,35 @@ static char nvram_buf[NVRAM_SPACE]; /* Probe for NVRAM header */ static void early_nvram_init(void) { - struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; +#ifdef CONFIG_BCM47XX_SSB + struct ssb_mipscore *mcore_ssb; +#endif +#ifdef CONFIG_BCM47XX_BCMA + struct bcma_drv_cc *bcma_cc; +#endif struct nvram_header *header; int i; - u32 base, lim, off; + u32 base = 0; + u32 lim = 0; + u32 off; u32 *src, *dst; - base = mcore->flash_window; - lim = mcore->flash_window_size; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + mcore_ssb = &bcm47xx_bus.ssb.mipscore; + base = mcore_ssb->flash_window; + lim = mcore_ssb->flash_window_size; + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; + base = bcma_cc->pflash.window; + lim = bcma_cc->pflash.window_size; + break; +#endif + } off = FLASH_MIN; while (off <= lim) { diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index 59c11afdb2ab..57981e4fe2bc 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c @@ -23,10 +23,11 @@ static struct platform_device uart8250_device = { }, }; -static int __init uart8250_init(void) +#ifdef CONFIG_BCM47XX_SSB +static int __init uart8250_init_ssb(void) { int i; - struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore); + struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore); memset(&uart8250_data, 0, sizeof(uart8250_data)); @@ -44,6 +45,47 @@ static int __init uart8250_init(void) } return platform_device_register(&uart8250_device); } +#endif + +#ifdef CONFIG_BCM47XX_BCMA +static int __init uart8250_init_bcma(void) +{ + int i; + struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc); + + memset(&uart8250_data, 0, sizeof(uart8250_data)); + + for (i = 0; i < cc->nr_serial_ports; i++) { + struct plat_serial8250_port *p = &(uart8250_data[i]); + struct bcma_serial_port *bcma_port; + bcma_port = &(cc->serial_ports[i]); + + p->mapbase = (unsigned int) bcma_port->regs; + p->membase = (void *) bcma_port->regs; + p->irq = bcma_port->irq + 2; + p->uartclk = bcma_port->baud_base; + p->regshift = bcma_port->reg_shift; + p->iotype = UPIO_MEM; + p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + } + return platform_device_register(&uart8250_device); +} +#endif + +static int __init uart8250_init(void) +{ + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + return uart8250_init_ssb(); +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + return uart8250_init_bcma(); +#endif + } + return -EINVAL; +} module_init(uart8250_init); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index cfae81571ded..17c3d14d7c49 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -29,21 +29,36 @@ #include <linux/types.h> #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_embedded.h> +#include <linux/bcma/bcma_soc.h> #include <asm/bootinfo.h> #include <asm/reboot.h> #include <asm/time.h> #include <bcm47xx.h> #include <asm/mach-bcm47xx/nvram.h> -struct ssb_bus ssb_bcm47xx; -EXPORT_SYMBOL(ssb_bcm47xx); +union bcm47xx_bus bcm47xx_bus; +EXPORT_SYMBOL(bcm47xx_bus); + +enum bcm47xx_bus_type bcm47xx_bus_type; +EXPORT_SYMBOL(bcm47xx_bus_type); static void bcm47xx_machine_restart(char *command) { printk(KERN_ALERT "Please stand by while rebooting the system...\n"); local_irq_disable(); /* Set the watchdog timer to reset immediately */ - ssb_watchdog_timer_set(&ssb_bcm47xx, 1); + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1); + break; +#endif + } while (1) cpu_relax(); } @@ -52,11 +67,23 @@ static void bcm47xx_machine_halt(void) { /* Disable interrupts and watchdog and spin forever */ local_irq_disable(); - ssb_watchdog_timer_set(&ssb_bcm47xx, 0); + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0); + break; +#endif + } while (1) cpu_relax(); } +#ifdef CONFIG_BCM47XX_SSB #define READ_FROM_NVRAM(_outvar, name, buf) \ if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\ sprom->_outvar = simple_strtoul(buf, NULL, 0); @@ -247,7 +274,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, return 0; } -void __init plat_mem_setup(void) +static void __init bcm47xx_register_ssb(void) { int err; char buf[100]; @@ -258,12 +285,12 @@ void __init plat_mem_setup(void) printk(KERN_WARNING "bcm47xx: someone else already registered" " a ssb SPROM callback handler (err %d)\n", err); - err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, + err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, bcm47xx_get_invariants); if (err) panic("Failed to initialize SSB bus (err %d)\n", err); - mcore = &ssb_bcm47xx.mipscore; + mcore = &bcm47xx_bus.ssb.mipscore; if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { if (strstr(buf, "console=ttyS1")) { struct ssb_serial_port port; @@ -276,8 +303,57 @@ void __init plat_mem_setup(void) memcpy(&mcore->serial_ports[1], &port, sizeof(port)); } } +} +#endif + +#ifdef CONFIG_BCM47XX_BCMA +static void __init bcm47xx_register_bcma(void) +{ + int err; + + err = bcma_host_soc_register(&bcm47xx_bus.bcma); + if (err) + panic("Failed to initialize BCMA bus (err %d)\n", err); +} +#endif + +void __init plat_mem_setup(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + if (c->cputype == CPU_74K) { + printk(KERN_INFO "bcm47xx: using bcma bus\n"); +#ifdef CONFIG_BCM47XX_BCMA + bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; + bcm47xx_register_bcma(); +#endif + } else { + printk(KERN_INFO "bcm47xx: using ssb bus\n"); +#ifdef CONFIG_BCM47XX_SSB + bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; + bcm47xx_register_ssb(); +#endif + } _machine_restart = bcm47xx_machine_restart; _machine_halt = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt; } + +static int __init bcm47xx_register_bus_complete(void) +{ + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + /* Nothing to do */ + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_bus_register(&bcm47xx_bus.bcma.bus); + break; +#endif + } + return 0; +} +device_initcall(bcm47xx_register_bus_complete); diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c index 0c6f47b3fd94..536374dcba78 100644 --- a/arch/mips/bcm47xx/time.c +++ b/arch/mips/bcm47xx/time.c @@ -30,7 +30,7 @@ void __init plat_time_init(void) { - unsigned long hz; + unsigned long hz = 0; /* * Use deterministic values for initial counter interrupt @@ -39,7 +39,19 @@ void __init plat_time_init(void) write_c0_count(0); write_c0_compare(0xffff); - hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2; + break; +#endif + } + if (!hz) hz = 100000000; diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c index 74d06965326f..e9f9ec8d443b 100644 --- a/arch/mips/bcm47xx/wgt634u.c +++ b/arch/mips/bcm47xx/wgt634u.c @@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored) /* Interrupts are shared, check if the current one is a GPIO interrupt. */ - if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco, + if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco, SSB_CHIPCO_IRQ_GPIO)) return IRQ_NONE; @@ -132,22 +132,26 @@ static int __init wgt634u_init(void) * machine. Use the MAC address as an heuristic. Netgear Inc. has * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. */ + u8 *et0mac; - u8 *et0mac = ssb_bcm47xx.sprom.et0mac; + if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) + return -ENODEV; + + et0mac = bcm47xx_bus.ssb.sprom.et0mac; if (et0mac[0] == 0x00 && ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { - struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; + struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; printk(KERN_INFO "WGT634U machine detected.\n"); if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET), gpio_interrupt, IRQF_SHARED, - "WGT634U GPIO", &ssb_bcm47xx.chipco)) { + "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) { gpio_direction_input(WGT634U_GPIO_RESET); gpio_intmask(WGT634U_GPIO_RESET, 1); - ssb_chipco_irq_mask(&ssb_bcm47xx.chipco, + ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco, SSB_CHIPCO_IRQ_GPIO, SSB_CHIPCO_IRQ_GPIO); } diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index cea6021cb8d7..162e11b4ed75 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -222,6 +222,7 @@ static struct irq_chip bcm63xx_external_irq_chip = { static struct irqaction cpu_ip2_cascade_action = { .handler = no_action, .name = "cascade_ip2", + .flags = IRQF_NO_THREAD, }; void __init arch_init_irq(void) diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c index cb9bf820fe53..965c777d3561 100644 --- a/arch/mips/cobalt/irq.c +++ b/arch/mips/cobalt/irq.c @@ -48,6 +48,7 @@ asmlinkage void plat_irq_dispatch(void) static struct irqaction cascade = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; void __init arch_init_irq(void) diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index fa45e924be05..f7b7ba6d5c45 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -101,20 +101,24 @@ int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU); static struct irqaction ioirq = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; static struct irqaction fpuirq = { .handler = no_action, .name = "fpu", + .flags = IRQF_NO_THREAD, }; static struct irqaction busirq = { .flags = IRQF_DISABLED, .name = "bus error", + .flags = IRQF_NO_THREAD, }; static struct irqaction haltirq = { .handler = dec_intr_halt, .name = "halt", + .flags = IRQF_NO_THREAD, }; diff --git a/arch/mips/emma/markeins/irq.c b/arch/mips/emma/markeins/irq.c index 3dbd7a5a6ad3..7798887a1288 100644 --- a/arch/mips/emma/markeins/irq.c +++ b/arch/mips/emma/markeins/irq.c @@ -169,7 +169,7 @@ void emma2rh_gpio_irq_init(void) static struct irqaction irq_cascade = { .handler = no_action, - .flags = 0, + .flags = IRQF_NO_THREAD, .name = "cascade", .dev_id = NULL, .next = NULL, diff --git a/arch/mips/include/asm/lasat/lasat.h b/arch/mips/include/asm/lasat/lasat.h index a1ada1c27c16..e8ff70f80e13 100644 --- a/arch/mips/include/asm/lasat/lasat.h +++ b/arch/mips/include/asm/lasat/lasat.h @@ -41,10 +41,8 @@ enum lasat_mtdparts { /* * The format of the data record in the EEPROM. - * See Documentation/LASAT/eeprom.txt for a detailed description - * of the fields in this struct, and the LASAT Hardware Configuration - * field specification for a detailed description of the config - * field. + * See the LASAT Hardware Configuration field specification for a detailed + * description of the config field. */ #include <linux/types.h> diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index d008f47a28bd..de95e0723e2b 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -19,7 +19,29 @@ #ifndef __ASM_BCM47XX_H #define __ASM_BCM47XX_H -/* SSB bus */ -extern struct ssb_bus ssb_bcm47xx; +#include <linux/ssb/ssb.h> +#include <linux/bcma/bcma.h> +#include <linux/bcma/bcma_soc.h> + +enum bcm47xx_bus_type { +#ifdef CONFIG_BCM47XX_SSB + BCM47XX_BUS_TYPE_SSB, +#endif +#ifdef CONFIG_BCM47XX_BCMA + BCM47XX_BUS_TYPE_BCMA, +#endif +}; + +union bcm47xx_bus { +#ifdef CONFIG_BCM47XX_SSB + struct ssb_bus ssb; +#endif +#ifdef CONFIG_BCM47XX_BCMA + struct bcma_soc bcma; +#endif +}; + +extern union bcm47xx_bus bcm47xx_bus; +extern enum bcm47xx_bus_type bcm47xx_bus_type; #endif /* __ASM_BCM47XX_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h index 98504142124e..76961cabeedf 100644 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h @@ -10,6 +10,7 @@ #define __BCM47XX_GPIO_H #include <linux/ssb/ssb_embedded.h> +#include <linux/bcma/bcma.h> #include <asm/mach-bcm47xx/bcm47xx.h> #define BCM47XX_EXTIF_GPIO_LINES 5 @@ -21,41 +22,118 @@ extern int gpio_to_irq(unsigned gpio); static inline int gpio_get_value(unsigned gpio) { - return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio); + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc, + 1 << gpio); +#endif + } + return -EINVAL; } static inline void gpio_set_value(unsigned gpio, int value) { - ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0); + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + return; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, + value ? 1 << gpio : 0); + return; +#endif + } } static inline int gpio_direction_input(unsigned gpio) { - ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); - return 0; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); + return 0; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, + 0); + return 0; +#endif + } + return -EINVAL; } static inline int gpio_direction_output(unsigned gpio, int value) { - /* first set the gpio out value */ - ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0); - /* then set the gpio mode */ - ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); - return 0; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + /* first set the gpio out value */ + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + /* then set the gpio mode */ + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio); + return 0; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + /* first set the gpio out value */ + bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, + value ? 1 << gpio : 0); + /* then set the gpio mode */ + bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, + 1 << gpio); + return 0; +#endif + } + return -EINVAL; } static inline int gpio_intmask(unsigned gpio, int value) { - ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, - value ? 1 << gpio : 0); - return 0; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + return 0; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc, + 1 << gpio, value ? 1 << gpio : 0); + return 0; +#endif + } + return -EINVAL; } static inline int gpio_polarity(unsigned gpio, int value) { - ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, - value ? 1 << gpio : 0); - return 0; + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + return 0; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc, + 1 << gpio, value ? 1 << gpio : 0); + return 0; +#endif + } + return -EINVAL; } diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index 0d5a42b5f47a..a58addb98cfd 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -54,7 +54,6 @@ #define cpu_has_mips_r2_exec_hazard 0 #define cpu_has_dsp 0 #define cpu_has_mipsmt 0 -#define cpu_has_userlocal 0 #define cpu_has_vint 0 #define cpu_has_veic 0 #define cpu_hwrena_impl_bits 0xc0000000 diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h index 62c094085947..35371641575d 100644 --- a/arch/mips/include/asm/mach-powertv/dma-coherence.h +++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h @@ -13,7 +13,6 @@ #define __ASM_MACH_POWERTV_DMA_COHERENCE_H #include <linux/sched.h> -#include <linux/version.h> #include <linux/device.h> #include <asm/mach-powertv/asic.h> diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index b4ba2449444b..cb41af5f3406 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -195,9 +195,9 @@ * to cover the pipeline delay. */ .set mips32 - mfc0 v1, CP0_TCSTATUS + mfc0 k0, CP0_TCSTATUS .set mips0 - LONG_S v1, PT_TCSTATUS(sp) + LONG_S k0, PT_TCSTATUS(sp) #endif /* CONFIG_MIPS_MT_SMTC */ LONG_S $4, PT_R4(sp) LONG_S $5, PT_R5(sp) diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 73031f7fc827..4397972949fa 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -18,7 +18,7 @@ #include <linux/init.h> #include <linux/spinlock.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/delay.h> @@ -86,7 +86,6 @@ struct jz_gpio_chip { spinlock_t lock; struct gpio_chip gpio_chip; - struct sys_device sysdev; }; static struct jz_gpio_chip jz4740_gpio_chips[]; @@ -459,49 +458,47 @@ static struct jz_gpio_chip jz4740_gpio_chips[] = { JZ4740_GPIO_CHIP(D), }; -static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev) +static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip) { - return container_of(dev, struct jz_gpio_chip, sysdev); + chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); + writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); + writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); } -static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state) +static int jz4740_gpio_suspend(void) { - struct jz_gpio_chip *chip = sysdev_to_chip(dev); + int i; - chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); - writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); - writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); + for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++) + jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]); return 0; } -static int jz4740_gpio_resume(struct sys_device *dev) +static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip) { - struct jz_gpio_chip *chip = sysdev_to_chip(dev); uint32_t mask = chip->suspend_mask; writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); +} - return 0; +static void jz4740_gpio_resume(void) +{ + int i; + + for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--) + jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]); } -static struct sysdev_class jz4740_gpio_sysdev_class = { - .name = "gpio", +static struct syscore_ops jz4740_gpio_syscore_ops = { .suspend = jz4740_gpio_suspend, .resume = jz4740_gpio_resume, }; -static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) +static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) { - int ret, irq; - - chip->sysdev.id = id; - chip->sysdev.cls = &jz4740_gpio_sysdev_class; - ret = sysdev_register(&chip->sysdev); - - if (ret) - return ret; + int irq; spin_lock_init(&chip->lock); @@ -519,22 +516,17 @@ static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) irq_set_chip_and_handler(irq, &jz_gpio_irq_chip, handle_level_irq); } - - return 0; } static int __init jz4740_gpio_init(void) { unsigned int i; - int ret; - - ret = sysdev_class_register(&jz4740_gpio_sysdev_class); - if (ret) - return ret; for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); + register_syscore_ops(&jz4740_gpio_syscore_ops); + printk(KERN_INFO "JZ4740 GPIO initialized\n"); return 0; diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index feb8021a305f..6a2d758dd8e9 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -19,6 +19,26 @@ #include <asm-generic/sections.h> +#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) +#define MCOUNT_OFFSET_INSNS 5 +#else +#define MCOUNT_OFFSET_INSNS 4 +#endif + +/* + * Check if the address is in kernel space + * + * Clone core_kernel_text() from kernel/extable.c, but doesn't call + * init_kernel_text() for Ftrace doesn't trace functions in init sections. + */ +static inline int in_kernel_space(unsigned long ip) +{ + if (ip >= (unsigned long)_stext && + ip <= (unsigned long)_etext) + return 1; + return 0; +} + #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ @@ -54,20 +74,6 @@ static inline void ftrace_dyn_arch_init_insns(void) #endif } -/* - * Check if the address is in kernel space - * - * Clone core_kernel_text() from kernel/extable.c, but doesn't call - * init_kernel_text() for Ftrace doesn't trace functions in init sections. - */ -static inline int in_kernel_space(unsigned long ip) -{ - if (ip >= (unsigned long)_stext && - ip <= (unsigned long)_etext) - return 1; - return 0; -} - static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { int faulted; @@ -112,11 +118,6 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) * 1: offset = 4 instructions */ -#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) -#define MCOUNT_OFFSET_INSNS 5 -#else -#define MCOUNT_OFFSET_INSNS 4 -#endif #define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS) int ftrace_make_nop(struct module *mod, diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 5c74eb797f08..32b397b646ee 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -229,7 +229,7 @@ static void i8259A_shutdown(void) */ if (i8259A_auto_eoi >= 0) { outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ - outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ } } @@ -295,6 +295,7 @@ static void init_8259A(int auto_eoi) static struct irqaction irq2 = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; static struct resource pic1_io_resource = { diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 876a75cc376f..922a554cd108 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -349,3 +349,10 @@ SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags, return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4), dfd, pathname); } + +SYSCALL_DEFINE6(32_futex, u32 __user *, uaddr, int, op, u32, val, + struct compat_timespec __user *, utime, u32 __user *, uaddr2, + u32, val3) +{ + return compat_sys_futex(uaddr, op, val, utime, uaddr2, val3); +} diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index e521420a45a5..865bc7a6f5a1 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -424,7 +424,7 @@ einval: li v0, -ENOSYS sys sys_getresuid 3 sys sys_ni_syscall 0 /* was sys_query_module */ sys sys_poll 3 - sys sys_nfsservctl 3 + sys sys_ni_syscall 0 /* was nfsservctl */ sys sys_setresgid 3 /* 4190 */ sys sys_getresgid 3 sys sys_prctl 5 diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 85874d6a8a70..fb7334bea731 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -299,7 +299,7 @@ sys_call_table: PTR sys_ni_syscall /* 5170, was get_kernel_syms */ PTR sys_ni_syscall /* was query_module */ PTR sys_quotactl - PTR sys_nfsservctl + PTR sys_ni_syscall /* was nfsservctl */ PTR sys_ni_syscall /* res. for getpmsg */ PTR sys_ni_syscall /* 5175 for putpmsg */ PTR sys_ni_syscall /* res. for afs_syscall */ diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index b85842fc87ae..6de1f598346e 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -294,7 +294,7 @@ EXPORT(sysn32_call_table) PTR sys_ni_syscall /* 6170, was get_kernel_syms */ PTR sys_ni_syscall /* was query_module */ PTR sys_quotactl - PTR compat_sys_nfsservctl + PTR sys_ni_syscall /* was nfsservctl */ PTR sys_ni_syscall /* res. for getpmsg */ PTR sys_ni_syscall /* 6175 for putpmsg */ PTR sys_ni_syscall /* res. for afs_syscall */ @@ -315,7 +315,7 @@ EXPORT(sysn32_call_table) PTR sys_fremovexattr PTR sys_tkill PTR sys_ni_syscall - PTR compat_sys_futex + PTR sys_32_futex PTR compat_sys_sched_setaffinity /* 6195 */ PTR compat_sys_sched_getaffinity PTR sys_cacheflush diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 46c4763edf21..1d813169e453 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -392,7 +392,7 @@ sys_call_table: PTR sys_getresuid PTR sys_ni_syscall /* was query_module */ PTR sys_poll - PTR compat_sys_nfsservctl + PTR sys_ni_syscall /* was nfsservctl */ PTR sys_setresgid /* 4190 */ PTR sys_getresgid PTR sys_prctl @@ -441,7 +441,7 @@ sys_call_table: PTR sys_fremovexattr /* 4235 */ PTR sys_tkill PTR sys_sendfile64 - PTR compat_sys_futex + PTR sys_32_futex PTR compat_sys_sched_setaffinity PTR compat_sys_sched_getaffinity /* 4240 */ PTR compat_sys_io_setup diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index dbbe0ce48d89..f8524003676a 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -8,6 +8,7 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include <linux/cache.h> +#include <linux/irqflags.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/personality.h> @@ -658,6 +659,8 @@ static void do_signal(struct pt_regs *regs) asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { + local_irq_enable(); + /* deal with pending signal delivery */ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b7517e3abc85..cbea618af0b4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -14,6 +14,7 @@ #include <linux/bug.h> #include <linux/compiler.h> #include <linux/init.h> +#include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/sched.h> @@ -364,21 +365,26 @@ static int regs_to_trapnr(struct pt_regs *regs) return (regs->cp0_cause >> 2) & 0x1f; } -static DEFINE_SPINLOCK(die_lock); +static DEFINE_RAW_SPINLOCK(die_lock); void __noreturn die(const char *str, struct pt_regs *regs) { static int die_counter; int sig = SIGSEGV; #ifdef CONFIG_MIPS_MT_SMTC - unsigned long dvpret = dvpe(); + unsigned long dvpret; #endif /* CONFIG_MIPS_MT_SMTC */ + oops_enter(); + if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP) sig = 0; console_verbose(); - spin_lock_irq(&die_lock); + raw_spin_lock_irq(&die_lock); +#ifdef CONFIG_MIPS_MT_SMTC + dvpret = dvpe(); +#endif /* CONFIG_MIPS_MT_SMTC */ bust_spinlocks(1); #ifdef CONFIG_MIPS_MT_SMTC mips_mt_regdump(dvpret); @@ -387,7 +393,9 @@ void __noreturn die(const char *str, struct pt_regs *regs) printk("%s[#%d]:\n", str, ++die_counter); show_registers(regs); add_taint(TAINT_DIE); - spin_unlock_irq(&die_lock); + raw_spin_unlock_irq(&die_lock); + + oops_exit(); if (in_interrupt()) panic("Fatal exception in interrupt"); diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 2cd50ad0d5c6..3efcb065f78a 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -192,7 +192,7 @@ static struct tc *get_tc(int index) } spin_unlock(&vpecontrol.tc_list_lock); - return NULL; + return res; } /* allocate a vpe and associate it with this minor (or index) */ diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index fc89795cafdb..f9737bb3c5ab 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -123,11 +123,10 @@ void ltq_enable_irq(struct irq_data *d) static unsigned int ltq_startup_eiu_irq(struct irq_data *d) { int i; - int irq_nr = d->irq - INT_NUM_IRQ0; ltq_enable_irq(d); for (i = 0; i < MAX_EIU; i++) { - if (irq_nr == ltq_eiu_irq[i]) { + if (d->irq == ltq_eiu_irq[i]) { /* low level - we should really handle set_type */ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) | (0x6 << (i * 4)), LTQ_EIU_EXIN_C); @@ -147,11 +146,10 @@ static unsigned int ltq_startup_eiu_irq(struct irq_data *d) static void ltq_shutdown_eiu_irq(struct irq_data *d) { int i; - int irq_nr = d->irq - INT_NUM_IRQ0; ltq_disable_irq(d); for (i = 0; i < MAX_EIU; i++) { - if (irq_nr == ltq_eiu_irq[i]) { + if (d->irq == ltq_eiu_irq[i]) { /* disable */ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i), LTQ_EIU_EXIN_INEN); diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c index 66eb52fa50a1..033b3184c7a7 100644 --- a/arch/mips/lantiq/xway/ebu.c +++ b/arch/mips/lantiq/xway/ebu.c @@ -10,7 +10,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/ioport.h> #include <lantiq_soc.h> diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c index 9d69f01e352b..39f0d2641cbf 100644 --- a/arch/mips/lantiq/xway/pmu.c +++ b/arch/mips/lantiq/xway/pmu.c @@ -8,7 +8,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/ioport.h> #include <lantiq_soc.h> diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index de4c165515d7..d608b6ef0edd 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -105,6 +105,7 @@ asmlinkage void plat_irq_dispatch(void) static struct irqaction cascade = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; void __init arch_init_irq(void) diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c index d61a04222b87..3cf1fef29f0e 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson/fuloong-2e/irq.c @@ -42,6 +42,7 @@ asmlinkage void mach_irq_dispatch(unsigned int pending) static struct irqaction cascade_irqaction = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; void __init mach_init_irq(void) diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 081db102bb98..14b081841b6b 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -96,12 +96,13 @@ static irqreturn_t ip6_action(int cpl, void *dev_id) struct irqaction ip6_irqaction = { .handler = ip6_action, .name = "cascade", - .flags = IRQF_SHARED, + .flags = IRQF_SHARED | IRQF_NO_THREAD, }; struct irqaction cascade_irqaction = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; void __init mach_init_irq(void) diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 9ff5d0fac556..302d779d5b0d 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -6,6 +6,7 @@ * Copyright (C) 2011 Wind River Systems, * written by Ralf Baechle <ralf@linux-mips.org> */ +#include <linux/compiler.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/mman.h> @@ -15,12 +16,11 @@ #include <linux/sched.h> unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ - EXPORT_SYMBOL(shm_align_mask); /* gap between mmap and stack */ #define MIN_GAP (128*1024*1024UL) -#define MAX_GAP ((TASK_SIZE)/6*5) +#define MAX_GAP ((TASK_SIZE)/6*5) static int mmap_is_legacy(void) { @@ -57,13 +57,13 @@ static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr, return base - off; } -#define COLOUR_ALIGN(addr,pgoff) \ +#define COLOUR_ALIGN(addr, pgoff) \ ((((addr) + shm_align_mask) & ~shm_align_mask) + \ (((pgoff) << PAGE_SHIFT) & shm_align_mask)) enum mmap_allocation_direction {UP, DOWN}; -static unsigned long arch_get_unmapped_area_foo(struct file *filp, +static unsigned long arch_get_unmapped_area_common(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, unsigned long flags, enum mmap_allocation_direction dir) { @@ -103,16 +103,16 @@ static unsigned long arch_get_unmapped_area_foo(struct file *filp, vma = find_vma(mm, addr); if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vma->vm_start)) + (!vma || addr + len <= vma->vm_start)) return addr; } if (dir == UP) { addr = mm->mmap_base; - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { /* At this point: (!vma || addr < vma->vm_end). */ @@ -131,28 +131,30 @@ static unsigned long arch_get_unmapped_area_foo(struct file *filp, mm->free_area_cache = mm->mmap_base; } - /* either no address requested or can't fit in requested address hole */ + /* + * either no address requested, or the mapping can't fit into + * the requested address hole + */ addr = mm->free_area_cache; - if (do_color_align) { - unsigned long base = - COLOUR_ALIGN_DOWN(addr - len, pgoff); - + if (do_color_align) { + unsigned long base = + COLOUR_ALIGN_DOWN(addr - len, pgoff); addr = base + len; - } + } /* make sure it can fit in the remaining address space */ if (likely(addr > len)) { vma = find_vma(mm, addr - len); if (!vma || addr <= vma->vm_start) { - /* remember the address as a hint for next time */ - return mm->free_area_cache = addr-len; + /* cache the address as a hint for next time */ + return mm->free_area_cache = addr - len; } } if (unlikely(mm->mmap_base < len)) goto bottomup; - addr = mm->mmap_base-len; + addr = mm->mmap_base - len; if (do_color_align) addr = COLOUR_ALIGN_DOWN(addr, pgoff); @@ -163,8 +165,8 @@ static unsigned long arch_get_unmapped_area_foo(struct file *filp, * return with success: */ vma = find_vma(mm, addr); - if (likely(!vma || addr+len <= vma->vm_start)) { - /* remember the address as a hint for next time */ + if (likely(!vma || addr + len <= vma->vm_start)) { + /* cache the address as a hint for next time */ return mm->free_area_cache = addr; } @@ -173,7 +175,7 @@ static unsigned long arch_get_unmapped_area_foo(struct file *filp, mm->cached_hole_size = vma->vm_start - addr; /* try just below the current vma->vm_start */ - addr = vma->vm_start-len; + addr = vma->vm_start - len; if (do_color_align) addr = COLOUR_ALIGN_DOWN(addr, pgoff); } while (likely(len < vma->vm_start)); @@ -201,7 +203,7 @@ bottomup: unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, unsigned long flags) { - return arch_get_unmapped_area_foo(filp, + return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, UP); } @@ -213,7 +215,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, unsigned long flags) { - return arch_get_unmapped_area_foo(filp, + return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, DOWN); } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index b6e1cff50667..e06370f58ef3 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1759,14 +1759,13 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) u32 *p = handle_tlbm; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - struct work_registers wr; memset(handle_tlbm, 0, sizeof(handle_tlbm)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); build_r3000_tlbchange_handler_head(&p, K0, K1); - build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm); + build_pte_modifiable(&p, &r, K0, K1, -1, label_nopage_tlbm); uasm_i_nop(&p); /* load delay */ build_make_write(&p, &r, K0, K1); build_r3000_pte_reload_tlbwi(&p, K0, K1); @@ -1963,7 +1962,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void) uasm_i_andi(&p, wr.r3, wr.r3, 2); uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2); } - + if (PM_DEFAULT_MASK == 0) + uasm_i_nop(&p); /* * We clobbered C0_PAGEMASK, restore it. On the other branch * it is restored in build_huge_tlb_write_entry. diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 1d36c511a7a5..d53ff91b277c 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -350,12 +350,14 @@ unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) static struct irqaction i8259irq = { .handler = no_action, - .name = "XT-PIC cascade" + .name = "XT-PIC cascade", + .flags = IRQF_NO_THREAD, }; static struct irqaction corehi_irqaction = { .handler = no_action, - .name = "CoreHi" + .name = "CoreHi", + .flags = IRQF_NO_THREAD, }; static msc_irqmap_t __initdata msc_irqmap[] = { diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile index 9bd3f731f62e..2dca585dd2f7 100644 --- a/arch/mips/netlogic/xlr/Makefile +++ b/arch/mips/netlogic/xlr/Makefile @@ -2,4 +2,4 @@ obj-y += setup.o platform.o irq.o setup.o time.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += xlr_console.o -EXTRA_CFLAGS += -Werror +ccflags-y += -Werror diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c index 455f8e50a007..400535a955d0 100644 --- a/arch/mips/pci/pci-bcm47xx.c +++ b/arch/mips/pci/pci-bcm47xx.c @@ -25,6 +25,7 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/ssb/ssb.h> +#include <bcm47xx.h> int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { @@ -33,9 +34,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) int pcibios_plat_dev_init(struct pci_dev *dev) { +#ifdef CONFIG_BCM47XX_SSB int res; u8 slot, pin; + if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) + return 0; + res = ssb_pcibios_plat_dev_init(dev); if (res < 0) { printk(KERN_ALERT "PCI: Failed to init device %s\n", @@ -55,5 +60,6 @@ int pcibios_plat_dev_init(struct pci_dev *dev) } dev->irq = res; +#endif return 0; } diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 603d7493e966..8656388b34bd 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -171,8 +171,13 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) u32 temp_buffer; /* set clock to 33Mhz */ - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR); - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR); + if (ltq_is_ar9()) { + ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR); + } else { + ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR); + } /* external or internal clock ? */ if (conf->clock) { diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index 764362ce5e40..5f3a69cebad1 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -215,7 +215,7 @@ static int __init rc32434_pci_init(void) rc32434_pcibridge_init(); io_map_base = ioremap(rc32434_res_pci_io1.start, - resource_size(&rcrc32434_res_pci_io1)); + resource_size(&rc32434_res_pci_io1)); if (!io_map_base) return -ENOMEM; diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/arch/mips/pmc-sierra/msp71xx/msp_irq.c index 4531c4a514bc..d3c3d81757a5 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_irq.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_irq.c @@ -108,12 +108,14 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) static struct irqaction cic_cascade_msp = { .handler = no_action, - .name = "MSP CIC cascade" + .name = "MSP CIC cascade", + .flags = IRQF_NO_THREAD, }; static struct irqaction per_cascade_msp = { .handler = no_action, - .name = "MSP PER cascade" + .name = "MSP PER cascade", + .flags = IRQF_NO_THREAD, }; void __init arch_init_irq(void) diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index f7261628d8a6..a1c7c7da2336 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c @@ -27,6 +27,7 @@ #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> +#include <linux/slab.h> #include <asm/bootinfo.h> #include <asm/io.h> @@ -38,6 +39,55 @@ #include <msp_int.h> #include <msp_regs.h> +struct msp_uart_data { + int last_lcr; +}; + +static void msp_serial_out(struct uart_port *p, int offset, int value) +{ + struct msp_uart_data *d = p->private_data; + + if (offset == UART_LCR) + d->last_lcr = value; + + offset <<= p->regshift; + writeb(value, p->membase + offset); +} + +static unsigned int msp_serial_in(struct uart_port *p, int offset) +{ + offset <<= p->regshift; + + return readb(p->membase + offset); +} + +static int msp_serial_handle_irq(struct uart_port *p) +{ + struct msp_uart_data *d = p->private_data; + unsigned int iir = readb(p->membase + (UART_IIR << p->regshift)); + + if (serial8250_handle_irq(p, iir)) { + return 1; + } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { + /* + * The DesignWare APB UART has an Busy Detect (0x07) interrupt + * meaning an LCR write attempt occurred while the UART was + * busy. The interrupt must be cleared by reading the UART + * status register (USR) and the LCR re-written. + * + * Note: MSP reserves 0x20 bytes of address space for the UART + * and the USR is mapped in a separate block at an offset of + * 0xc0 from the start of the UART. + */ + (void)readb(p->membase + 0xc0); + writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift)); + + return 1; + } + + return 0; +} + void __init msp_serial_setup(void) { char *s; @@ -59,13 +109,22 @@ void __init msp_serial_setup(void) up.irq = MSP_INT_UART0; up.uartclk = uartclk; up.regshift = 2; - up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ + up.iotype = UPIO_MEM; up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; up.type = PORT_16550A; up.line = 0; - up.private_data = (void*)UART0_STATUS_REG; - if (early_serial_setup(&up)) - printk(KERN_ERR "Early serial init of port 0 failed\n"); + up.serial_out = msp_serial_out; + up.serial_in = msp_serial_in; + up.handle_irq = msp_serial_handle_irq; + up.private_data = kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL); + if (!up.private_data) { + pr_err("failed to allocate uart private data\n"); + return; + } + if (early_serial_setup(&up)) { + kfree(up.private_data); + pr_err("Early serial init of port 0 failed\n"); + } /* Initialize the second serial port, if one exists */ switch (mips_machtype) { @@ -88,6 +147,8 @@ void __init msp_serial_setup(void) up.irq = MSP_INT_UART1; up.line = 1; up.private_data = (void*)UART1_STATUS_REG; - if (early_serial_setup(&up)) - printk(KERN_ERR "Early serial init of port 1 failed\n"); + if (early_serial_setup(&up)) { + kfree(up.private_data); + pr_err("Early serial init of port 1 failed\n"); + } } diff --git a/arch/mips/pnx8550/common/int.c b/arch/mips/pnx8550/common/int.c index 6b93c81779c1..1ebe22bdadc8 100644 --- a/arch/mips/pnx8550/common/int.c +++ b/arch/mips/pnx8550/common/int.c @@ -167,7 +167,7 @@ static struct irq_chip level_irq_type = { static struct irqaction gic_action = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "GIC", }; diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index b4d08e4d2ea9..f72c336ea27b 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -155,32 +155,32 @@ static void __irq_entry indy_buserror_irq(void) static struct irqaction local0_cascade = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "local0 cascade", }; static struct irqaction local1_cascade = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "local1 cascade", }; static struct irqaction buserr = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "Bus Error", }; static struct irqaction map0_cascade = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "mapable0 cascade", }; #ifdef USE_LIO3_IRQ static struct irqaction map1_cascade = { .handler = no_action, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_NO_THREAD, .name = "mapable1 cascade", }; #define SGI_INTERRUPTS SGINT_END diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c index a7e5a6d917b1..3ab5b5d25b0a 100644 --- a/arch/mips/sni/rm200.c +++ b/arch/mips/sni/rm200.c @@ -359,6 +359,7 @@ void sni_rm200_init_8259A(void) static struct irqaction sni_rm200_irq2 = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; static struct resource sni_rm200_pic1_resource = { diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index e9f95dcde379..ba3cec3155df 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -321,7 +321,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) static u32 tx4939_get_eth_speed(struct net_device *dev) { struct ethtool_cmd cmd; - if (dev_ethtool_get_settings(dev, &cmd)) + if (__ethtool_get_settings(dev, &cmd)) return 100; /* default 100Mbps */ return ethtool_cmd_speed(&cmd); diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 70a3b85f3757..fad2bef432cd 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -34,6 +34,7 @@ static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; static struct irqaction cascade_irqaction = { .handler = no_action, .name = "cascade", + .flags = IRQF_NO_THREAD, }; int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 1f870340ebdd..438db84a1f7c 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -47,9 +47,6 @@ config GENERIC_CMOS_UPDATE config GENERIC_HWEIGHT def_bool y -config GENERIC_TIME - def_bool y - config GENERIC_CLOCKEVENTS def_bool y @@ -195,7 +192,7 @@ config SMP singleprocessor machines. On a singleprocessor machine, the kernel will run faster if you say N here. - See also <file:Documentation/i386/IO-APIC.txt>, + See also <file:Documentation/x86/i386/IO-APIC.txt>, <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at <http://www.tldp.org/docs.html#howto>. diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index ae435e1d5669..3e3620d9fc45 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -589,7 +589,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* was nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 2623d19f4f4c..2381df83bd00 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -260,7 +260,6 @@ void set_intr_level(int irq, u16 level) /* * mark an interrupt to be ACK'd after interrupt handlers have been run rather * than before - * - see Documentation/mn10300/features.txt */ void mn10300_set_lateack_irq_type(int irq) { diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 4558bafbd1a2..9460e1c266dd 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see Documentation/kbuild/config-language.txt. +# see Documentation/kbuild/kconfig-language.txt. # config OPENRISC diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h index 052f877b52a5..b206ba4608b2 100644 --- a/arch/openrisc/include/asm/dma-mapping.h +++ b/arch/openrisc/include/asm/dma-mapping.h @@ -18,7 +18,7 @@ #define __ASM_OPENRISC_DMA_MAPPING_H /* - * See Documentation/PCI/PCI-DMA-mapping.txt and + * See Documentation/DMA-API-HOWTO.txt and * Documentation/DMA-API.txt for documentation. * * This file is written with the intention of eventually moving over @@ -31,7 +31,6 @@ #define DMA_ERROR_CODE (~(dma_addr_t)0x0) -int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) @@ -47,6 +46,12 @@ dma_addr_t or1k_map_page(struct device *dev, struct page *page, void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); +int or1k_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs); +void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs); void or1k_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir); @@ -98,6 +103,51 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, debug_dma_unmap_page(dev, addr, size, dir, true); } +static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + int i, ents; + struct scatterlist *s; + + for_each_sg(sg, s, nents, i) + kmemcheck_mark_initialized(sg_virt(s), s->length); + BUG_ON(!valid_dma_direction(dir)); + ents = or1k_map_sg(dev, sg, nents, dir, NULL); + debug_dma_map_sg(dev, sg, nents, ents, dir); + + return ents; +} + +static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + BUG_ON(!valid_dma_direction(dir)); + debug_dma_unmap_sg(dev, sg, nents, dir); + or1k_unmap_sg(dev, sg, nents, dir, NULL); +} + +static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t addr; + + kmemcheck_mark_initialized(page_address(page) + offset, size); + BUG_ON(!valid_dma_direction(dir)); + addr = or1k_map_page(dev, page, offset, size, dir, NULL); + debug_dma_map_page(dev, page, offset, size, dir, addr, false); + + return addr; +} + +static inline void dma_unmap_page(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + BUG_ON(!valid_dma_direction(dir)); + or1k_unmap_page(dev, addr, size, dir, NULL); + debug_dma_unmap_page(dev, addr, size, dir, true); +} + static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) @@ -119,7 +169,12 @@ static inline void dma_sync_single_for_device(struct device *dev, static inline int dma_supported(struct device *dev, u64 dma_mask) { /* Support 32 bit DMA mask exclusively */ - return dma_mask == 0xffffffffULL; + return dma_mask == DMA_BIT_MASK(32); +} + +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; } static inline int dma_set_mask(struct device *dev, u64 dma_mask) diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h index 54a5c50132e3..b79c2b19afbe 100644 --- a/arch/openrisc/include/asm/sigcontext.h +++ b/arch/openrisc/include/asm/sigcontext.h @@ -23,16 +23,11 @@ /* This struct is saved by setup_frame in signal.c, to keep the current context while a signal handler is executed. It's restored by sys_sigreturn. - - To keep things simple, we use pt_regs here even though normally you just - specify the list of regs to save. Then we can use copy_from_user on the - entire regs instead of a bunch of get_user's as well... */ struct sigcontext { - struct pt_regs regs; /* needs to be first */ + struct user_regs_struct regs; /* needs to be first */ unsigned long oldmask; - unsigned long usp; /* usp before stacking this gunk on it */ }; #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c index 968d3ee477e3..f1c8ee2895d0 100644 --- a/arch/openrisc/kernel/dma.c +++ b/arch/openrisc/kernel/dma.c @@ -154,6 +154,33 @@ void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, /* Nothing special to do here... */ } +int or1k_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nents, i) { + s->dma_address = or1k_map_page(dev, sg_page(s), s->offset, + s->length, dir, NULL); + } + + return nents; +} + +void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nents, i) { + or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL); + } +} + void or1k_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) @@ -187,5 +214,4 @@ static int __init dma_init(void) return 0; } - fs_initcall(dma_init); diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 5f759c76834e..95207ab0c99e 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -52,31 +52,25 @@ struct rt_sigframe { static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { unsigned int err = 0; - unsigned long old_usp; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; - /* restore the regs from &sc->regs (same as sc, since regs is first) + /* + * Restore the regs from &sc->regs. * (sc is already checked for VERIFY_READ since the sigframe was * checked in sys_sigreturn previously) */ - - if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) + if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long))) + goto badframe; + if (__copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long))) + goto badframe; + if (__copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long))) goto badframe; /* make sure the SM-bit is cleared so user-mode cannot fool us */ regs->sr &= ~SPR_SR_SM; - /* restore the old USP as it was before we stacked the sc etc. - * (we cannot just pop the sigcontext since we aligned the sp and - * stuff after pushing it) - */ - - err |= __get_user(old_usp, &sc->usp); - - regs->sp = old_usp; - /* TODO: the other ports use regs->orig_XX to disable syscall checks * after this completes, but we don't use that mechanism. maybe we can * use it now ? @@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask) { int err = 0; - unsigned long usp = regs->sp; - /* copy the regs. they are first in sc so we can use sc directly */ + /* copy the regs */ - err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); + err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); + err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long)); + err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); /* then some other stuff */ err |= __put_user(mask, &sc->oldmask); - err |= __put_user(usp, &sc->usp); - return err; } diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index e077b0bf56ca..fdfd8be29e95 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -169,9 +169,7 @@ config 64BIT choice prompt "Kernel page size" - default PARISC_PAGE_SIZE_4KB if !64BIT - default PARISC_PAGE_SIZE_4KB if 64BIT -# default PARISC_PAGE_SIZE_16KB if 64BIT + default PARISC_PAGE_SIZE_4KB config PARISC_PAGE_SIZE_4KB bool "4KB" diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 890531e32fe8..467bbd510eac 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -5,7 +5,7 @@ #include <asm/cacheflush.h> #include <asm/scatterlist.h> -/* See Documentation/PCI/PCI-DMA-mapping.txt */ +/* See Documentation/DMA-API-HOWTO.txt */ struct hppa_dma_ops { int (*dma_supported)(struct device *dev, u64 mask); void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag); diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index a029f74a3c5c..d047edea2504 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -2,7 +2,7 @@ ** PARISC 1.1 Dynamic DMA mapping support. ** This implementation is for PA-RISC platforms that do not support ** I/O TLBs (aka DMA address translation hardware). -** See Documentation/PCI/PCI-DMA-mapping.txt for interface definitions. +** See Documentation/DMA-API-HOWTO.txt for interface definitions. ** ** (c) Copyright 1999,2000 Hewlett-Packard Company ** (c) Copyright 2000 Grant Grundler diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index e66366fd2abc..3735abd7f8f6 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -259,7 +259,7 @@ ENTRY_SAME(ni_syscall) /* query_module */ ENTRY_SAME(poll) /* structs contain pointers and an in_addr... */ - ENTRY_COMP(nfsservctl) + ENTRY_SAME(ni_syscall) /* was nfsservctl */ ENTRY_SAME(setresgid) /* 170 */ ENTRY_SAME(getresgid) ENTRY_SAME(prctl) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6926b61acfea..47682b67fd36 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -656,6 +656,8 @@ config SBUS config FSL_SOC bool + select HAVE_CAN_FLEXCAN if NET && CAN + select PPC_CLOCK if CAN_FLEXCAN config FSL_PCI bool diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts index 6b33b73a5ba0..d6c669c888e9 100644 --- a/arch/powerpc/boot/dts/p1010rdb.dts +++ b/arch/powerpc/boot/dts/p1010rdb.dts @@ -23,6 +23,8 @@ ethernet2 = &enet2; pci0 = &pci0; pci1 = &pci1; + can0 = &can0; + can1 = &can1; }; memory { @@ -169,14 +171,6 @@ }; }; - can0@1c000 { - fsl,flexcan-clock-source = "platform"; - }; - - can1@1d000 { - fsl,flexcan-clock-source = "platform"; - }; - usb@22000 { phy_type = "utmi"; }; diff --git a/arch/powerpc/boot/dts/p1010si.dtsi b/arch/powerpc/boot/dts/p1010si.dtsi index 7f51104f2e36..cabe0a453ae6 100644 --- a/arch/powerpc/boot/dts/p1010si.dtsi +++ b/arch/powerpc/boot/dts/p1010si.dtsi @@ -140,20 +140,18 @@ interrupt-parent = <&mpic>; }; - can0@1c000 { - compatible = "fsl,flexcan-v1.0"; + can0: can@1c000 { + compatible = "fsl,p1010-flexcan"; reg = <0x1c000 0x1000>; interrupts = <48 0x2>; interrupt-parent = <&mpic>; - fsl,flexcan-clock-divider = <2>; }; - can1@1d000 { - compatible = "fsl,flexcan-v1.0"; + can1: can@1d000 { + compatible = "fsl,p1010-flexcan"; reg = <0x1d000 0x1000>; interrupts = <61 0x2>; interrupt-parent = <&mpic>; - fsl,flexcan-clock-divider = <2>; }; L2: l2-cache-controller@20000 { diff --git a/arch/powerpc/boot/dts/p1023rds.dts b/arch/powerpc/boot/dts/p1023rds.dts index bfa96aa8f2ca..d9b776740a67 100644 --- a/arch/powerpc/boot/dts/p1023rds.dts +++ b/arch/powerpc/boot/dts/p1023rds.dts @@ -387,7 +387,7 @@ #size-cells = <1>; compatible = "cfi-flash"; reg = <0x0 0x0 0x02000000>; - bank-width = <1>; + bank-width = <2>; device-width = <1>; partition@0 { label = "ramdisk"; diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig index 4182c772340b..ed3bab72a834 100644 --- a/arch/powerpc/configs/40x/acadia_defconfig +++ b/arch/powerpc/configs/40x/acadia_defconfig @@ -44,12 +44,13 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 # CONFIG_MISC_DEVICES is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y CONFIG_MII=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 -CONFIG_IBM_NEW_EMAC_DEBUG=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 +CONFIG_IBM_EMAC_DEBUG=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig index 2dbb293163f5..17582a3420fb 100644 --- a/arch/powerpc/configs/40x/ep405_defconfig +++ b/arch/powerpc/configs/40x/ep405_defconfig @@ -42,8 +42,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig index ebeb4accad65..dba263c1d3a2 100644 --- a/arch/powerpc/configs/40x/hcu4_defconfig +++ b/arch/powerpc/configs/40x/hcu4_defconfig @@ -43,8 +43,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig index 532ea9d93a15..f2d4be936e08 100644 --- a/arch/powerpc/configs/40x/kilauea_defconfig +++ b/arch/powerpc/configs/40x/kilauea_defconfig @@ -51,10 +51,11 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 # CONFIG_MISC_DEVICES is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig index 3c142ac1b344..42b979355f9b 100644 --- a/arch/powerpc/configs/40x/makalu_defconfig +++ b/arch/powerpc/configs/40x/makalu_defconfig @@ -43,10 +43,11 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 # CONFIG_MISC_DEVICES is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig index ff57d4828ffc..aa1a4cac3708 100644 --- a/arch/powerpc/configs/40x/walnut_defconfig +++ b/arch/powerpc/configs/40x/walnut_defconfig @@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig index 3ed16d5c909d..329f9a3b892e 100644 --- a/arch/powerpc/configs/44x/arches_defconfig +++ b/arch/powerpc/configs/44x/arches_defconfig @@ -44,10 +44,11 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 # CONFIG_MISC_DEVICES is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig index b1b7d2c5c059..cef7d62560c4 100644 --- a/arch/powerpc/configs/44x/bamboo_defconfig +++ b/arch/powerpc/configs/44x/bamboo_defconfig @@ -32,8 +32,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig index 30a0a8e08fdd..20c8d26d7fc0 100644 --- a/arch/powerpc/configs/44x/bluestone_defconfig +++ b/arch/powerpc/configs/44x/bluestone_defconfig @@ -38,10 +38,11 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig index a46942aac695..d5be93e6e92d 100644 --- a/arch/powerpc/configs/44x/canyonlands_defconfig +++ b/arch/powerpc/configs/44x/canyonlands_defconfig @@ -49,10 +49,11 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 # CONFIG_MISC_DEVICES is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig index 07d77e51f1ba..f9269fc4ffcc 100644 --- a/arch/powerpc/configs/44x/ebony_defconfig +++ b/arch/powerpc/configs/44x/ebony_defconfig @@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/eiger_defconfig b/arch/powerpc/configs/44x/eiger_defconfig index 2ce7e9aff09e..9be089038fd7 100644 --- a/arch/powerpc/configs/44x/eiger_defconfig +++ b/arch/powerpc/configs/44x/eiger_defconfig @@ -55,10 +55,11 @@ CONFIG_FUSION=y CONFIG_FUSION_SAS=y CONFIG_I2O=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 CONFIG_E1000E=y # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/44x/icon_defconfig b/arch/powerpc/configs/44x/icon_defconfig index 18730ff9de7c..82f73035a7ce 100644 --- a/arch/powerpc/configs/44x/icon_defconfig +++ b/arch/powerpc/configs/44x/icon_defconfig @@ -56,8 +56,9 @@ CONFIG_FUSION_SAS=y CONFIG_FUSION_CTL=y CONFIG_FUSION_LOGGING=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_WLAN is not set diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig index 34c09144a699..109562c3c6be 100644 --- a/arch/powerpc/configs/44x/katmai_defconfig +++ b/arch/powerpc/configs/44x/katmai_defconfig @@ -42,8 +42,9 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_MACINTOSH_DRIVERS=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig index 01cc2b1a7f9a..48802811da76 100644 --- a/arch/powerpc/configs/44x/redwood_defconfig +++ b/arch/powerpc/configs/44x/redwood_defconfig @@ -53,11 +53,12 @@ CONFIG_FUSION=y CONFIG_FUSION_SAS=y CONFIG_I2O=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 -CONFIG_IBM_NEW_EMAC_DEBUG=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=256 +CONFIG_IBM_EMAC_TXB=256 +CONFIG_IBM_EMAC_DEBUG=y CONFIG_E1000E=y # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig index dfcffede16ad..ca088cd581af 100644 --- a/arch/powerpc/configs/44x/sam440ep_defconfig +++ b/arch/powerpc/configs/44x/sam440ep_defconfig @@ -44,8 +44,9 @@ CONFIG_ATA=y # CONFIG_SATA_PMP is not set CONFIG_SATA_SIL=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_INPUT_FF_MEMLESS=m diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig index 47e399f2892f..b7a653b626db 100644 --- a/arch/powerpc/configs/44x/sequoia_defconfig +++ b/arch/powerpc/configs/44x/sequoia_defconfig @@ -46,8 +46,9 @@ CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig index a6a002ed5681..30de97f158a4 100644 --- a/arch/powerpc/configs/44x/taishan_defconfig +++ b/arch/powerpc/configs/44x/taishan_defconfig @@ -40,8 +40,9 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_MACINTOSH_DRIVERS=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig index abf74dc1f79c..105bc56f4b2b 100644 --- a/arch/powerpc/configs/44x/warp_defconfig +++ b/arch/powerpc/configs/44x/warp_defconfig @@ -54,9 +54,10 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y CONFIG_MII=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_IBM_EMAC=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_INPUT is not set diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig index 980ff8f61fd4..3ff5a81c709f 100644 --- a/arch/powerpc/configs/85xx/p1023rds_defconfig +++ b/arch/powerpc/configs/85xx/p1023rds_defconfig @@ -171,3 +171,4 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_FSL_CAAM=y diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index 10562a5c65b9..4311d02a3bfd 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig @@ -185,3 +185,4 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_FSL_CAAM=y diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index d32283555b53..c92c204a204b 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig @@ -100,5 +100,8 @@ CONFIG_DEBUG_INFO=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_VIRQ_DEBUG=y CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_DEV_TALITOS=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index fcd85d2c72dc..a3467bfb7671 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig @@ -139,6 +139,7 @@ CONFIG_SND=y CONFIG_SND_INTEL8X0=y # CONFIG_SND_PPC is not set # CONFIG_SND_USB is not set +CONFIG_SND_SOC=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index 908c941fc24c..9693f6ed3da0 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig @@ -140,6 +140,7 @@ CONFIG_SND=y CONFIG_SND_INTEL8X0=y # CONFIG_SND_PPC is not set # CONFIG_SND_USB is not set +CONFIG_SND_SOC=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig index bfd634b5ada7..7cb703b948b1 100644 --- a/arch/powerpc/configs/ppc40x_defconfig +++ b/arch/powerpc/configs/ppc40x_defconfig @@ -50,8 +50,9 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=35000 CONFIG_XILINX_SYSACE=m CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set CONFIG_SERIO=m # CONFIG_SERIO_I8042 is not set diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index 47133202a625..6cdf1c0d2c8a 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig @@ -63,8 +63,9 @@ CONFIG_BLK_DEV_SD=m # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y CONFIG_TUN=m -CONFIG_NET_ETHERNET=y -CONFIG_IBM_NEW_EMAC=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_IBM_EMAC=y # CONFIG_INPUT is not set CONFIG_SERIO=m # CONFIG_SERIO_I8042 is not set diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index 0947b36e534c..5e0b6d511e14 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -196,7 +196,7 @@ static inline int qe_alive_during_sleep(void) /* Structure that defines QE firmware binary files. * - * See Documentation/powerpc/qe-firmware.txt for a description of these + * See Documentation/powerpc/qe_firmware.txt for a description of these * fields. */ struct qe_firmware { diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index f6736b7da463..fa0d27a400de 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -171,7 +171,7 @@ SYSCALL_SPU(setresuid) SYSCALL_SPU(getresuid) SYSCALL(ni_syscall) SYSCALL_SPU(poll) -COMPAT_SYS(nfsservctl) +SYSCALL(ni_syscall) SYSCALL_SPU(setresgid) SYSCALL_SPU(getresgid) COMPAT_SYS_SPU(prctl) diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index 93e05d1b34b2..5354ae91bdde 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h @@ -54,6 +54,7 @@ extern void __init udbg_init_40x_realmode(void); extern void __init udbg_init_cpm(void); extern void __init udbg_init_usbgecko(void); extern void __init udbg_init_wsp(void); +extern void __init udbg_init_ehv_bc(void); #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_UDBG_H */ diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index faa82c1f3f68..b4607a91d1f4 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -67,6 +67,8 @@ void __init udbg_early_init(void) udbg_init_usbgecko(); #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) udbg_init_wsp(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) + udbg_init_ehv_bc(); #endif #ifdef CONFIG_PPC_EARLY_DEBUG diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index d733d7ca939c..b5d87067a58b 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig @@ -130,21 +130,21 @@ config 405GP bool select IBM405_ERR77 select IBM405_ERR51 - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_ZMII config 405EP bool config 405EX bool - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII config 405EZ bool - select IBM_NEW_EMAC_NO_FLOW_CTRL - select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT - select IBM_NEW_EMAC_MAL_COMMON_ERR + select IBM_EMAC_NO_FLOW_CTRL + select IBM_EMAC_MAL_CLR_ICINTSTAT + select IBM_EMAC_MAL_COMMON_ERR config 405GPR bool diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index e958b6f48ec2..762322ce24a9 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -23,7 +23,7 @@ config BLUESTONE default n select PPC44x_SIMPLE select APM821xx - select IBM_NEW_EMAC_RGMII + select IBM_EMAC_RGMII help This option enables support for the APM APM821xx Evaluation board. @@ -122,8 +122,8 @@ config CANYONLANDS select PPC4xx_PCI_EXPRESS select PCI_MSI select PPC4xx_MSI - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII help This option enables support for the AMCC PPC460EX evaluation board. @@ -135,8 +135,8 @@ config GLACIER select 460EX # Odd since it uses 460GT but the effects are the same select PCI select PPC4xx_PCI_EXPRESS - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII help This option enables support for the AMCC PPC460GT evaluation board. @@ -161,7 +161,7 @@ config EIGER select 460SX select PCI select PPC4xx_PCI_EXPRESS - select IBM_NEW_EMAC_RGMII + select IBM_EMAC_RGMII help This option enables support for the AMCC PPC460SX evaluation board. @@ -260,59 +260,59 @@ config 440EP bool select PPC_FPU select IBM440EP_ERR42 - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_ZMII select USB_ARCH_HAS_OHCI config 440EPX bool select PPC_FPU - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII config 440GRX bool - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII config 440GP bool - select IBM_NEW_EMAC_ZMII + select IBM_EMAC_ZMII config 440GX bool - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII #test only - select IBM_NEW_EMAC_TAH #test only + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII #test only + select IBM_EMAC_TAH #test only config 440SP bool config 440SPe bool - select IBM_NEW_EMAC_EMAC4 + select IBM_EMAC_EMAC4 config 460EX bool select PPC_FPU - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_TAH + select IBM_EMAC_EMAC4 + select IBM_EMAC_TAH config 460SX bool select PPC_FPU - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII - select IBM_NEW_EMAC_TAH + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII + select IBM_EMAC_TAH config APM821xx bool select PPC_FPU - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_TAH + select IBM_EMAC_EMAC4 + select IBM_EMAC_TAH # 44x errata/workaround config symbols, selected by the CPU models above config IBM440EP_ERR42 diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 498534cd5265..12f5932dadc9 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -80,7 +80,7 @@ config P1010_RDB config P1022_DS bool "Freescale P1022 DS" select DEFAULT_UIMAGE - select CONFIG_PHYS_64BIT # The DTS has 36-bit addresses + select PHYS_64BIT # The DTS has 36-bit addresses select SWIOTLB help This option enables support for the Freescale P1022DS reference board. diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 67d5009b4e86..2e7ff0c5cf42 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -17,10 +17,10 @@ config PPC_CELL_NATIVE select PPC_CELL_COMMON select MPIC select PPC_IO_WORKAROUNDS - select IBM_NEW_EMAC_EMAC4 - select IBM_NEW_EMAC_RGMII - select IBM_NEW_EMAC_ZMII #test only - select IBM_NEW_EMAC_TAH #test only + select IBM_EMAC_EMAC4 + select IBM_EMAC_RGMII + select IBM_EMAC_ZMII #test only + select IBM_EMAC_TAH #test only default n config PPC_IBM_CELL_BLADE diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index 613070e9ddbe..f1eebcae9bf0 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c @@ -77,7 +77,7 @@ static void __init storcenter_setup_arch(void) } /* - * Interrupt setup and service. Interrrupts on the turbostation come + * Interrupt setup and service. Interrupts on the turbostation come * from the four PCI slots plus onboard 8241 devices: I2C, DUART. */ static void __init storcenter_init_IRQ(void) diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 5cc83851ad06..31a7d3a7ce25 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -561,6 +561,20 @@ static struct pci_ops u4_pcie_pci_ops = .write = u4_pcie_write_config, }; +static void __devinit pmac_pci_fixup_u4_of_node(struct pci_dev *dev) +{ + /* Apple's device-tree "hides" the root complex virtual P2P bridge + * on U4. However, Linux sees it, causing the PCI <-> OF matching + * code to fail to properly match devices below it. This works around + * it by setting the node of the bridge to point to the PHB node, + * which is not entirely correct but fixes the matching code and + * doesn't break anything else. It's also the simplest possible fix. + */ + if (dev->dev.of_node == NULL) + dev->dev.of_node = pcibios_get_phb_of_node(dev->bus); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, 0x5b, pmac_pci_fixup_u4_of_node); + #endif /* CONFIG_PPC64 */ #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 2de8551df40f..c65f75aa7ff7 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -54,6 +54,7 @@ #define ODSR_CLEAR 0x1c00 #define LTLEECSR_ENABLE_ALL 0xFFC000FC #define ESCSR_CLEAR 0x07120204 +#define IECSR_CLEAR 0x80000000 #define RIO_PORT1_EDCSR 0x0640 #define RIO_PORT2_EDCSR 0x0680 @@ -1089,11 +1090,11 @@ static void port_error_handler(struct rio_mport *port, int offset) if (offset == 0) { out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), 0); + out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR); out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR); } else { out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0); - out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), 0); + out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR); out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR); } } diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 904c6cbaf45b..3363fbc964f8 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -382,7 +382,7 @@ static void qe_upload_microcode(const void *base, /* * Upload a microcode to the I-RAM at a specific address. * - * See Documentation/powerpc/qe-firmware.txt for information on QE microcode + * See Documentation/powerpc/qe_firmware.txt for information on QE microcode * uploading. * * Currently, only version 1 is supported, so the 'version' field must be diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 984cd2029158..3330feca7502 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -47,7 +47,7 @@ struct uic { int index; int dcrbase; - spinlock_t lock; + raw_spinlock_t lock; /* The remapper for this UIC */ struct irq_host *irqhost; @@ -61,14 +61,14 @@ static void uic_unmask_irq(struct irq_data *d) u32 er, sr; sr = 1 << (31-src); - spin_lock_irqsave(&uic->lock, flags); + raw_spin_lock_irqsave(&uic->lock, flags); /* ack level-triggered interrupts here */ if (irqd_is_level_type(d)) mtdcr(uic->dcrbase + UIC_SR, sr); er = mfdcr(uic->dcrbase + UIC_ER); er |= sr; mtdcr(uic->dcrbase + UIC_ER, er); - spin_unlock_irqrestore(&uic->lock, flags); + raw_spin_unlock_irqrestore(&uic->lock, flags); } static void uic_mask_irq(struct irq_data *d) @@ -78,11 +78,11 @@ static void uic_mask_irq(struct irq_data *d) unsigned long flags; u32 er; - spin_lock_irqsave(&uic->lock, flags); + raw_spin_lock_irqsave(&uic->lock, flags); er = mfdcr(uic->dcrbase + UIC_ER); er &= ~(1 << (31 - src)); mtdcr(uic->dcrbase + UIC_ER, er); - spin_unlock_irqrestore(&uic->lock, flags); + raw_spin_unlock_irqrestore(&uic->lock, flags); } static void uic_ack_irq(struct irq_data *d) @@ -91,9 +91,9 @@ static void uic_ack_irq(struct irq_data *d) unsigned int src = irqd_to_hwirq(d); unsigned long flags; - spin_lock_irqsave(&uic->lock, flags); + raw_spin_lock_irqsave(&uic->lock, flags); mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); - spin_unlock_irqrestore(&uic->lock, flags); + raw_spin_unlock_irqrestore(&uic->lock, flags); } static void uic_mask_ack_irq(struct irq_data *d) @@ -104,7 +104,7 @@ static void uic_mask_ack_irq(struct irq_data *d) u32 er, sr; sr = 1 << (31-src); - spin_lock_irqsave(&uic->lock, flags); + raw_spin_lock_irqsave(&uic->lock, flags); er = mfdcr(uic->dcrbase + UIC_ER); er &= ~sr; mtdcr(uic->dcrbase + UIC_ER, er); @@ -118,7 +118,7 @@ static void uic_mask_ack_irq(struct irq_data *d) */ if (!irqd_is_level_type(d)) mtdcr(uic->dcrbase + UIC_SR, sr); - spin_unlock_irqrestore(&uic->lock, flags); + raw_spin_unlock_irqrestore(&uic->lock, flags); } static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) @@ -152,7 +152,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) mask = ~(1 << (31 - src)); - spin_lock_irqsave(&uic->lock, flags); + raw_spin_lock_irqsave(&uic->lock, flags); tr = mfdcr(uic->dcrbase + UIC_TR); pr = mfdcr(uic->dcrbase + UIC_PR); tr = (tr & mask) | (trigger << (31-src)); @@ -161,7 +161,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) mtdcr(uic->dcrbase + UIC_PR, pr); mtdcr(uic->dcrbase + UIC_TR, tr); - spin_unlock_irqrestore(&uic->lock, flags); + raw_spin_unlock_irqrestore(&uic->lock, flags); return 0; } @@ -254,7 +254,7 @@ static struct uic * __init uic_init_one(struct device_node *node) if (! uic) return NULL; /* FIXME: panic? */ - spin_lock_init(&uic->lock); + raw_spin_lock_init(&uic->lock); indexp = of_get_property(node, "cell-index", &len); if (!indexp || (len != sizeof(u32))) { printk(KERN_ERR "uic: Device node %s has missing or invalid " diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ed5cb5af5281..6b99fc3f9b63 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -91,6 +91,7 @@ config S390 select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select HAVE_RCU_TABLE_FREE if SMP + select ARCH_SAVE_PAGE_KEYS if HIBERNATION select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_LOCK diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 6023c6dc1fb7..74c8f5e76ce4 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -562,10 +562,9 @@ static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size) void *base; buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); - base = vmalloc(buf_size); + base = vzalloc(buf_size); if (!base) return -ENOMEM; - memset(base, 0, buf_size); d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr); rc = diag204_do_store(d204->buf, diag204_buf_pages); if (rc) { diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 64b61bf72e93..547f1a6a35d4 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -188,7 +188,8 @@ extern char elf_platform[]; #define SET_PERSONALITY(ex) \ do { \ if (personality(current->personality) != PER_LINUX32) \ - set_personality(PER_LINUX); \ + set_personality(PER_LINUX | \ + (current->personality & ~PER_MASK)); \ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ set_thread_flag(TIF_31BIT); \ else \ diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 519eb5f187ef..c0cb794bb365 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -658,12 +658,14 @@ static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) * struct gmap_struct - guest address space * @mm: pointer to the parent mm_struct * @table: pointer to the page directory + * @asce: address space control element for gmap page table * @crst_list: list of all crst tables used in the guest address space */ struct gmap { struct list_head list; struct mm_struct *mm; unsigned long *table; + unsigned long asce; struct list_head crst_list; }; diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 15c97625df8d..21993623da9a 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -123,6 +123,40 @@ struct slibe { }; /** + * struct qaob - queue asynchronous operation block + * @res0: reserved parameters + * @res1: reserved parameter + * @res2: reserved parameter + * @res3: reserved parameter + * @aorc: asynchronous operation return code + * @flags: internal flags + * @cbtbs: control block type + * @sb_count: number of storage blocks + * @sba: storage block element addresses + * @dcount: size of storage block elements + * @user0: user defineable value + * @res4: reserved paramater + * @user1: user defineable value + * @user2: user defineable value + */ +struct qaob { + u64 res0[6]; + u8 res1; + u8 res2; + u8 res3; + u8 aorc; + u8 flags; + u16 cbtbs; + u8 sb_count; + u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER]; + u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER]; + u64 user0; + u64 res4[2]; + u64 user1; + u64 user2; +} __attribute__ ((packed, aligned(256))); + +/** * struct slib - storage list information block (SLIB) * @nsliba: next SLIB address (if any) * @sla: SL address @@ -225,6 +259,41 @@ struct slsb { #define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 #define CHSC_AC2_DATA_DIV_ENABLED 0x0002 +/** + * struct qdio_outbuf_state - SBAL related asynchronous operation information + * (for communication with upper layer programs) + * (only required for use with completion queues) + * @flags: flags indicating state of buffer + * @aob: pointer to QAOB used for the particular SBAL + * @user: pointer to upper layer program's state information related to SBAL + * (stored in user1 data of QAOB) + */ +struct qdio_outbuf_state { + u8 flags; + struct qaob *aob; + void *user; +}; + +#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00 +#define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01 + +#define CHSC_AC1_INITIATE_INPUTQ 0x80 + + +/* qdio adapter-characteristics-1 flag */ +#define AC1_SIGA_INPUT_NEEDED 0x40 /* process input queues */ +#define AC1_SIGA_OUTPUT_NEEDED 0x20 /* process output queues */ +#define AC1_SIGA_SYNC_NEEDED 0x10 /* ask hypervisor to sync */ +#define AC1_AUTOMATIC_SYNC_ON_THININT 0x08 /* set by hypervisor */ +#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI 0x04 /* set by hypervisor */ +#define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */ +#define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */ + +#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 +#define CHSC_AC2_DATA_DIV_ENABLED 0x0002 + +#define CHSC_AC3_FORMAT2_CQ_AVAILABLE 0x8000 + struct qdio_ssqd_desc { u8 flags; u8:8; @@ -243,8 +312,7 @@ struct qdio_ssqd_desc { u64 sch_token; u8 mro; u8 mri; - u8:8; - u8 sbalic; + u16 qdioac3; u16:16; u8:8; u8 mmwc; @@ -280,9 +348,11 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, * @no_output_qs: number of output queues * @input_handler: handler to be called for input queues * @output_handler: handler to be called for output queues + * @queue_start_poll: polling handlers (one per input queue or NULL) * @int_parm: interruption parameter * @input_sbal_addr_array: address of no_input_qs * 128 pointers * @output_sbal_addr_array: address of no_output_qs * 128 pointers + * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL) */ struct qdio_initialize { struct ccw_device *cdev; @@ -297,11 +367,12 @@ struct qdio_initialize { unsigned int no_output_qs; qdio_handler_t *input_handler; qdio_handler_t *output_handler; - void (*queue_start_poll) (struct ccw_device *, int, unsigned long); + void (**queue_start_poll) (struct ccw_device *, int, unsigned long); int scan_threshold; unsigned long int_parm; void **input_sbal_addr_array; void **output_sbal_addr_array; + struct qdio_outbuf_state *output_sbal_state_array; }; #define QDIO_STATE_INACTIVE 0x00000002 /* after qdio_cleanup */ @@ -316,6 +387,7 @@ struct qdio_initialize { extern int qdio_allocate(struct qdio_initialize *); extern int qdio_establish(struct qdio_initialize *); extern int qdio_activate(struct ccw_device *); +extern void qdio_release_aob(struct qaob *); extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int, unsigned int); extern int qdio_start_irq(struct ccw_device *, int); diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 532fd4322156..2b45591e1582 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -10,6 +10,7 @@ #include <linux/sched.h> #include <asm/vdso.h> #include <asm/sigp.h> +#include <asm/pgtable.h> /* * Make sure that the compiler is new enough. We want a compiler that @@ -126,6 +127,7 @@ int main(void) DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack)); DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack)); DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); + DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); @@ -151,6 +153,7 @@ int main(void) DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp)); + DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); #endif /* CONFIG_32BIT */ return 0; } diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 08ab9aa6a0d5..7526db6bf501 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -665,12 +665,6 @@ ENTRY(sys32_poll_wrapper) lgfr %r4,%r4 # long jg sys_poll # branch to system call -ENTRY(compat_sys_nfsservctl_wrapper) - lgfr %r2,%r2 # int - llgtr %r3,%r3 # struct compat_nfsctl_arg* - llgtr %r4,%r4 # union compat_nfsctl_res* - jg compat_sys_nfsservctl # branch to system call - ENTRY(sys32_setresgid16_wrapper) llgfr %r2,%r2 # __kernel_old_gid_emu31_t llgfr %r3,%r3 # __kernel_old_gid_emu31_t diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 068f8465c4ee..f297456dba7a 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -396,17 +396,19 @@ static __init void detect_machine_facilities(void) static __init void rescue_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD + unsigned long min_initrd_addr = (unsigned long) _end + (4UL << 20); /* - * Move the initrd right behind the bss section in case it starts - * within the bss section. So we don't overwrite it when the bss - * section gets cleared. + * Just like in case of IPL from VM reader we make sure there is a + * gap of 4MB between end of kernel and start of initrd. + * That way we can also be sure that saving an NSS will succeed, + * which however only requires different segments. */ if (!INITRD_START || !INITRD_SIZE) return; - if (INITRD_START >= (unsigned long) __bss_stop) + if (INITRD_START >= min_initrd_addr) return; - memmove(__bss_stop, (void *) INITRD_START, INITRD_SIZE); - INITRD_START = (unsigned long) __bss_stop; + memmove((void *) min_initrd_addr, (void *) INITRD_START, INITRD_SIZE); + INITRD_START = min_initrd_addr; #endif } diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 5f729d627cef..713da0760538 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -1076,6 +1076,11 @@ sie_loop: lg %r14,__LC_THREAD_INFO # pointer thread_info struct tm __TI_flags+7(%r14),_TIF_EXIT_SIE jnz sie_exit + lg %r14,__LC_GMAP # get gmap pointer + ltgr %r14,%r14 + jz sie_gmap + lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce +sie_gmap: lg %r14,__SF_EMPTY(%r15) # get control block pointer SPP __SF_EMPTY(%r15) # set guest id sie 0(%r14) @@ -1083,6 +1088,7 @@ sie_done: SPP __LC_CMF_HPP # set host id lg %r14,__LC_THREAD_INFO # pointer thread_info struct sie_exit: + lctlg %c1,%c1,__LC_USER_ASCE # load primary asce ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) lg %r14,__SF_EMPTY+8(%r15) # load guest register save area stmg %r0,%r13,0(%r14) # save guest gprs 0-13 diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 04361d5a4279..48c710206366 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1220,7 +1220,7 @@ static int __init reipl_fcp_init(void) /* sysfs: create fcp kset for mixing attr group and bin attrs */ reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL, &reipl_kset->kobj); - if (!reipl_kset) { + if (!reipl_fcp_kset) { free_page((unsigned long) reipl_block_fcp); return -ENOMEM; } @@ -1618,7 +1618,8 @@ static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR, static void stop_run(struct shutdown_trigger *trigger) { - if (strcmp(trigger->name, ON_PANIC_STR) == 0) + if (strcmp(trigger->name, ON_PANIC_STR) == 0 || + strcmp(trigger->name, ON_RESTART_STR) == 0) disabled_wait((unsigned long) __builtin_return_address(0)); while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) cpu_relax(); @@ -1717,7 +1718,7 @@ static void do_panic(void) /* on restart */ static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR, - &reipl_action}; + &stop_action}; static ssize_t on_restart_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c index cf9e5c6d5527..b6f9afed74ec 100644 --- a/arch/s390/kernel/suspend.c +++ b/arch/s390/kernel/suspend.c @@ -7,6 +7,7 @@ */ #include <linux/pfn.h> +#include <linux/mm.h> #include <asm/system.h> /* @@ -14,6 +15,123 @@ */ extern const void __nosave_begin, __nosave_end; +/* + * The restore of the saved pages in an hibernation image will set + * the change and referenced bits in the storage key for each page. + * Overindication of the referenced bits after an hibernation cycle + * does not cause any harm but the overindication of the change bits + * would cause trouble. + * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each + * page to the most significant byte of the associated page frame + * number in the hibernation image. + */ + +/* + * Key storage is allocated as a linked list of pages. + * The size of the keys array is (PAGE_SIZE - sizeof(long)) + */ +struct page_key_data { + struct page_key_data *next; + unsigned char data[]; +}; + +#define PAGE_KEY_DATA_SIZE (PAGE_SIZE - sizeof(struct page_key_data *)) + +static struct page_key_data *page_key_data; +static struct page_key_data *page_key_rp, *page_key_wp; +static unsigned long page_key_rx, page_key_wx; + +/* + * For each page in the hibernation image one additional byte is + * stored in the most significant byte of the page frame number. + * On suspend no additional memory is required but on resume the + * keys need to be memorized until the page data has been restored. + * Only then can the storage keys be set to their old state. + */ +unsigned long page_key_additional_pages(unsigned long pages) +{ + return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE); +} + +/* + * Free page_key_data list of arrays. + */ +void page_key_free(void) +{ + struct page_key_data *pkd; + + while (page_key_data) { + pkd = page_key_data; + page_key_data = pkd->next; + free_page((unsigned long) pkd); + } +} + +/* + * Allocate page_key_data list of arrays with enough room to store + * one byte for each page in the hibernation image. + */ +int page_key_alloc(unsigned long pages) +{ + struct page_key_data *pk; + unsigned long size; + + size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE); + while (size--) { + pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL); + if (!pk) { + page_key_free(); + return -ENOMEM; + } + pk->next = page_key_data; + page_key_data = pk; + } + page_key_rp = page_key_wp = page_key_data; + page_key_rx = page_key_wx = 0; + return 0; +} + +/* + * Save the storage key into the upper 8 bits of the page frame number. + */ +void page_key_read(unsigned long *pfn) +{ + unsigned long addr; + + addr = (unsigned long) page_address(pfn_to_page(*pfn)); + *(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr); +} + +/* + * Extract the storage key from the upper 8 bits of the page frame number + * and store it in the page_key_data list of arrays. + */ +void page_key_memorize(unsigned long *pfn) +{ + page_key_wp->data[page_key_wx] = *(unsigned char *) pfn; + *(unsigned char *) pfn = 0; + if (++page_key_wx < PAGE_KEY_DATA_SIZE) + return; + page_key_wp = page_key_wp->next; + page_key_wx = 0; +} + +/* + * Get the next key from the page_key_data list of arrays and set the + * storage key of the page referred by @address. If @address refers to + * a "safe" page the swsusp_arch_resume code will transfer the storage + * key from the buffer page to the original page. + */ +void page_key_write(void *address) +{ + page_set_storage_key((unsigned long) address, + page_key_rp->data[page_key_rx], 0); + if (++page_key_rx >= PAGE_KEY_DATA_SIZE) + return; + page_key_rp = page_key_rp->next; + page_key_rx = 0; +} + int pfn_is_nosave(unsigned long pfn) { unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 51bcdb50a230..acb78cdee896 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -136,11 +136,14 @@ ENTRY(swsusp_arch_resume) 0: lg %r2,8(%r1) lg %r4,0(%r1) + iske %r0,%r4 lghi %r3,PAGE_SIZE lghi %r5,PAGE_SIZE 1: mvcle %r2,%r4,0 jo 1b + lg %r2,8(%r1) + sske %r0,%r2 lg %r1,16(%r1) ltgr %r1,%r1 jnz 0b diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 6ee39ef8fe4a..73eb08c874fb 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -177,7 +177,7 @@ SYSCALL(sys_getresuid16,sys_ni_syscall,sys32_getresuid16_wrapper) /* 165 old get NI_SYSCALL /* for vm86 */ NI_SYSCALL /* old sys_query_module */ SYSCALL(sys_poll,sys_poll,sys32_poll_wrapper) -SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper) +NI_SYSCALL /* old nfsservctl */ SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index dff933065ab6..8d65bd0383fc 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -109,10 +109,14 @@ static void fixup_clock_comparator(unsigned long long delta) set_clock_comparator(S390_lowcore.clock_comparator); } -static int s390_next_event(unsigned long delta, +static int s390_next_ktime(ktime_t expires, struct clock_event_device *evt) { - S390_lowcore.clock_comparator = get_clock() + delta; + u64 nsecs; + + nsecs = ktime_to_ns(ktime_sub(expires, ktime_get_monotonic_offset())); + do_div(nsecs, 125); + S390_lowcore.clock_comparator = TOD_UNIX_EPOCH + (nsecs << 9); set_clock_comparator(S390_lowcore.clock_comparator); return 0; } @@ -137,14 +141,15 @@ void init_cpu_timer(void) cpu = smp_processor_id(); cd = &per_cpu(comparators, cpu); cd->name = "comparator"; - cd->features = CLOCK_EVT_FEAT_ONESHOT; + cd->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_KTIME; cd->mult = 16777; cd->shift = 12; cd->min_delta_ns = 1; cd->max_delta_ns = LONG_MAX; cd->rating = 400; cd->cpumask = cpumask_of(cpu); - cd->set_next_event = s390_next_event; + cd->set_next_ktime = s390_next_ktime; cd->set_mode = s390_set_mode; clockevents_register_device(cd); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index f17296e4fc89..dc2b580e27bc 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -123,6 +123,7 @@ int kvm_dev_ioctl_check_extension(long ext) switch (ext) { case KVM_CAP_S390_PSW: + case KVM_CAP_S390_GMAP: r = 1; break; default: @@ -263,10 +264,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK; restore_fp_regs(&vcpu->arch.guest_fpregs); restore_access_regs(vcpu->arch.guest_acrs); + gmap_enable(vcpu->arch.gmap); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { + gmap_disable(vcpu->arch.gmap); save_fp_regs(&vcpu->arch.guest_fpregs); save_access_regs(vcpu->arch.guest_acrs); restore_fp_regs(&vcpu->arch.host_fpregs); @@ -461,7 +464,6 @@ static void __vcpu_run(struct kvm_vcpu *vcpu) local_irq_disable(); kvm_guest_enter(); local_irq_enable(); - gmap_enable(vcpu->arch.gmap); VCPU_EVENT(vcpu, 6, "entering sie flags %x", atomic_read(&vcpu->arch.sie_block->cpuflags)); if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) { @@ -470,7 +472,6 @@ static void __vcpu_run(struct kvm_vcpu *vcpu) } VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", vcpu->arch.sie_block->icptcode); - gmap_disable(vcpu->arch.gmap); local_irq_disable(); kvm_guest_exit(); local_irq_enable(); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 4d1f2bce87b3..5d56c2b95b14 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -160,6 +160,8 @@ struct gmap *gmap_alloc(struct mm_struct *mm) table = (unsigned long *) page_to_phys(page); crst_table_init(table, _REGION1_ENTRY_EMPTY); gmap->table = table; + gmap->asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH | + _ASCE_USER_BITS | __pa(table); list_add(&gmap->list, &mm->context.gmap_list); return gmap; @@ -240,10 +242,6 @@ EXPORT_SYMBOL_GPL(gmap_free); */ void gmap_enable(struct gmap *gmap) { - /* Load primary space page table origin. */ - S390_lowcore.user_asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH | - _ASCE_USER_BITS | __pa(gmap->table); - asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) ); S390_lowcore.gmap = (unsigned long) gmap; } EXPORT_SYMBOL_GPL(gmap_enable); @@ -254,10 +252,6 @@ EXPORT_SYMBOL_GPL(gmap_enable); */ void gmap_disable(struct gmap *gmap) { - /* Load primary space page table origin. */ - S390_lowcore.user_asce = - gmap->mm->context.asce_bits | __pa(gmap->mm->pgd); - asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) ); S390_lowcore.gmap = 0UL; } EXPORT_SYMBOL_GPL(gmap_disable); @@ -309,15 +303,15 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len) /* Walk the guest addr space page table */ table = gmap->table + (((to + off) >> 53) & 0x7ff); if (*table & _REGION_ENTRY_INV) - return 0; + goto out; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); table = table + (((to + off) >> 42) & 0x7ff); if (*table & _REGION_ENTRY_INV) - return 0; + goto out; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); table = table + (((to + off) >> 31) & 0x7ff); if (*table & _REGION_ENTRY_INV) - return 0; + goto out; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); table = table + (((to + off) >> 20) & 0x7ff); @@ -325,6 +319,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len) flush |= gmap_unlink_segment(gmap, table); *table = _SEGMENT_ENTRY_INV; } +out: up_read(&gmap->mm->mmap_sem); if (flush) gmap_flush_tlb(gmap); diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index b97baf81a87b..2d3679b2447f 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -123,7 +123,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, struct perf_event; struct perf_sample_data; -extern void ptrace_triggered(struct perf_event *bp, int nmi, +extern void ptrace_triggered(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs); #define task_pt_regs(task) \ diff --git a/arch/sh/include/asm/sh_eth.h b/arch/sh/include/asm/sh_eth.h deleted file mode 100644 index 0f325da0f923..000000000000 --- a/arch/sh/include/asm/sh_eth.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __ASM_SH_ETH_H__ -#define __ASM_SH_ETH_H__ - -#include <linux/phy.h> - -enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN}; -enum { - SH_ETH_REG_GIGABIT, - SH_ETH_REG_FAST_SH4, - SH_ETH_REG_FAST_SH3_SH2 -}; - -struct sh_eth_plat_data { - int phy; - int edmac_endian; - int register_type; - phy_interface_t phy_interface; - void (*set_mdio_gate)(unsigned long addr); - - unsigned char mac_addr[6]; - unsigned no_ether_link:1; - unsigned ether_link_active_low:1; -}; - -#endif diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index e915deafac89..05559295d2ca 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -15,6 +15,7 @@ #include <linux/serial_sci.h> #include <linux/io.h> #include <linux/mm.h> +#include <linux/dma-mapping.h> #include <linux/sh_timer.h> #include <linux/sh_dma.h> diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 32114e0941ae..db4ecd731a00 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -22,7 +22,7 @@ #include <linux/atomic.h> #include <asm/smp.h> -static void (*pm_idle)(void); +void (*pm_idle)(void); static int hlt_counter; diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 39b051de4c7c..293e39c59c00 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -185,7 +185,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* vm86 */ .long sys_ni_syscall /* old "query_module" */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* was nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 089c4d825d08..ceb34b94afa9 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -189,7 +189,7 @@ sys_call_table: .long sys_ni_syscall /* vm86 */ .long sys_ni_syscall /* old "query_module" */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* was nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index d9006f8ffc14..7bbef95c9d1b 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs, break; } break; + + case 9: /* mov.w @(disp,PC),Rn */ + srcu = (unsigned char __user *)regs->pc; + srcu += 4; + srcu += (instruction & 0x00FF) << 1; + dst = (unsigned char *)rn; + *(unsigned long *)dst = 0; + +#if !defined(__LITTLE_ENDIAN__) + dst += 2; +#endif + + if (ma->from(dst, srcu, 2)) + goto fetch_fault; + sign_extend(2, dst); + ret = 0; + break; + + case 0xd: /* mov.l @(disp,PC),Rn */ + srcu = (unsigned char __user *)(regs->pc & ~0x3); + srcu += 4; + srcu += (instruction & 0x00FF) << 2; + dst = (unsigned char *)rn; + *(unsigned long *)dst = 0; + + if (ma->from(dst, srcu, 4)) + goto fetch_fault; + ret = 0; + break; } return ret; @@ -466,6 +495,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, case 0x0500: /* mov.w @(disp,Rm),R0 */ goto simple; case 0x0B00: /* bf lab - no delayslot*/ + ret = 0; break; case 0x0F00: /* bf/s lab */ ret = handle_delayslot(regs, instruction, ma); @@ -479,6 +509,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, } break; case 0x0900: /* bt lab - no delayslot */ + ret = 0; break; case 0x0D00: /* bt/s lab */ ret = handle_delayslot(regs, instruction, ma); @@ -494,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, } break; + case 0x9000: /* mov.w @(disp,Rm),Rn */ + goto simple; + case 0xA000: /* bra label */ ret = handle_delayslot(regs, instruction, ma); if (ret==0) @@ -507,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, regs->pc += SH_PC_12BIT_OFFSET(instruction); } break; + + case 0xD000: /* mov.l @(disp,Rm),Rn */ + goto simple; } return ret; diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index 1407c07bdade..f6ae2b2b6870 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -280,7 +280,7 @@ static inline unsigned long srmmu_hwprobe(unsigned long vaddr) return retval; } #else -#define srmmu_hwprobe(addr) (srmmu_swprobe(addr, 0) & SRMMU_PTE_PMASK) +#define srmmu_hwprobe(addr) srmmu_swprobe(addr, 0) #endif static inline int diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h index a1607d180354..69914d748130 100644 --- a/arch/sparc/include/asm/sigcontext.h +++ b/arch/sparc/include/asm/sigcontext.h @@ -45,6 +45,19 @@ typedef struct { int si_mask; } __siginfo32_t; +#define __SIGC_MAXWIN 7 + +typedef struct { + unsigned long locals[8]; + unsigned long ins[8]; +} __siginfo_reg_window; + +typedef struct { + int wsaved; + __siginfo_reg_window reg_window[__SIGC_MAXWIN]; + unsigned long rwbuf_stkptrs[__SIGC_MAXWIN]; +} __siginfo_rwin_t; + #ifdef CONFIG_SPARC64 typedef struct { unsigned int si_float_regs [64]; @@ -73,6 +86,7 @@ struct sigcontext { unsigned long ss_size; } sigc_stack; unsigned long sigc_mask; + __siginfo_rwin_t * sigc_rwin_save; }; #else diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h index 55a17c6efeb8..d06a26601753 100644 --- a/arch/sparc/include/asm/spitfire.h +++ b/arch/sparc/include/asm/spitfire.h @@ -43,6 +43,8 @@ #define SUN4V_CHIP_NIAGARA1 0x01 #define SUN4V_CHIP_NIAGARA2 0x02 #define SUN4V_CHIP_NIAGARA3 0x03 +#define SUN4V_CHIP_NIAGARA4 0x04 +#define SUN4V_CHIP_NIAGARA5 0x05 #define SUN4V_CHIP_UNKNOWN 0xff #ifndef __ASSEMBLY__ diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h index 9ed6ff679ab7..ee8edc68423e 100644 --- a/arch/sparc/include/asm/xor_64.h +++ b/arch/sparc/include/asm/xor_64.h @@ -66,6 +66,8 @@ static struct xor_block_template xor_block_niagara = { ((tlb_type == hypervisor && \ (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \ sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \ - sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \ + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || \ + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || \ + sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) ? \ &xor_block_niagara : \ &xor_block_VIS) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index b90b4a1d070a..cb85458f89d2 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o obj-y += process_$(BITS).o obj-y += signal_$(BITS).o +obj-y += sigutil_$(BITS).o obj-$(CONFIG_SPARC32) += ioport.o obj-y += setup_$(BITS).o obj-y += idprom.o diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 9810fd881058..ba9b1cec4e6b 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -481,6 +481,18 @@ static void __init sun4v_cpu_probe(void) sparc_pmu_type = "niagara3"; break; + case SUN4V_CHIP_NIAGARA4: + sparc_cpu_type = "UltraSparc T4 (Niagara4)"; + sparc_fpu_type = "UltraSparc T4 integrated FPU"; + sparc_pmu_type = "niagara4"; + break; + + case SUN4V_CHIP_NIAGARA5: + sparc_cpu_type = "UltraSparc T5 (Niagara5)"; + sparc_fpu_type = "UltraSparc T5 integrated FPU"; + sparc_pmu_type = "niagara5"; + break; + default: printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", prom_cpu_compatible); diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c index 4197e8d62d4c..9323eafccb93 100644 --- a/arch/sparc/kernel/cpumap.c +++ b/arch/sparc/kernel/cpumap.c @@ -325,6 +325,8 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index) case SUN4V_CHIP_NIAGARA1: case SUN4V_CHIP_NIAGARA2: case SUN4V_CHIP_NIAGARA3: + case SUN4V_CHIP_NIAGARA4: + case SUN4V_CHIP_NIAGARA5: rover_inc_table = niagara_iterate_method; break; default: diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 0eac1b2fc53d..0d810c2f1d00 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -133,7 +133,7 @@ prom_sun4v_name: prom_niagara_prefix: .asciz "SUNW,UltraSPARC-T" prom_sparc_prefix: - .asciz "SPARC-T" + .asciz "SPARC-" .align 4 prom_root_compatible: .skip 64 @@ -396,7 +396,7 @@ sun4v_chip_type: or %g1, %lo(prom_cpu_compatible), %g1 sethi %hi(prom_sparc_prefix), %g7 or %g7, %lo(prom_sparc_prefix), %g7 - mov 7, %g3 + mov 6, %g3 90: ldub [%g7], %g2 ldub [%g1], %g4 cmp %g2, %g4 @@ -408,10 +408,23 @@ sun4v_chip_type: sethi %hi(prom_cpu_compatible), %g1 or %g1, %lo(prom_cpu_compatible), %g1 - ldub [%g1 + 7], %g2 + ldub [%g1 + 6], %g2 + cmp %g2, 'T' + be,pt %xcc, 70f + cmp %g2, 'M' + bne,pn %xcc, 4f + nop + +70: ldub [%g1 + 7], %g2 cmp %g2, '3' be,pt %xcc, 5f mov SUN4V_CHIP_NIAGARA3, %g4 + cmp %g2, '4' + be,pt %xcc, 5f + mov SUN4V_CHIP_NIAGARA4, %g4 + cmp %g2, '5' + be,pt %xcc, 5f + mov SUN4V_CHIP_NIAGARA5, %g4 ba,pt %xcc, 4f nop @@ -545,6 +558,12 @@ niagara_tlb_fixup: cmp %g1, SUN4V_CHIP_NIAGARA3 be,pt %xcc, niagara2_patch nop + cmp %g1, SUN4V_CHIP_NIAGARA4 + be,pt %xcc, niagara2_patch + nop + cmp %g1, SUN4V_CHIP_NIAGARA5 + be,pt %xcc, niagara2_patch + nop call generic_patch_copyops nop diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 100b9c204e78..42851122bbd9 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -88,7 +88,7 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int) #define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ -#define SUN4D_IPI_IRQ 14 +#define SUN4D_IPI_IRQ 13 extern void sun4d_ipi_interrupt(void); diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 1e94f946570e..8aa0d4408586 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -230,7 +230,8 @@ static void pci_parse_of_addrs(struct platform_device *op, res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; } else if (i == dev->rom_base_reg) { res = &dev->resource[PCI_ROM_RESOURCE]; - flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; + flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE + | IORESOURCE_SIZEALIGN; } else { printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); continue; diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index c8cc461ff75f..f793742eec2b 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -380,8 +380,7 @@ void flush_thread(void) #endif } - /* Now, this task is no longer a kernel thread. */ - current->thread.current_ds = USER_DS; + /* This task is no longer a kernel thread. */ if (current->thread.flags & SPARC_FLAG_KTHREAD) { current->thread.flags &= ~SPARC_FLAG_KTHREAD; diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index c158a95ec664..d959cd0a4aa4 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -368,9 +368,6 @@ void flush_thread(void) /* Clear FPU register state. */ t->fpsaved[0] = 0; - - if (get_thread_current_ds() != ASI_AIUS) - set_fs(USER_DS); } /* It's a bit more tricky when 64-bit tasks are involved... */ diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index d26e1f6c717a..3e3e2914c70b 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -137,7 +137,7 @@ static void __init process_switch(char c) prom_halt(); break; case 'p': - /* Just ignore, this behavior is now the default. */ + prom_early_console.flags &= ~CON_BOOT; break; default: printk("Unknown boot switch (-%c)\n", c); diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 3e9daea1653d..c965595aa7e9 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -106,7 +106,7 @@ static void __init process_switch(char c) prom_halt(); break; case 'p': - /* Just ignore, this behavior is now the default. */ + prom_early_console.flags &= ~CON_BOOT; break; case 'P': /* Force UltraSPARC-III P-Cache on. */ @@ -425,10 +425,14 @@ static void __init init_sparc64_elf_hwcap(void) else if (tlb_type == hypervisor) { if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || - sun4v_chip_type == SUN4V_CHIP_NIAGARA3) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5) cap |= HWCAP_SPARC_BLKINIT; if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || - sun4v_chip_type == SUN4V_CHIP_NIAGARA3) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5) cap |= HWCAP_SPARC_N2; } @@ -440,17 +444,27 @@ static void __init init_sparc64_elf_hwcap(void) cap |= AV_SPARC_VIS; if (tlb_type == cheetah || tlb_type == cheetah_plus) cap |= AV_SPARC_VIS | AV_SPARC_VIS2; - if (tlb_type == cheetah_plus) - cap |= AV_SPARC_POPC; + if (tlb_type == cheetah_plus) { + unsigned long impl, ver; + + __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); + impl = ((ver >> 32) & 0xffff); + if (impl == PANTHER_IMPL) + cap |= AV_SPARC_POPC; + } if (tlb_type == hypervisor) { if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1) cap |= AV_SPARC_ASI_BLK_INIT; if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || - sun4v_chip_type == SUN4V_CHIP_NIAGARA3) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5) cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 | AV_SPARC_ASI_BLK_INIT | AV_SPARC_POPC); - if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3) + if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5) cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC | AV_SPARC_FMAF); } diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 75fad425e249..2caa556db86d 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -29,6 +29,8 @@ #include <asm/visasm.h> #include <asm/compat_signal.h> +#include "sigutil.h" + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) /* This magic should be in g_upper[0] for all upper parts @@ -44,14 +46,14 @@ typedef struct { struct signal_frame32 { struct sparc_stackf32 ss; __siginfo32_t info; - /* __siginfo_fpu32_t * */ u32 fpu_save; + /* __siginfo_fpu_t * */ u32 fpu_save; unsigned int insns[2]; unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ siginfo_extra_v8plus_t v8plus; - __siginfo_fpu_t fpu_state; -}; + /* __siginfo_rwin_t * */u32 rwin_save; +} __attribute__((aligned(8))); typedef struct compat_siginfo{ int si_signo; @@ -110,18 +112,14 @@ struct rt_signal_frame32 { compat_siginfo_t info; struct pt_regs32 regs; compat_sigset_t mask; - /* __siginfo_fpu32_t * */ u32 fpu_save; + /* __siginfo_fpu_t * */ u32 fpu_save; unsigned int insns[2]; stack_t32 stack; unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ siginfo_extra_v8plus_t v8plus; - __siginfo_fpu_t fpu_state; -}; - -/* Align macros */ -#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 15) & (~15))) -#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 15) & (~15))) + /* __siginfo_rwin_t * */u32 rwin_save; +} __attribute__((aligned(8))); int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { @@ -192,30 +190,13 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) return 0; } -static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err; - - err = __get_user(fprs, &fpu->si_fprs); - fprs_write(0); - regs->tstate &= ~TSTATE_PEF; - if (fprs & FPRS_DL) - err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32)); - err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); - current_thread_info()->fpsaved[0] |= fprs; - return err; -} - void do_sigreturn32(struct pt_regs *regs) { struct signal_frame32 __user *sf; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; unsigned int psr; - unsigned pc, npc, fpu_save; + unsigned pc, npc; sigset_t set; unsigned seta[_COMPAT_NSIG_WORDS]; int err, i; @@ -273,8 +254,13 @@ void do_sigreturn32(struct pt_regs *regs) pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state32(regs, &sf->fpu_state); + if (!err && fpu_save) + err |= restore_fpu_state(regs, compat_ptr(fpu_save)); + err |= __get_user(rwin_save, &sf->rwin_save); + if (!err && rwin_save) { + if (restore_rwin_state(compat_ptr(rwin_save))) + goto segv; + } err |= __get_user(seta[0], &sf->info.si_mask); err |= copy_from_user(seta+1, &sf->extramask, (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); @@ -287,10 +273,7 @@ void do_sigreturn32(struct pt_regs *regs) case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); } sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); return; segv: @@ -300,7 +283,9 @@ segv: asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) { struct rt_signal_frame32 __user *sf; - unsigned int psr, pc, npc, fpu_save, u_ss_sp; + unsigned int psr, pc, npc, u_ss_sp; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; mm_segment_t old_fs; sigset_t set; compat_sigset_t seta; @@ -359,8 +344,8 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state32(regs, &sf->fpu_state); + if (!err && fpu_save) + err |= restore_fpu_state(regs, compat_ptr(fpu_save)); err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); err |= __get_user(u_ss_sp, &sf->stack.ss_sp); st.ss_sp = compat_ptr(u_ss_sp); @@ -376,6 +361,12 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf); set_fs(old_fs); + err |= __get_user(rwin_save, &sf->rwin_save); + if (!err && rwin_save) { + if (restore_rwin_state(compat_ptr(rwin_save))) + goto segv; + } + switch (_NSIG_WORDS) { case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32); case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32); @@ -383,10 +374,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); } sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); @@ -433,26 +421,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns return (void __user *) sp; } -static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err = 0; - - fprs = current_thread_info()->fpsaved[0]; - if (fprs & FPRS_DL) - err |= copy_to_user(&fpu->si_float_regs[0], fpregs, - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, - (sizeof(unsigned int) * 32)); - err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); - err |= __put_user(fprs, &fpu->si_fprs); - - return err; -} - /* The I-cache flush instruction only works in the primary ASI, which * right now is the nucleus, aka. kernel space. * @@ -515,18 +483,23 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset) { struct signal_frame32 __user *sf; + int i, err, wsaved; + void __user *tail; int sigframe_size; u32 psr; - int i, err; unsigned int seta[_COMPAT_NSIG_WORDS]; /* 1. Make sure everything is clean */ synchronize_user_stack(); save_and_clear_fpu(); - sigframe_size = SF_ALIGNEDSZ; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); + wsaved = get_thread_wsaved(); + + sigframe_size = sizeof(*sf); + if (current_thread_info()->fpsaved[0] & FPRS_FEF) + sigframe_size += sizeof(__siginfo_fpu_t); + if (wsaved) + sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct signal_frame32 __user *) get_sigframe(&ka->sa, regs, sigframe_size); @@ -534,8 +507,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (invalid_frame_pointer(sf, sigframe_size)) goto sigill; - if (get_thread_wsaved() != 0) - goto sigill; + tail = (sf + 1); /* 2. Save the current process state */ if (test_thread_flag(TIF_32BIT)) { @@ -560,11 +532,22 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, &sf->v8plus.asi); if (psr & PSR_EF) { - err |= save_fpu_state32(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); + __siginfo_fpu_t __user *fp = tail; + tail += sizeof(*fp); + err |= save_fpu_state(regs, fp); + err |= __put_user((u64)fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } + if (wsaved) { + __siginfo_rwin_t __user *rwp = tail; + tail += sizeof(*rwp); + err |= save_rwin_state(wsaved, rwp); + err |= __put_user((u64)rwp, &sf->rwin_save); + set_thread_wsaved(0); + } else { + err |= __put_user(0, &sf->rwin_save); + } switch (_NSIG_WORDS) { case 4: seta[7] = (oldset->sig[3] >> 32); @@ -580,10 +563,21 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, err |= __copy_to_user(sf->extramask, seta + 1, (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - err |= copy_in_user((u32 __user *)sf, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); - + if (!wsaved) { + err |= copy_in_user((u32 __user *)sf, + (u32 __user *)(regs->u_regs[UREG_FP]), + sizeof(struct reg_window32)); + } else { + struct reg_window *rp; + + rp = ¤t_thread_info()->reg_window[wsaved - 1]; + for (i = 0; i < 8; i++) + err |= __put_user(rp->locals[i], &sf->ss.locals[i]); + for (i = 0; i < 6; i++) + err |= __put_user(rp->ins[i], &sf->ss.ins[i]); + err |= __put_user(rp->ins[6], &sf->ss.fp); + err |= __put_user(rp->ins[7], &sf->ss.callers_pc); + } if (err) goto sigsegv; @@ -613,7 +607,6 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/ if (err) goto sigsegv; - flush_signal_insns(address); } return 0; @@ -632,18 +625,23 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, siginfo_t *info) { struct rt_signal_frame32 __user *sf; + int i, err, wsaved; + void __user *tail; int sigframe_size; u32 psr; - int i, err; compat_sigset_t seta; /* 1. Make sure everything is clean */ synchronize_user_stack(); save_and_clear_fpu(); - sigframe_size = RT_ALIGNEDSZ; - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); + wsaved = get_thread_wsaved(); + + sigframe_size = sizeof(*sf); + if (current_thread_info()->fpsaved[0] & FPRS_FEF) + sigframe_size += sizeof(__siginfo_fpu_t); + if (wsaved) + sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame32 __user *) get_sigframe(&ka->sa, regs, sigframe_size); @@ -651,8 +649,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (invalid_frame_pointer(sf, sigframe_size)) goto sigill; - if (get_thread_wsaved() != 0) - goto sigill; + tail = (sf + 1); /* 2. Save the current process state */ if (test_thread_flag(TIF_32BIT)) { @@ -677,11 +674,22 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, &sf->v8plus.asi); if (psr & PSR_EF) { - err |= save_fpu_state32(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); + __siginfo_fpu_t __user *fp = tail; + tail += sizeof(*fp); + err |= save_fpu_state(regs, fp); + err |= __put_user((u64)fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } + if (wsaved) { + __siginfo_rwin_t __user *rwp = tail; + tail += sizeof(*rwp); + err |= save_rwin_state(wsaved, rwp); + err |= __put_user((u64)rwp, &sf->rwin_save); + set_thread_wsaved(0); + } else { + err |= __put_user(0, &sf->rwin_save); + } /* Update the siginfo structure. */ err |= copy_siginfo_to_user32(&sf->info, info); @@ -703,9 +711,21 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, } err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); - err |= copy_in_user((u32 __user *)sf, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); + if (!wsaved) { + err |= copy_in_user((u32 __user *)sf, + (u32 __user *)(regs->u_regs[UREG_FP]), + sizeof(struct reg_window32)); + } else { + struct reg_window *rp; + + rp = ¤t_thread_info()->reg_window[wsaved - 1]; + for (i = 0; i < 8; i++) + err |= __put_user(rp->locals[i], &sf->ss.locals[i]); + for (i = 0; i < 6; i++) + err |= __put_user(rp->ins[i], &sf->ss.ins[i]); + err |= __put_user(rp->ins[6], &sf->ss.fp); + err |= __put_user(rp->ins[7], &sf->ss.callers_pc); + } if (err) goto sigsegv; @@ -756,6 +776,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + sigset_t blocked; int err; if (ka->sa.sa_flags & SA_SIGINFO) @@ -766,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, if (err) return err; - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) - sigaddset(¤t->blocked,signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + sigaddset(&blocked, signr); + set_current_blocked(&blocked); tracehook_signal_handler(signr, info, ka, regs, 0); @@ -855,7 +874,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + set_current_blocked(¤t->saved_sigmask); } } diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 5e5c5fd03783..8ce247ac04cc 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -26,6 +26,8 @@ #include <asm/pgtable.h> #include <asm/cacheflush.h> /* flush_sig_insns */ +#include "sigutil.h" + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) extern void fpsave(unsigned long *fpregs, unsigned long *fsr, @@ -39,8 +41,8 @@ struct signal_frame { unsigned long insns[2] __attribute__ ((aligned (8))); unsigned int extramask[_NSIG_WORDS - 1]; unsigned int extra_size; /* Should be 0 */ - __siginfo_fpu_t fpu_state; -}; + __siginfo_rwin_t __user *rwin_save; +} __attribute__((aligned(8))); struct rt_signal_frame { struct sparc_stackf ss; @@ -51,8 +53,8 @@ struct rt_signal_frame { unsigned int insns[2]; stack_t stack; unsigned int extra_size; /* Should be 0 */ - __siginfo_fpu_t fpu_state; -}; + __siginfo_rwin_t __user *rwin_save; +} __attribute__((aligned(8))); /* Align macros */ #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) @@ -60,12 +62,13 @@ struct rt_signal_frame { static int _sigpause_common(old_sigset_t set) { - set &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); + sigset_t blocked; + current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, set); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + + set &= _BLOCKABLE; + siginitset(&blocked, set); + set_current_blocked(&blocked); current->state = TASK_INTERRUPTIBLE; schedule(); @@ -79,43 +82,13 @@ asmlinkage int sys_sigsuspend(old_sigset_t set) return _sigpause_common(set); } -static inline int -restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - int err; -#ifdef CONFIG_SMP - if (test_tsk_thread_flag(current, TIF_USEDFPU)) - regs->psr &= ~PSR_EF; -#else - if (current == last_task_used_math) { - last_task_used_math = NULL; - regs->psr &= ~PSR_EF; - } -#endif - set_used_math(); - clear_tsk_thread_flag(current, TIF_USEDFPU); - - if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu))) - return -EFAULT; - - err = __copy_from_user(¤t->thread.float_regs[0], &fpu->si_float_regs[0], - (sizeof(unsigned long) * 32)); - err |= __get_user(current->thread.fsr, &fpu->si_fsr); - err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth); - if (current->thread.fpqdepth != 0) - err |= __copy_from_user(¤t->thread.fpqueue[0], - &fpu->si_fpqueue[0], - ((sizeof(unsigned long) + - (sizeof(unsigned long *)))*16)); - return err; -} - asmlinkage void do_sigreturn(struct pt_regs *regs) { struct signal_frame __user *sf; unsigned long up_psr, pc, npc; sigset_t set; __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; int err; /* Always make any pending restarted system calls return -EINTR */ @@ -150,9 +123,11 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) err |= restore_fpu_state(regs, fpu_save); + err |= __get_user(rwin_save, &sf->rwin_save); + if (rwin_save) + err |= restore_rwin_state(rwin_save); /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. @@ -165,10 +140,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) goto segv_and_exit; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); return; segv_and_exit: @@ -180,6 +152,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) struct rt_signal_frame __user *sf; unsigned int psr, pc, npc; __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; mm_segment_t old_fs; sigset_t set; stack_t st; @@ -207,8 +180,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) pt_regs_clear_syscall(regs); err |= __get_user(fpu_save, &sf->fpu_save); - - if (fpu_save) + if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); @@ -228,11 +200,14 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); set_fs(old_fs); + err |= __get_user(rwin_save, &sf->rwin_save); + if (!err && rwin_save) { + if (restore_rwin_state(rwin_save)) + goto segv; + } + sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); @@ -280,53 +255,23 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re return (void __user *) sp; } -static inline int -save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - int err = 0; -#ifdef CONFIG_SMP - if (test_tsk_thread_flag(current, TIF_USEDFPU)) { - put_psr(get_psr() | PSR_EF); - fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, - ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); - regs->psr &= ~(PSR_EF); - clear_tsk_thread_flag(current, TIF_USEDFPU); - } -#else - if (current == last_task_used_math) { - put_psr(get_psr() | PSR_EF); - fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, - ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); - last_task_used_math = NULL; - regs->psr &= ~(PSR_EF); - } -#endif - err |= __copy_to_user(&fpu->si_float_regs[0], - ¤t->thread.float_regs[0], - (sizeof(unsigned long) * 32)); - err |= __put_user(current->thread.fsr, &fpu->si_fsr); - err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth); - if (current->thread.fpqdepth != 0) - err |= __copy_to_user(&fpu->si_fpqueue[0], - ¤t->thread.fpqueue[0], - ((sizeof(unsigned long) + - (sizeof(unsigned long *)))*16)); - clear_used_math(); - return err; -} - static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset) { struct signal_frame __user *sf; - int sigframe_size, err; + int sigframe_size, err, wsaved; + void __user *tail; /* 1. Make sure everything is clean */ synchronize_user_stack(); - sigframe_size = SF_ALIGNEDSZ; - if (!used_math()) - sigframe_size -= sizeof(__siginfo_fpu_t); + wsaved = current_thread_info()->w_saved; + + sigframe_size = sizeof(*sf); + if (used_math()) + sigframe_size += sizeof(__siginfo_fpu_t); + if (wsaved) + sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); @@ -334,8 +279,7 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, if (invalid_frame_pointer(sf, sigframe_size)) goto sigill_and_return; - if (current_thread_info()->w_saved != 0) - goto sigill_and_return; + tail = sf + 1; /* 2. Save the current process state */ err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs)); @@ -343,17 +287,34 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(0, &sf->extra_size); if (used_math()) { - err |= save_fpu_state(regs, &sf->fpu_state); - err |= __put_user(&sf->fpu_state, &sf->fpu_save); + __siginfo_fpu_t __user *fp = tail; + tail += sizeof(*fp); + err |= save_fpu_state(regs, fp); + err |= __put_user(fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } + if (wsaved) { + __siginfo_rwin_t __user *rwp = tail; + tail += sizeof(*rwp); + err |= save_rwin_state(wsaved, rwp); + err |= __put_user(rwp, &sf->rwin_save); + } else { + err |= __put_user(0, &sf->rwin_save); + } err |= __put_user(oldset->sig[0], &sf->info.si_mask); err |= __copy_to_user(sf->extramask, &oldset->sig[1], (_NSIG_WORDS - 1) * sizeof(unsigned int)); - err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], - sizeof(struct reg_window32)); + if (!wsaved) { + err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], + sizeof(struct reg_window32)); + } else { + struct reg_window32 *rp; + + rp = ¤t_thread_info()->reg_window[wsaved - 1]; + err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); + } if (err) goto sigsegv; @@ -399,21 +360,24 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; - int sigframe_size; + int sigframe_size, wsaved; + void __user *tail; unsigned int psr; int err; synchronize_user_stack(); - sigframe_size = RT_ALIGNEDSZ; - if (!used_math()) - sigframe_size -= sizeof(__siginfo_fpu_t); + wsaved = current_thread_info()->w_saved; + sigframe_size = sizeof(*sf); + if (used_math()) + sigframe_size += sizeof(__siginfo_fpu_t); + if (wsaved) + sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) goto sigill; - if (current_thread_info()->w_saved != 0) - goto sigill; + tail = sf + 1; err = __put_user(regs->pc, &sf->regs.pc); err |= __put_user(regs->npc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); @@ -425,11 +389,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(0, &sf->extra_size); if (psr & PSR_EF) { - err |= save_fpu_state(regs, &sf->fpu_state); - err |= __put_user(&sf->fpu_state, &sf->fpu_save); + __siginfo_fpu_t *fp = tail; + tail += sizeof(*fp); + err |= save_fpu_state(regs, fp); + err |= __put_user(fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } + if (wsaved) { + __siginfo_rwin_t *rwp = tail; + tail += sizeof(*rwp); + err |= save_rwin_state(wsaved, rwp); + err |= __put_user(rwp, &sf->rwin_save); + } else { + err |= __put_user(0, &sf->rwin_save); + } err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ @@ -437,8 +411,15 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); - err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], - sizeof(struct reg_window32)); + if (!wsaved) { + err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], + sizeof(struct reg_window32)); + } else { + struct reg_window32 *rp; + + rp = ¤t_thread_info()->reg_window[wsaved - 1]; + err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); + } err |= copy_siginfo_to_user(&sf->info, info); @@ -484,6 +465,7 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + sigset_t blocked; int err; if (ka->sa.sa_flags & SA_SIGINFO) @@ -494,12 +476,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, if (err) return err; - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) - sigaddset(¤t->blocked, signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + sigaddset(&blocked, signr); + set_current_blocked(&blocked); tracehook_signal_handler(signr, info, ka, regs, 0); @@ -595,7 +575,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + set_current_blocked(¤t->saved_sigmask); } } diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 006fe4515886..a2b81598d905 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -34,6 +34,7 @@ #include "entry.h" #include "systbls.h" +#include "sigutil.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -69,10 +70,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) goto do_sigsegv; } sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); } if (test_thread_flag(TIF_32BIT)) { pc &= 0xffffffff; @@ -236,17 +234,18 @@ struct rt_signal_frame { __siginfo_fpu_t __user *fpu_save; stack_t stack; sigset_t mask; - __siginfo_fpu_t fpu_state; + __siginfo_rwin_t *rwin_save; }; static long _sigpause_common(old_sigset_t set) { - set &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); + sigset_t blocked; + current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, set); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + + set &= _BLOCKABLE; + siginitset(&blocked, set); + set_current_blocked(&blocked); current->state = TASK_INTERRUPTIBLE; schedule(); @@ -266,33 +265,12 @@ asmlinkage long sys_sigsuspend(old_sigset_t set) return _sigpause_common(set); } -static inline int -restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err; - - err = __get_user(fprs, &fpu->si_fprs); - fprs_write(0); - regs->tstate &= ~TSTATE_PEF; - if (fprs & FPRS_DL) - err |= copy_from_user(fpregs, &fpu->si_float_regs[0], - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], - (sizeof(unsigned int) * 32)); - err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); - current_thread_info()->fpsaved[0] |= fprs; - return err; -} - void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; unsigned long tpc, tnpc, tstate; __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; sigset_t set; int err; @@ -325,8 +303,8 @@ void do_rt_sigreturn(struct pt_regs *regs) regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state(regs, &sf->fpu_state); + if (!err && fpu_save) + err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); @@ -334,6 +312,12 @@ void do_rt_sigreturn(struct pt_regs *regs) if (err) goto segv; + err |= __get_user(rwin_save, &sf->rwin_save); + if (!err && rwin_save) { + if (restore_rwin_state(rwin_save)) + goto segv; + } + regs->tpc = tpc; regs->tnpc = tnpc; @@ -341,44 +325,20 @@ void do_rt_sigreturn(struct pt_regs *regs) pt_regs_clear_syscall(regs); sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); return; segv: force_sig(SIGSEGV, current); } /* Checks if the fp is valid */ -static int invalid_frame_pointer(void __user *fp, int fplen) +static int invalid_frame_pointer(void __user *fp) { if (((unsigned long) fp) & 15) return 1; return 0; } -static inline int -save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) -{ - unsigned long *fpregs = current_thread_info()->fpregs; - unsigned long fprs; - int err = 0; - - fprs = current_thread_info()->fpsaved[0]; - if (fprs & FPRS_DL) - err |= copy_to_user(&fpu->si_float_regs[0], fpregs, - (sizeof(unsigned int) * 32)); - if (fprs & FPRS_DU) - err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, - (sizeof(unsigned int) * 32)); - err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); - err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); - err |= __put_user(fprs, &fpu->si_fprs); - - return err; -} - static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; @@ -414,34 +374,48 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; - int sigframe_size, err; + int wsaved, err, sf_size; + void __user *tail; /* 1. Make sure everything is clean */ synchronize_user_stack(); save_and_clear_fpu(); - sigframe_size = sizeof(struct rt_signal_frame); - if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); + wsaved = get_thread_wsaved(); + sf_size = sizeof(struct rt_signal_frame); + if (current_thread_info()->fpsaved[0] & FPRS_FEF) + sf_size += sizeof(__siginfo_fpu_t); + if (wsaved) + sf_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) - get_sigframe(ka, regs, sigframe_size); - - if (invalid_frame_pointer (sf, sigframe_size)) - goto sigill; + get_sigframe(ka, regs, sf_size); - if (get_thread_wsaved() != 0) + if (invalid_frame_pointer (sf)) goto sigill; + tail = (sf + 1); + /* 2. Save the current process state */ err = copy_to_user(&sf->regs, regs, sizeof (*regs)); if (current_thread_info()->fpsaved[0] & FPRS_FEF) { - err |= save_fpu_state(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); + __siginfo_fpu_t __user *fpu_save = tail; + tail += sizeof(__siginfo_fpu_t); + err |= save_fpu_state(regs, fpu_save); + err |= __put_user((u64)fpu_save, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } + if (wsaved) { + __siginfo_rwin_t __user *rwin_save = tail; + tail += sizeof(__siginfo_rwin_t); + err |= save_rwin_state(wsaved, rwin_save); + err |= __put_user((u64)rwin_save, &sf->rwin_save); + set_thread_wsaved(0); + } else { + err |= __put_user(0, &sf->rwin_save); + } /* Setup sigaltstack */ err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); @@ -450,10 +424,17 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); - err |= copy_in_user((u64 __user *)sf, - (u64 __user *)(regs->u_regs[UREG_FP]+STACK_BIAS), - sizeof(struct reg_window)); + if (!wsaved) { + err |= copy_in_user((u64 __user *)sf, + (u64 __user *)(regs->u_regs[UREG_FP] + + STACK_BIAS), + sizeof(struct reg_window)); + } else { + struct reg_window *rp; + rp = ¤t_thread_info()->reg_window[wsaved - 1]; + err |= copy_to_user(sf, rp, sizeof(struct reg_window)); + } if (info) err |= copy_siginfo_to_user(&sf->info, info); else { @@ -498,18 +479,17 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + sigset_t blocked; int err; err = setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); if (err) return err; - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) - sigaddset(¤t->blocked,signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + sigaddset(&blocked, signr); + set_current_blocked(&blocked); tracehook_signal_handler(signr, info, ka, regs, 0); @@ -615,7 +595,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + set_current_blocked(¤t->saved_sigmask); } } diff --git a/arch/sparc/kernel/sigutil.h b/arch/sparc/kernel/sigutil.h new file mode 100644 index 000000000000..d223aa432bb6 --- /dev/null +++ b/arch/sparc/kernel/sigutil.h @@ -0,0 +1,9 @@ +#ifndef _SIGUTIL_H +#define _SIGUTIL_H + +int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu); +int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu); +int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin); +int restore_rwin_state(__siginfo_rwin_t __user *rp); + +#endif /* _SIGUTIL_H */ diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c new file mode 100644 index 000000000000..35c7897b009a --- /dev/null +++ b/arch/sparc/kernel/sigutil_32.c @@ -0,0 +1,120 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/thread_info.h> +#include <linux/uaccess.h> +#include <linux/sched.h> + +#include <asm/sigcontext.h> +#include <asm/fpumacro.h> +#include <asm/ptrace.h> + +#include "sigutil.h" + +int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) +{ + int err = 0; +#ifdef CONFIG_SMP + if (test_tsk_thread_flag(current, TIF_USEDFPU)) { + put_psr(get_psr() | PSR_EF); + fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, + ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); + regs->psr &= ~(PSR_EF); + clear_tsk_thread_flag(current, TIF_USEDFPU); + } +#else + if (current == last_task_used_math) { + put_psr(get_psr() | PSR_EF); + fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, + ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); + last_task_used_math = NULL; + regs->psr &= ~(PSR_EF); + } +#endif + err |= __copy_to_user(&fpu->si_float_regs[0], + ¤t->thread.float_regs[0], + (sizeof(unsigned long) * 32)); + err |= __put_user(current->thread.fsr, &fpu->si_fsr); + err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth); + if (current->thread.fpqdepth != 0) + err |= __copy_to_user(&fpu->si_fpqueue[0], + ¤t->thread.fpqueue[0], + ((sizeof(unsigned long) + + (sizeof(unsigned long *)))*16)); + clear_used_math(); + return err; +} + +int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) +{ + int err; +#ifdef CONFIG_SMP + if (test_tsk_thread_flag(current, TIF_USEDFPU)) + regs->psr &= ~PSR_EF; +#else + if (current == last_task_used_math) { + last_task_used_math = NULL; + regs->psr &= ~PSR_EF; + } +#endif + set_used_math(); + clear_tsk_thread_flag(current, TIF_USEDFPU); + + if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu))) + return -EFAULT; + + err = __copy_from_user(¤t->thread.float_regs[0], &fpu->si_float_regs[0], + (sizeof(unsigned long) * 32)); + err |= __get_user(current->thread.fsr, &fpu->si_fsr); + err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth); + if (current->thread.fpqdepth != 0) + err |= __copy_from_user(¤t->thread.fpqueue[0], + &fpu->si_fpqueue[0], + ((sizeof(unsigned long) + + (sizeof(unsigned long *)))*16)); + return err; +} + +int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin) +{ + int i, err = __put_user(wsaved, &rwin->wsaved); + + for (i = 0; i < wsaved; i++) { + struct reg_window32 *rp; + unsigned long fp; + + rp = ¤t_thread_info()->reg_window[i]; + fp = current_thread_info()->rwbuf_stkptrs[i]; + err |= copy_to_user(&rwin->reg_window[i], rp, + sizeof(struct reg_window32)); + err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]); + } + return err; +} + +int restore_rwin_state(__siginfo_rwin_t __user *rp) +{ + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + + __get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + + err = 0; + for (i = 0; i < wsaved; i++) { + err |= copy_from_user(&t->reg_window[i], + &rp->reg_window[i], + sizeof(struct reg_window32)); + err |= __get_user(t->rwbuf_stkptrs[i], + &rp->rwbuf_stkptrs[i]); + } + if (err) + return err; + + t->w_saved = wsaved; + synchronize_user_stack(); + if (t->w_saved) + return -EFAULT; + return 0; + +} diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c new file mode 100644 index 000000000000..e7dc508c38eb --- /dev/null +++ b/arch/sparc/kernel/sigutil_64.c @@ -0,0 +1,93 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/thread_info.h> +#include <linux/uaccess.h> + +#include <asm/sigcontext.h> +#include <asm/fpumacro.h> +#include <asm/ptrace.h> + +#include "sigutil.h" + +int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) +{ + unsigned long *fpregs = current_thread_info()->fpregs; + unsigned long fprs; + int err = 0; + + fprs = current_thread_info()->fpsaved[0]; + if (fprs & FPRS_DL) + err |= copy_to_user(&fpu->si_float_regs[0], fpregs, + (sizeof(unsigned int) * 32)); + if (fprs & FPRS_DU) + err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, + (sizeof(unsigned int) * 32)); + err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); + err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); + err |= __put_user(fprs, &fpu->si_fprs); + + return err; +} + +int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) +{ + unsigned long *fpregs = current_thread_info()->fpregs; + unsigned long fprs; + int err; + + err = __get_user(fprs, &fpu->si_fprs); + fprs_write(0); + regs->tstate &= ~TSTATE_PEF; + if (fprs & FPRS_DL) + err |= copy_from_user(fpregs, &fpu->si_float_regs[0], + (sizeof(unsigned int) * 32)); + if (fprs & FPRS_DU) + err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], + (sizeof(unsigned int) * 32)); + err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); + err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); + current_thread_info()->fpsaved[0] |= fprs; + return err; +} + +int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin) +{ + int i, err = __put_user(wsaved, &rwin->wsaved); + + for (i = 0; i < wsaved; i++) { + struct reg_window *rp = ¤t_thread_info()->reg_window[i]; + unsigned long fp = current_thread_info()->rwbuf_stkptrs[i]; + + err |= copy_to_user(&rwin->reg_window[i], rp, + sizeof(struct reg_window)); + err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]); + } + return err; +} + +int restore_rwin_state(__siginfo_rwin_t __user *rp) +{ + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + + __get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + + err = 0; + for (i = 0; i < wsaved; i++) { + err |= copy_from_user(&t->reg_window[i], + &rp->reg_window[i], + sizeof(struct reg_window)); + err |= __get_user(t->rwbuf_stkptrs[i], + &rp->rwbuf_stkptrs[i]); + } + if (err) + return err; + + set_thread_wsaved(wsaved); + synchronize_user_stack(); + if (get_thread_wsaved()) + return -EFAULT; + return 0; +} diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S index 44e5faf1ad5f..d97f3eb72e06 100644 --- a/arch/sparc/kernel/sys32.S +++ b/arch/sparc/kernel/sys32.S @@ -81,7 +81,6 @@ SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4) SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) SIGN1(sys32_mlockall, sys_mlockall, %o0) -SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0) SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 6e492d59f6b1..09d8ec454450 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -67,7 +67,7 @@ sys_call_table: /*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl +/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_ni_syscall /*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index f566518483b5..edbec45d4688 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -68,7 +68,7 @@ sys_call_table32: .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep -/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl +/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys_nis_syscall .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy @@ -145,7 +145,7 @@ sys_call_table: .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl +/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 581531dbc8b5..8e073d802139 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -511,6 +511,11 @@ static void __init read_obp_translations(void) for (i = 0; i < prom_trans_ents; i++) prom_trans[i].data &= ~0x0003fe0000000000UL; } + + /* Force execute bit on. */ + for (i = 0; i < prom_trans_ents; i++) + prom_trans[i].data |= (tlb_type == hypervisor ? + _PAGE_EXEC_4V : _PAGE_EXEC_4U); } static void __init hypervisor_tlb_lock(unsigned long vaddr, diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c index e485a6804998..13c2169822a8 100644 --- a/arch/sparc/mm/leon_mm.c +++ b/arch/sparc/mm/leon_mm.c @@ -162,7 +162,7 @@ ready: printk(KERN_INFO "swprobe: padde %x\n", paddr_calc); if (paddr) *paddr = paddr_calc; - return paddrbase; + return pte; } void leon_flush_icache_all(void) diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index b30f71ac0d06..70a0de46cd1b 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -46,9 +46,6 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK config SYS_SUPPORTS_HUGETLBFS def_bool y -config GENERIC_TIME - def_bool y - config GENERIC_CLOCKEVENTS def_bool y diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index 2ad73fb707b9..dafdbbae1124 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_DEFAULT_MIGRATION_COST=10000000 diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index f58dc362b944..6f05f969b564 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_DEFAULT_MIGRATION_COST=10000000 diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index fc94607f0bd5..aecc8ed5f39b 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -21,7 +21,7 @@ #include <asm/ptrace.h> #include <asm/thread_info.h> #include <asm/irqflags.h> -#include <linux/atomic.h> +#include <asm/atomic_32.h> #include <asm/asm-offsets.h> #include <hv/hypervisor.h> #include <arch/abi.h> diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S index 1f75a2a56101..30638042691d 100644 --- a/arch/tile/lib/atomic_asm_32.S +++ b/arch/tile/lib/atomic_asm_32.S @@ -70,7 +70,7 @@ */ #include <linux/linkage.h> -#include <linux/atomic.h> +#include <asm/atomic_32.h> #include <asm/page.h> #include <asm/processor.h> diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86 index d31ecf346b4e..21bebe63df66 100644 --- a/arch/um/Kconfig.x86 +++ b/arch/um/Kconfig.x86 @@ -10,6 +10,10 @@ config CMPXCHG_LOCAL bool default n +config CMPXCHG_DOUBLE + bool + default n + source "arch/x86/Kconfig.cpu" endmenu diff --git a/arch/um/Makefile b/arch/um/Makefile index fab8121d2b32..c0f712cc7c5f 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -41,7 +41,7 @@ KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH) KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ -Din6addr_loopback=kernel_in6addr_loopback \ - -Din6addr_any=kernel_in6addr_any + -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr KBUILD_AFLAGS += $(ARCH_INCLUDE) diff --git a/arch/um/defconfig b/arch/um/defconfig index 9f7634f08cf3..761f5e1a657e 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -13,7 +13,6 @@ CONFIG_LOCKDEP_SUPPORT=y # CONFIG_STACKTRACE_SUPPORT is not set CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_IRQ_RELEASE_METHOD=y CONFIG_HZ=100 diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index d51c404239a8..364c8a15c4c3 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -399,8 +399,8 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) * is done under a spinlock. Checking whether the device is in use is * line->tty->count > 1, also under the spinlock. * - * tty->count serves to decide whether the device should be enabled or - * disabled on the host. If it's equal to 1, then we are doing the + * line->count serves to decide whether the device should be enabled or + * disabled on the host. If it's equal to 0, then we are doing the * first open or last close. Otherwise, open and close just return. */ @@ -414,16 +414,16 @@ int line_open(struct line *lines, struct tty_struct *tty) goto out_unlock; err = 0; - if (tty->count > 1) + if (line->count++) goto out_unlock; - spin_unlock(&line->count_lock); - + BUG_ON(tty->driver_data); tty->driver_data = line; line->tty = tty; + spin_unlock(&line->count_lock); err = enable_chan(line); - if (err) + if (err) /* line_close() will be called by our caller */ return err; INIT_DELAYED_WORK(&line->task, line_timer_cb); @@ -436,7 +436,7 @@ int line_open(struct line *lines, struct tty_struct *tty) chan_window_size(&line->chan_list, &tty->winsize.ws_row, &tty->winsize.ws_col); - return err; + return 0; out_unlock: spin_unlock(&line->count_lock); @@ -460,17 +460,16 @@ void line_close(struct tty_struct *tty, struct file * filp) flush_buffer(line); spin_lock(&line->count_lock); - if (!line->valid) - goto out_unlock; + BUG_ON(!line->valid); - if (tty->count > 1) + if (--line->count) goto out_unlock; - spin_unlock(&line->count_lock); - line->tty = NULL; tty->driver_data = NULL; + spin_unlock(&line->count_lock); + if (line->sigio) { unregister_winch(tty); line->sigio = 0; @@ -498,7 +497,7 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, spin_lock(&line->count_lock); - if (line->tty != NULL) { + if (line->count) { *error_out = "Device is already open"; goto out; } @@ -722,41 +721,53 @@ struct winch { int pid; struct tty_struct *tty; unsigned long stack; + struct work_struct work; }; -static void free_winch(struct winch *winch, int free_irq_ok) +static void __free_winch(struct work_struct *work) { - if (free_irq_ok) - free_irq(WINCH_IRQ, winch); - - list_del(&winch->list); + struct winch *winch = container_of(work, struct winch, work); + free_irq(WINCH_IRQ, winch); if (winch->pid != -1) os_kill_process(winch->pid, 1); - if (winch->fd != -1) - os_close_file(winch->fd); if (winch->stack != 0) free_stack(winch->stack, 0); kfree(winch); } +static void free_winch(struct winch *winch) +{ + int fd = winch->fd; + winch->fd = -1; + if (fd != -1) + os_close_file(fd); + list_del(&winch->list); + __free_winch(&winch->work); +} + static irqreturn_t winch_interrupt(int irq, void *data) { struct winch *winch = data; struct tty_struct *tty; struct line *line; + int fd = winch->fd; int err; char c; - if (winch->fd != -1) { - err = generic_read(winch->fd, &c, NULL); + if (fd != -1) { + err = generic_read(fd, &c, NULL); if (err < 0) { if (err != -EAGAIN) { + winch->fd = -1; + list_del(&winch->list); + os_close_file(fd); printk(KERN_ERR "winch_interrupt : " "read failed, errno = %d\n", -err); printk(KERN_ERR "fd %d is losing SIGWINCH " "support\n", winch->tty_fd); - free_winch(winch, 0); + INIT_WORK(&winch->work, __free_winch); + schedule_work(&winch->work); return IRQ_HANDLED; } goto out; @@ -828,7 +839,7 @@ static void unregister_winch(struct tty_struct *tty) list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); if (winch->tty == tty) { - free_winch(winch, 1); + free_winch(winch); break; } } @@ -844,7 +855,7 @@ static void winch_cleanup(void) list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); - free_winch(winch, 1); + free_winch(winch); } spin_unlock(&winch_handler_lock); diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 22745b47c829..a492e59883a3 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -368,7 +368,7 @@ static const struct net_device_ops uml_netdev_ops = { .ndo_open = uml_net_open, .ndo_stop = uml_net_close, .ndo_start_xmit = uml_net_start_xmit, - .ndo_set_multicast_list = uml_net_set_multicast_list, + .ndo_set_rx_mode = uml_net_set_multicast_list, .ndo_tx_timeout = uml_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = uml_net_change_mtu, diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 8ac7146c237f..2e1de5728604 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -123,6 +123,7 @@ static int xterm_open(int input, int output, int primary, void *d, err = -errno; printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n", errno); + close(fd); return err; } close(fd); diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index ae084ad1a3a0..1a7d2757fe05 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -42,10 +42,6 @@ extern long subarch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data); extern unsigned long getreg(struct task_struct *child, int regno); extern int putreg(struct task_struct *child, int regno, unsigned long value); -extern int get_fpregs(struct user_i387_struct __user *buf, - struct task_struct *child); -extern int set_fpregs(struct user_i387_struct __user *buf, - struct task_struct *child); extern int arch_copy_tls(struct task_struct *new); extern void clear_flushed_tls(struct task_struct *task); diff --git a/arch/um/include/shared/line.h b/arch/um/include/shared/line.h index 72f4f25af247..63df3ca02ac2 100644 --- a/arch/um/include/shared/line.h +++ b/arch/um/include/shared/line.h @@ -33,6 +33,7 @@ struct line_driver { struct line { struct tty_struct *tty; spinlock_t count_lock; + unsigned long count; int valid; char *init_str; diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h index b0b4589e0ebc..f1e0aa56c52a 100644 --- a/arch/um/include/shared/registers.h +++ b/arch/um/include/shared/registers.h @@ -16,7 +16,7 @@ extern int restore_fpx_registers(int pid, unsigned long *fp_regs); extern int save_registers(int pid, struct uml_pt_regs *regs); extern int restore_registers(int pid, struct uml_pt_regs *regs); extern int init_registers(int pid); -extern void get_safe_registers(unsigned long *regs); +extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); extern int get_fp_registers(int pid, unsigned long *regs); extern int put_fp_registers(int pid, unsigned long *regs); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index fab4371184f6..21c1ae7c3d75 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -202,7 +202,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, arch_copy_thread(¤t->thread.arch, &p->thread.arch); } else { - get_safe_registers(p->thread.regs.regs.gp); + get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); p->thread.request.u.thread = current->thread.request.u.thread; handler = new_thread_handler; } diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 701b672c1122..c9da32b0c707 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -50,23 +50,11 @@ long arch_ptrace(struct task_struct *child, long request, void __user *vp = p; switch (request) { - /* read word at location addr. */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: ret = peek_user(child, addr, data); break; - /* write the word at location addr. */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: ret = poke_user(child, addr, data); @@ -107,16 +95,6 @@ long arch_ptrace(struct task_struct *child, long request, break; } #endif -#ifdef PTRACE_GETFPREGS - case PTRACE_GETFPREGS: /* Get the child FPU state. */ - ret = get_fpregs(vp, child); - break; -#endif -#ifdef PTRACE_SETFPREGS - case PTRACE_SETFPREGS: /* Set the child FPU state. */ - ret = set_fpregs(vp, child); - break; -#endif case PTRACE_GET_THREAD_AREA: ret = ptrace_get_thread_area(child, addr, vp); break; @@ -154,12 +132,6 @@ long arch_ptrace(struct task_struct *child, long request, break; } #endif -#ifdef PTRACE_ARCH_PRCTL - case PTRACE_ARCH_PRCTL: - /* XXX Calls ptrace on the host - needs some SMP thinking */ - ret = arch_prctl(child, data, (void __user *) addr); - break; -#endif default: ret = ptrace_request(child, request, addr, data); if (ret == -EIO) diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c index 830fe6a1518a..b866b9e3bef9 100644 --- a/arch/um/os-Linux/registers.c +++ b/arch/um/os-Linux/registers.c @@ -8,6 +8,8 @@ #include <string.h> #include <sys/ptrace.h> #include "sysdep/ptrace.h" +#include "sysdep/ptrace_user.h" +#include "registers.h" int save_registers(int pid, struct uml_pt_regs *regs) { @@ -32,6 +34,7 @@ int restore_registers(int pid, struct uml_pt_regs *regs) /* This is set once at boot time and not changed thereafter */ static unsigned long exec_regs[MAX_REG_NR]; +static unsigned long exec_fp_regs[FP_SIZE]; int init_registers(int pid) { @@ -42,10 +45,14 @@ int init_registers(int pid) return -errno; arch_init_registers(pid); + get_fp_registers(pid, exec_fp_regs); return 0; } -void get_safe_registers(unsigned long *regs) +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) { memcpy(regs, exec_regs, sizeof(exec_regs)); + + if (fp_regs) + memcpy(fp_regs, exec_fp_regs, sizeof(exec_fp_regs)); } diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index d261f170d120..e771398be5f3 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -39,7 +39,7 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - get_safe_registers(syscall_regs); + get_safe_registers(syscall_regs, NULL); syscall_regs[REGS_IP_INDEX] = STUB_CODE + ((unsigned long) &batch_syscall_stub - (unsigned long) &__syscall_stub_start); diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index d6e0a2234b86..dee0e8cf8ad0 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -373,6 +373,9 @@ void userspace(struct uml_pt_regs *regs) if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) fatal_sigsegv(); + if (put_fp_registers(pid, regs->fp)) + fatal_sigsegv(); + /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); @@ -399,6 +402,12 @@ void userspace(struct uml_pt_regs *regs) fatal_sigsegv(); } + if (get_fp_registers(pid, regs->fp)) { + printk(UM_KERN_ERR "userspace - get_fp_registers failed, " + "errno = %d\n", errno); + fatal_sigsegv(); + } + UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if (WIFSTOPPED(status)) { @@ -457,10 +466,11 @@ void userspace(struct uml_pt_regs *regs) } static unsigned long thread_regs[MAX_REG_NR]; +static unsigned long thread_fp_regs[FP_SIZE]; static int __init init_thread_regs(void) { - get_safe_registers(thread_regs); + get_safe_registers(thread_regs, thread_fp_regs); /* Set parent's instruction pointer to start of clone-stub */ thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - @@ -503,6 +513,13 @@ int copy_context_skas0(unsigned long new_stack, int pid) return err; } + err = put_fp_registers(pid, thread_fp_regs); + if (err < 0) { + printk(UM_KERN_ERR "copy_context_skas0 : put_fp_registers " + "failed, pid = %d, err = %d\n", pid, err); + return err; + } + /* set a well known return code for detection of child write failure */ child_data->err = 12345678; diff --git a/arch/um/sys-i386/asm/ptrace.h b/arch/um/sys-i386/asm/ptrace.h index 0273e4d09af7..5d2a59112537 100644 --- a/arch/um/sys-i386/asm/ptrace.h +++ b/arch/um/sys-i386/asm/ptrace.h @@ -42,11 +42,6 @@ */ struct user_desc; -extern int get_fpxregs(struct user_fxsr_struct __user *buf, - struct task_struct *child); -extern int set_fpxregs(struct user_fxsr_struct __user *buf, - struct task_struct *tsk); - extern int ptrace_get_thread_area(struct task_struct *child, int idx, struct user_desc __user *user_desc); diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index d23b2d3ea384..3375c2717851 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -145,7 +145,7 @@ int peek_user(struct task_struct *child, long addr, long data) return put_user(tmp, (unsigned long __user *) data); } -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; struct user_i387_struct fpregs; @@ -161,7 +161,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) return n; } -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; struct user_i387_struct fpregs; @@ -174,7 +174,7 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) (unsigned long *) &fpregs); } -int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) +static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; struct user_fxsr_struct fpregs; @@ -190,7 +190,7 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) return n; } -int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) +static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; struct user_fxsr_struct fpregs; @@ -206,5 +206,23 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) long subarch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { - return -EIO; + int ret = -EIO; + void __user *datap = (void __user *) data; + switch (request) { + case PTRACE_GETFPREGS: /* Get the child FPU state. */ + ret = get_fpregs(datap, child); + break; + case PTRACE_SETFPREGS: /* Set the child FPU state. */ + ret = set_fpregs(datap, child); + break; + case PTRACE_GETFPXREGS: /* Get the child FPU state. */ + ret = get_fpxregs(datap, child); + break; + case PTRACE_SETFPXREGS: /* Set the child FPU state. */ + ret = set_fpxregs(datap, child); + break; + default: + ret = -EIO; + } + return ret; } diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/um/sys-i386/shared/sysdep/ptrace.h index d50e62e07070..c398a5076111 100644 --- a/arch/um/sys-i386/shared/sysdep/ptrace.h +++ b/arch/um/sys-i386/shared/sysdep/ptrace.h @@ -53,6 +53,7 @@ extern int sysemu_supported; struct uml_pt_regs { unsigned long gp[MAX_REG_NR]; + unsigned long fp[HOST_FPX_SIZE]; struct faultinfo faultinfo; long syscall; int is_user; diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index f43613643cdb..4005506834fd 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -145,7 +145,7 @@ int is_syscall(unsigned long addr) return instr == 0x050f; } -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; long fpregs[HOST_FP_SIZE]; @@ -162,7 +162,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) return n; } -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) +static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; long fpregs[HOST_FP_SIZE]; @@ -182,12 +182,16 @@ long subarch_ptrace(struct task_struct *child, long request, void __user *datap = (void __user *) data; switch (request) { - case PTRACE_GETFPXREGS: /* Get the child FPU state. */ + case PTRACE_GETFPREGS: /* Get the child FPU state. */ ret = get_fpregs(datap, child); break; - case PTRACE_SETFPXREGS: /* Set the child FPU state. */ + case PTRACE_SETFPREGS: /* Set the child FPU state. */ ret = set_fpregs(datap, child); break; + case PTRACE_ARCH_PRCTL: + /* XXX Calls ptrace on the host - needs some SMP thinking */ + ret = arch_prctl(child, data, (void __user *) addr); + break; } return ret; diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace.h b/arch/um/sys-x86_64/shared/sysdep/ptrace.h index fdba5457947a..8ee8f8e12af1 100644 --- a/arch/um/sys-x86_64/shared/sysdep/ptrace.h +++ b/arch/um/sys-x86_64/shared/sysdep/ptrace.h @@ -85,6 +85,7 @@ struct uml_pt_regs { unsigned long gp[MAX_REG_NR]; + unsigned long fp[HOST_FP_SIZE]; struct faultinfo faultinfo; long syscall; int is_user; diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h index 4bd87f3d13d4..1a5c5a5eb39c 100644 --- a/arch/unicore32/include/asm/io.h +++ b/arch/unicore32/include/asm/io.h @@ -32,7 +32,7 @@ extern void __uc32_iounmap(volatile void __iomem *addr); * ioremap and friends. * * ioremap takes a PCI memory address, as specified in - * Documentation/IO-mapping.txt. + * Documentation/io-mapping.txt. * */ #define ioremap(cookie, size) __uc32_ioremap(cookie, size) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6a47bb22657f..f49767716c70 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -64,10 +64,12 @@ config X86 select HAVE_TEXT_POKE_SMP select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ + select SPARSE_IRQ select GENERIC_FIND_FIRST_BIT select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP select GENERIC_IRQ_SHOW + select GENERIC_CLOCKEVENTS_MIN_ADJUST select IRQ_FORCED_THREADING select USE_GENERIC_SMP_HELPERS if SMP select HAVE_BPF_JIT if (X86_64 && NET) @@ -130,7 +132,7 @@ config SBUS bool config NEED_DMA_MAP_STATE - def_bool (X86_64 || DMAR || DMA_API_DEBUG) + def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG) config NEED_SG_DMA_LENGTH def_bool y @@ -220,7 +222,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC config HAVE_INTEL_TXT def_bool y - depends on EXPERIMENTAL && DMAR && ACPI + depends on EXPERIMENTAL && INTEL_IOMMU && ACPI config X86_32_SMP def_bool y @@ -279,7 +281,7 @@ config SMP Y to "Enhanced Real Time Clock Support", below. The "Advanced Power Management" code will be disabled if you say Y here. - See also <file:Documentation/i386/IO-APIC.txt>, + See also <file:Documentation/x86/i386/IO-APIC.txt>, <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at <http://www.tldp.org/docs.html#howto>. @@ -287,7 +289,7 @@ config SMP config X86_X2APIC bool "Support x2apic" - depends on X86_LOCAL_APIC && X86_64 && INTR_REMAP + depends on X86_LOCAL_APIC && X86_64 && IRQ_REMAP ---help--- This enables x2apic support on CPUs that have this feature. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index c0f8a5c88910..bf56e1793272 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -139,7 +139,7 @@ config IOMMU_DEBUG code. When you use it make sure you have a big enough IOMMU/AGP aperture. Most of the options enabled by this can be set more finegrained using the iommu= command line - options. See Documentation/x86_64/boot-options.txt for more + options. See Documentation/x86/x86_64/boot-options.txt for more details. config IOMMU_STRESS diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 93e689f4bd86..bdb4d458ec8c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -129,7 +129,7 @@ start_sys_seg: .word SYSSEG # obsolete and meaningless, but just type_of_loader: .byte 0 # 0 means ancient bootloader, newer # bootloaders know to change this. - # See Documentation/i386/boot.txt for + # See Documentation/x86/boot.txt for # assigned ids # flags, unused bits must be zero (RFU) bit within loadflags diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 22a0dc8e51dd..058a35b8286c 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -67,8 +67,8 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_PCI_MMCONFIG=y -CONFIG_DMAR=y -# CONFIG_DMAR_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_PCIEPORTBUS=y CONFIG_PCCARD=y CONFIG_YENTA=y diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index a0e866d233ee..54edb207ff3a 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -672,7 +672,7 @@ ia32_sys_call_table: .quad sys32_vm86_warning /* vm86 */ .quad quiet_ni_syscall /* query_module */ .quad sys_poll - .quad compat_sys_nfsservctl + .quad quiet_ni_syscall /* old nfsservctl */ .quad sys_setresgid16 /* 170 */ .quad sys_getresgid16 .quad sys_prctl diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h index 4554cc6fb96a..091508b533b4 100644 --- a/arch/x86/include/asm/alternative-asm.h +++ b/arch/x86/include/asm/alternative-asm.h @@ -16,7 +16,6 @@ #endif .macro altinstruction_entry orig alt feature orig_len alt_len - .align 8 .long \orig - . .long \alt - . .word \feature diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 23fb6d79f209..37ad100a2210 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -48,9 +48,6 @@ struct alt_instr { u16 cpuid; /* cpuid bit set for replacement */ u8 instrlen; /* length of original instruction */ u8 replacementlen; /* length of new instruction, <= instrlen */ -#ifdef CONFIG_X86_64 - u32 pad2; -#endif }; extern void alternative_instructions(void); @@ -83,7 +80,6 @@ static inline int alternatives_text_reserved(void *start, void *end) \ "661:\n\t" oldinstr "\n662:\n" \ ".section .altinstructions,\"a\"\n" \ - _ASM_ALIGN "\n" \ " .long 661b - .\n" /* label */ \ " .long 663f - .\n" /* new instruction */ \ " .word " __stringify(feature) "\n" /* feature bit */ \ diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 7b3ca8324b69..9b7273cb2193 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -495,7 +495,7 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert) return; } -extern struct apic *generic_bigsmp_probe(void); +extern void generic_bigsmp_probe(void); #ifdef CONFIG_X86_LOCAL_APIC diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 4258aac99a6e..88b23a43f340 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -332,7 +332,6 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) asm goto("1: jmp %l[t_no]\n" "2:\n" ".section .altinstructions,\"a\"\n" - _ASM_ALIGN "\n" " .long 1b - .\n" " .long 0\n" /* no replacement */ " .word %P0\n" /* feature bit */ @@ -350,7 +349,6 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) asm volatile("1: movb $0,%0\n" "2:\n" ".section .altinstructions,\"a\"\n" - _ASM_ALIGN "\n" " .long 1b - .\n" " .long 3f - .\n" " .word %P1\n" /* feature bit */ diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index 029f230ab637..63a2a03d7d51 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h @@ -8,7 +8,7 @@ struct dev_archdata { #ifdef CONFIG_X86_64 struct dma_map_ops *dma_ops; #endif -#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU) +#if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU) void *iommu; /* hook for IOMMU specific extension */ #endif }; diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index d4c419f883a0..ed3065fd6314 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -2,7 +2,7 @@ #define _ASM_X86_DMA_MAPPING_H /* - * IOMMU interface. See Documentation/PCI/PCI-DMA-mapping.txt and + * IOMMU interface. See Documentation/DMA-API-HOWTO.txt and * Documentation/DMA-API.txt for documentation. */ diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h index 326099199318..f6f15986df6c 100644 --- a/arch/x86/include/asm/dwarf2.h +++ b/arch/x86/include/asm/dwarf2.h @@ -27,6 +27,7 @@ #define CFI_REMEMBER_STATE .cfi_remember_state #define CFI_RESTORE_STATE .cfi_restore_state #define CFI_UNDEFINED .cfi_undefined +#define CFI_ESCAPE .cfi_escape #ifdef CONFIG_AS_CFI_SIGNAL_FRAME #define CFI_SIGNAL_FRAME .cfi_signal_frame @@ -68,6 +69,7 @@ #define CFI_REMEMBER_STATE cfi_ignore #define CFI_RESTORE_STATE cfi_ignore #define CFI_UNDEFINED cfi_ignore +#define CFI_ESCAPE cfi_ignore #define CFI_SIGNAL_FRAME cfi_ignore #endif diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 09199052060f..eb92a6ed2be7 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -119,7 +119,7 @@ struct irq_cfg { cpumask_var_t old_domain; u8 vector; u8 move_in_progress : 1; -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP struct irq_2_iommu irq_2_iommu; #endif }; diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h index 5df477ac3af7..b80420bcd09d 100644 --- a/arch/x86/include/asm/hyperv.h +++ b/arch/x86/include/asm/hyperv.h @@ -189,5 +189,6 @@ #define HV_STATUS_INVALID_HYPERCALL_CODE 2 #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 #define HV_STATUS_INVALID_ALIGNMENT 4 +#define HV_STATUS_INSUFFICIENT_BUFFERS 19 #endif diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 1c23360fb2d8..47d99934580f 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -3,7 +3,8 @@ #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8) -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP +static void irq_remap_modify_chip_defaults(struct irq_chip *chip); static inline void prepare_irte(struct irte *irte, int vector, unsigned int dest) { @@ -36,6 +37,9 @@ static inline bool irq_remapped(struct irq_cfg *cfg) { return false; } +static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip) +{ +} #endif #endif /* _ASM_X86_IRQ_REMAPPING_H */ diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 7e50f06393aa..4b4448761e88 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -160,19 +160,11 @@ static inline int invalid_vm86_irq(int irq) #define IO_APIC_VECTOR_LIMIT ( 32 * MAX_IO_APICS ) #ifdef CONFIG_X86_IO_APIC -# ifdef CONFIG_SPARSE_IRQ -# define CPU_VECTOR_LIMIT (64 * NR_CPUS) -# define NR_IRQS \ +# define CPU_VECTOR_LIMIT (64 * NR_CPUS) +# define NR_IRQS \ (CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ? \ (NR_VECTORS + CPU_VECTOR_LIMIT) : \ (NR_VECTORS + IO_APIC_VECTOR_LIMIT)) -# else -# define CPU_VECTOR_LIMIT (32 * NR_CPUS) -# define NR_IRQS \ - (CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ? \ - (NR_VECTORS + CPU_VECTOR_LIMIT) : \ - (NR_VECTORS + IO_APIC_VECTOR_LIMIT)) -# endif #else /* !CONFIG_X86_IO_APIC: */ # define NR_IRQS NR_IRQS_LEGACY #endif diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index 4886a68f267e..fd3f9f18cf3f 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h @@ -22,27 +22,26 @@ void arch_trigger_all_cpu_backtrace(void); #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace #endif -/* - * Define some priorities for the nmi notifier call chain. - * - * Create a local nmi bit that has a higher priority than - * external nmis, because the local ones are more frequent. - * - * Also setup some default high/normal/low settings for - * subsystems to registers with. Using 4 bits to separate - * the priorities. This can go a lot higher if needed be. - */ - -#define NMI_LOCAL_SHIFT 16 /* randomly picked */ -#define NMI_LOCAL_BIT (1ULL << NMI_LOCAL_SHIFT) -#define NMI_HIGH_PRIOR (1ULL << 8) -#define NMI_NORMAL_PRIOR (1ULL << 4) -#define NMI_LOW_PRIOR (1ULL << 0) -#define NMI_LOCAL_HIGH_PRIOR (NMI_LOCAL_BIT | NMI_HIGH_PRIOR) -#define NMI_LOCAL_NORMAL_PRIOR (NMI_LOCAL_BIT | NMI_NORMAL_PRIOR) -#define NMI_LOCAL_LOW_PRIOR (NMI_LOCAL_BIT | NMI_LOW_PRIOR) +#define NMI_FLAG_FIRST 1 + +enum { + NMI_LOCAL=0, + NMI_UNKNOWN, + NMI_MAX +}; + +#define NMI_DONE 0 +#define NMI_HANDLED 1 + +typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *); + +int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long, + const char *); + +void unregister_nmi_handler(unsigned int, const char *); void stop_nmi(void); void restart_nmi(void); +void local_touch_nmi(void); #endif /* _ASM_X86_NMI_H */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 094fb30817ab..f61c62f7d5d8 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -29,6 +29,9 @@ #define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23) #define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL +#define AMD_PERFMON_EVENTSEL_GUESTONLY (1ULL << 40) +#define AMD_PERFMON_EVENTSEL_HOSTONLY (1ULL << 41) + #define AMD64_EVENTSEL_EVENT \ (ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32)) #define INTEL_ARCH_EVENT_MASK \ @@ -43,14 +46,17 @@ #define AMD64_RAW_EVENT_MASK \ (X86_RAW_EVENT_MASK | \ AMD64_EVENTSEL_EVENT) +#define AMD64_NUM_COUNTERS 4 +#define AMD64_NUM_COUNTERS_F15H 6 +#define AMD64_NUM_COUNTERS_MAX AMD64_NUM_COUNTERS_F15H -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0 +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \ (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX)) -#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6 +#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6 /* * Intel "Architectural Performance Monitoring" CPUID @@ -110,6 +116,35 @@ union cpuid10_edx { */ #define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) +/* + * IBS cpuid feature detection + */ + +#define IBS_CPUID_FEATURES 0x8000001b + +/* + * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but + * bit 0 is used to indicate the existence of IBS. + */ +#define IBS_CAPS_AVAIL (1U<<0) +#define IBS_CAPS_FETCHSAM (1U<<1) +#define IBS_CAPS_OPSAM (1U<<2) +#define IBS_CAPS_RDWROPCNT (1U<<3) +#define IBS_CAPS_OPCNT (1U<<4) +#define IBS_CAPS_BRNTRGT (1U<<5) +#define IBS_CAPS_OPCNTEXT (1U<<6) + +#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ + | IBS_CAPS_FETCHSAM \ + | IBS_CAPS_OPSAM) + +/* + * IBS APIC setup + */ +#define IBSCTL 0x1cc +#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8) +#define IBSCTL_LVT_OFFSET_MASK 0x0F + /* IbsFetchCtl bits/masks */ #define IBS_FETCH_RAND_EN (1ULL<<57) #define IBS_FETCH_VAL (1ULL<<49) @@ -124,6 +159,8 @@ union cpuid10_edx { #define IBS_OP_MAX_CNT 0x0000FFFFULL #define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */ +extern u32 get_ibs_caps(void); + #ifdef CONFIG_PERF_EVENTS extern void perf_events_lapic_init(void); @@ -159,7 +196,19 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); ); \ } +struct perf_guest_switch_msr { + unsigned msr; + u64 host, guest; +}; + +extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr); #else +static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr) +{ + *nr = 0; + return NULL; +} + static inline void perf_events_lapic_init(void) { } #endif diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index a518c0a45044..c59cc97fe6c1 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -44,7 +44,7 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); #elif defined(__x86_64__) __asm__ ( - "mul %[mul_frac] ; shrd $32, %[hi], %[lo]" + "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]" : [lo]"=a"(product), [hi]"=d"(tmp) : "0"(delta), diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index 3250e3d605d9..92f297069e87 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -23,7 +23,7 @@ void machine_real_restart(unsigned int type); #define MRR_BIOS 0 #define MRR_APM 1 -typedef void (*nmi_shootdown_cb)(int, struct die_args*); +typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); void nmi_shootdown_cpus(nmi_shootdown_cb callback); #endif /* _ASM_X86_REBOOT_H */ diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h index 940d7204b89d..0a6ba337a2eb 100644 --- a/arch/x86/include/asm/unistd_64.h +++ b/arch/x86/include/asm/unistd_64.h @@ -414,7 +414,7 @@ __SYSCALL(__NR_query_module, sys_ni_syscall) __SYSCALL(__NR_quotactl, sys_quotactl) #define __NR_nfsservctl 180 -__SYSCALL(__NR_nfsservctl, sys_nfsservctl) +__SYSCALL(__NR_nfsservctl, sys_ni_syscall) /* reserved for LiS/STREAMS */ #define __NR_getpmsg 181 diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 7ff4669580cf..c34f96c2f7a0 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -12,6 +12,7 @@ #include <asm/pgtable.h> #include <xen/interface/xen.h> +#include <xen/grant_table.h> #include <xen/features.h> /* Xen machine address */ @@ -48,14 +49,11 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, unsigned long pfn_e); extern int m2p_add_override(unsigned long mfn, struct page *page, - bool clear_pte); + struct gnttab_map_grant_ref *kmap_op); extern int m2p_remove_override(struct page *page, bool clear_pte); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); -#ifdef CONFIG_XEN_DEBUG_FS -extern int p2m_dump_show(struct seq_file *m, void *v); -#endif static inline unsigned long pfn_to_mfn(unsigned long pfn) { unsigned long mfn; diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 82f2912155a5..8baca3c4871c 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -19,7 +19,7 @@ endif obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o -obj-y += time.o ioport.o ldt.o dumpstack.o +obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o obj-$(CONFIG_IRQ_WORK) += irq_work.o obj-y += probe_roms.o diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index 8a439d364b94..b1e7c7f7a0af 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c @@ -5,7 +5,7 @@ * This allows to use PCI devices that only support 32bit addresses on systems * with more than 4GB. * - * See Documentation/PCI/PCI-DMA-mapping.txt for the interface specification. + * See Documentation/DMA-API-HOWTO.txt for the interface specification. * * Copyright 2002 Andi Kleen, SuSE Labs. * Subject to the GNU General Public License v2 only. diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 52fa56399a50..a2fd72e0ab35 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1437,27 +1437,21 @@ void enable_x2apic(void) int __init enable_IR(void) { -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP if (!intr_remapping_supported()) { pr_debug("intr-remapping not supported\n"); - return 0; + return -1; } if (!x2apic_preenabled && skip_ioapic_setup) { pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n"); - return 0; + return -1; } - if (enable_intr_remapping(x2apic_supported())) - return 0; - - pr_info("Enabled Interrupt-remapping\n"); - - return 1; - + return enable_intr_remapping(); #endif - return 0; + return -1; } void __init enable_IR_x2apic(void) @@ -1481,11 +1475,11 @@ void __init enable_IR_x2apic(void) mask_ioapic_entries(); if (dmar_table_init_ret) - ret = 0; + ret = -1; else ret = enable_IR(); - if (!ret) { + if (ret < 0) { /* IR is required if there is APIC ID > 255 even when running * under KVM */ @@ -1499,6 +1493,9 @@ void __init enable_IR_x2apic(void) x2apic_force_phys(); } + if (ret == IRQ_REMAP_XAPIC_MODE) + goto nox2apic; + x2apic_enabled = 1; if (x2apic_supported() && !x2apic_mode) { @@ -1508,19 +1505,21 @@ void __init enable_IR_x2apic(void) } nox2apic: - if (!ret) /* IR enabling failed */ + if (ret < 0) /* IR enabling failed */ restore_ioapic_entries(); legacy_pic->restore_mask(); local_irq_restore(flags); out: - if (x2apic_enabled) + if (x2apic_enabled || !x2apic_supported()) return; if (x2apic_preenabled) panic("x2apic: enabled by BIOS but kernel init failed."); - else if (cpu_has_x2apic) - pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); + else if (ret == IRQ_REMAP_XAPIC_MODE) + pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); + else if (ret < 0) + pr_info("x2apic not enabled, IRQ remapping init failed\n"); } #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index efd737e827f4..521bead01137 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -255,12 +255,24 @@ static struct apic apic_bigsmp = { .x86_32_early_logical_apicid = bigsmp_early_logical_apicid, }; -struct apic * __init generic_bigsmp_probe(void) +void __init generic_bigsmp_probe(void) { - if (probe_bigsmp()) - return &apic_bigsmp; + unsigned int cpu; - return NULL; + if (!probe_bigsmp()) + return; + + apic = &apic_bigsmp; + + for_each_possible_cpu(cpu) { + if (early_per_cpu(x86_cpu_to_logical_apicid, + cpu) == BAD_APICID) + continue; + early_per_cpu(x86_cpu_to_logical_apicid, cpu) = + bigsmp_early_logical_apicid(cpu); + } + + pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name); } apic_driver(apic_bigsmp); diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index d5e57db0f7be..31cb9ae992b7 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c @@ -60,22 +60,10 @@ void arch_trigger_all_cpu_backtrace(void) } static int __kprobes -arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self, - unsigned long cmd, void *__args) +arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs) { - struct die_args *args = __args; - struct pt_regs *regs; int cpu; - switch (cmd) { - case DIE_NMI: - break; - - default: - return NOTIFY_DONE; - } - - regs = args->regs; cpu = smp_processor_id(); if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { @@ -86,21 +74,16 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self, show_regs(regs); arch_spin_unlock(&lock); cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); - return NOTIFY_STOP; + return NMI_HANDLED; } - return NOTIFY_DONE; + return NMI_DONE; } -static __read_mostly struct notifier_block backtrace_notifier = { - .notifier_call = arch_trigger_all_cpu_backtrace_handler, - .next = NULL, - .priority = NMI_LOCAL_LOW_PRIOR, -}; - static int __init register_trigger_all_cpu_backtrace(void) { - register_die_notifier(&backtrace_notifier); + register_nmi_handler(NMI_LOCAL, arch_trigger_all_cpu_backtrace_handler, + 0, "arch_bt"); return 0; } early_initcall(register_trigger_all_cpu_backtrace); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 8eb863e27ea6..3c31fa98af6d 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -92,21 +92,21 @@ static struct ioapic { DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); } ioapics[MAX_IO_APICS]; -#define mpc_ioapic_ver(id) ioapics[id].mp_config.apicver +#define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver -int mpc_ioapic_id(int id) +int mpc_ioapic_id(int ioapic_idx) { - return ioapics[id].mp_config.apicid; + return ioapics[ioapic_idx].mp_config.apicid; } -unsigned int mpc_ioapic_addr(int id) +unsigned int mpc_ioapic_addr(int ioapic_idx) { - return ioapics[id].mp_config.apicaddr; + return ioapics[ioapic_idx].mp_config.apicaddr; } -struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id) +struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx) { - return &ioapics[id].gsi_config; + return &ioapics[ioapic_idx].gsi_config; } int nr_ioapics; @@ -186,11 +186,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node) /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ -#ifdef CONFIG_SPARSE_IRQ static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; -#else -static struct irq_cfg irq_cfgx[NR_IRQS]; -#endif int __init arch_early_irq_init(void) { @@ -234,7 +230,6 @@ int __init arch_early_irq_init(void) return 0; } -#ifdef CONFIG_SPARSE_IRQ static struct irq_cfg *irq_cfg(unsigned int irq) { return irq_get_chip_data(irq); @@ -269,22 +264,6 @@ static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) kfree(cfg); } -#else - -struct irq_cfg *irq_cfg(unsigned int irq) -{ - return irq < nr_irqs ? irq_cfgx + irq : NULL; -} - -static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node) -{ - return irq_cfgx + irq; -} - -static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { } - -#endif - static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node) { int res = irq_alloc_desc_at(at, node); @@ -394,13 +373,21 @@ union entry_union { struct IO_APIC_route_entry entry; }; +static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin) +{ + union entry_union eu; + + eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); + eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); + return eu.entry; +} + static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) { union entry_union eu; unsigned long flags; raw_spin_lock_irqsave(&ioapic_lock, flags); - eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); - eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); + eu.entry = __ioapic_read_entry(apic, pin); raw_spin_unlock_irqrestore(&ioapic_lock, flags); return eu.entry; } @@ -529,18 +516,6 @@ static void io_apic_modify_irq(struct irq_cfg *cfg, __io_apic_modify_irq(entry, mask_and, mask_or, final); } -static void __mask_and_edge_IO_APIC_irq(struct irq_pin_list *entry) -{ - __io_apic_modify_irq(entry, ~IO_APIC_REDIR_LEVEL_TRIGGER, - IO_APIC_REDIR_MASKED, NULL); -} - -static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry) -{ - __io_apic_modify_irq(entry, ~IO_APIC_REDIR_MASKED, - IO_APIC_REDIR_LEVEL_TRIGGER, NULL); -} - static void io_apic_sync(struct irq_pin_list *entry) { /* @@ -585,6 +560,66 @@ static void unmask_ioapic_irq(struct irq_data *data) unmask_ioapic(data->chip_data); } +/* + * IO-APIC versions below 0x20 don't support EOI register. + * For the record, here is the information about various versions: + * 0Xh 82489DX + * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant + * 2Xh I/O(x)APIC which is PCI 2.2 Compliant + * 30h-FFh Reserved + * + * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic + * version as 0x2. This is an error with documentation and these ICH chips + * use io-apic's of version 0x20. + * + * For IO-APIC's with EOI register, we use that to do an explicit EOI. + * Otherwise, we simulate the EOI message manually by changing the trigger + * mode to edge and then back to level, with RTE being masked during this. + */ +static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg) +{ + if (mpc_ioapic_ver(apic) >= 0x20) { + /* + * Intr-remapping uses pin number as the virtual vector + * in the RTE. Actual vector is programmed in + * intr-remapping table entry. Hence for the io-apic + * EOI we use the pin number. + */ + if (cfg && irq_remapped(cfg)) + io_apic_eoi(apic, pin); + else + io_apic_eoi(apic, vector); + } else { + struct IO_APIC_route_entry entry, entry1; + + entry = entry1 = __ioapic_read_entry(apic, pin); + + /* + * Mask the entry and change the trigger mode to edge. + */ + entry1.mask = 1; + entry1.trigger = IOAPIC_EDGE; + + __ioapic_write_entry(apic, pin, entry1); + + /* + * Restore the previous level triggered entry. + */ + __ioapic_write_entry(apic, pin, entry); + } +} + +static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) +{ + struct irq_pin_list *entry; + unsigned long flags; + + raw_spin_lock_irqsave(&ioapic_lock, flags); + for_each_irq_pin(entry, cfg->irq_2_pin) + __eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg); + raw_spin_unlock_irqrestore(&ioapic_lock, flags); +} + static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) { struct IO_APIC_route_entry entry; @@ -593,10 +628,44 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) entry = ioapic_read_entry(apic, pin); if (entry.delivery_mode == dest_SMI) return; + + /* + * Make sure the entry is masked and re-read the contents to check + * if it is a level triggered pin and if the remote-IRR is set. + */ + if (!entry.mask) { + entry.mask = 1; + ioapic_write_entry(apic, pin, entry); + entry = ioapic_read_entry(apic, pin); + } + + if (entry.irr) { + unsigned long flags; + + /* + * Make sure the trigger mode is set to level. Explicit EOI + * doesn't clear the remote-IRR if the trigger mode is not + * set to level. + */ + if (!entry.trigger) { + entry.trigger = IOAPIC_LEVEL; + ioapic_write_entry(apic, pin, entry); + } + + raw_spin_lock_irqsave(&ioapic_lock, flags); + __eoi_ioapic_pin(apic, pin, entry.vector, NULL); + raw_spin_unlock_irqrestore(&ioapic_lock, flags); + } + /* - * Disable it in the IO-APIC irq-routing table: + * Clear the rest of the bits in the IO-APIC RTE except for the mask + * bit. */ ioapic_mask_entry(apic, pin); + entry = ioapic_read_entry(apic, pin); + if (entry.irr) + printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n", + mpc_ioapic_id(apic), pin); } static void clear_IO_APIC (void) @@ -712,13 +781,13 @@ int restore_ioapic_entries(void) /* * Find the IRQ entry number of a certain pin. */ -static int find_irq_entry(int apic, int pin, int type) +static int find_irq_entry(int ioapic_idx, int pin, int type) { int i; for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].irqtype == type && - (mp_irqs[i].dstapic == mpc_ioapic_id(apic) || + (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) || mp_irqs[i].dstapic == MP_APIC_ALL) && mp_irqs[i].dstirq == pin) return i; @@ -757,12 +826,13 @@ static int __init find_isa_irq_apic(int irq, int type) (mp_irqs[i].srcbusirq == irq)) break; } + if (i < mp_irq_entries) { - int apic; - for(apic = 0; apic < nr_ioapics; apic++) { - if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic) - return apic; - } + int ioapic_idx; + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) + if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic) + return ioapic_idx; } return -1; @@ -977,7 +1047,7 @@ static int pin_2_irq(int idx, int apic, int pin) int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, struct io_apic_irq_attr *irq_attr) { - int apic, i, best_guess = -1; + int ioapic_idx, i, best_guess = -1; apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", @@ -990,8 +1060,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, for (i = 0; i < mp_irq_entries; i++) { int lbus = mp_irqs[i].srcbus; - for (apic = 0; apic < nr_ioapics; apic++) - if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic || + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) + if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic || mp_irqs[i].dstapic == MP_APIC_ALL) break; @@ -999,13 +1069,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, !mp_irqs[i].irqtype && (bus == lbus) && (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) { - int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq); + int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq); - if (!(apic || IO_APIC_IRQ(irq))) + if (!(ioapic_idx || IO_APIC_IRQ(irq))) continue; if (pin == (mp_irqs[i].srcbusirq & 3)) { - set_io_apic_irq_attr(irq_attr, apic, + set_io_apic_irq_attr(irq_attr, ioapic_idx, mp_irqs[i].dstirq, irq_trigger(i), irq_polarity(i)); @@ -1016,7 +1086,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, * best-guess fuzzy result for broken mptables. */ if (best_guess < 0) { - set_io_apic_irq_attr(irq_attr, apic, + set_io_apic_irq_attr(irq_attr, ioapic_idx, mp_irqs[i].dstirq, irq_trigger(i), irq_polarity(i)); @@ -1202,7 +1272,6 @@ void __setup_vector_irq(int cpu) } static struct irq_chip ioapic_chip; -static struct irq_chip ir_ioapic_chip; #ifdef CONFIG_X86_32 static inline int IO_APIC_irq_trigger(int irq) @@ -1246,7 +1315,7 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, if (irq_remapped(cfg)) { irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); - chip = &ir_ioapic_chip; + irq_remap_modify_chip_defaults(chip); fasteoi = trigger != 0; } @@ -1255,77 +1324,100 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, fasteoi ? "fasteoi" : "edge"); } -static int setup_ioapic_entry(int apic_id, int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, int trigger, - int polarity, int vector, int pin) + +static int setup_ir_ioapic_entry(int irq, + struct IR_IO_APIC_route_entry *entry, + unsigned int destination, int vector, + struct io_apic_irq_attr *attr) { - /* - * add it to the IO-APIC irq-routing table: - */ - memset(entry,0,sizeof(*entry)); + int index; + struct irte irte; + int ioapic_id = mpc_ioapic_id(attr->ioapic); + struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id); - if (intr_remapping_enabled) { - struct intel_iommu *iommu = map_ioapic_to_ir(apic_id); - struct irte irte; - struct IR_IO_APIC_route_entry *ir_entry = - (struct IR_IO_APIC_route_entry *) entry; - int index; + if (!iommu) { + pr_warn("No mapping iommu for ioapic %d\n", ioapic_id); + return -ENODEV; + } - if (!iommu) - panic("No mapping iommu for ioapic %d\n", apic_id); + index = alloc_irte(iommu, irq, 1); + if (index < 0) { + pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id); + return -ENOMEM; + } - index = alloc_irte(iommu, irq, 1); - if (index < 0) - panic("Failed to allocate IRTE for ioapic %d\n", apic_id); + prepare_irte(&irte, vector, destination); - prepare_irte(&irte, vector, destination); + /* Set source-id of interrupt request */ + set_ioapic_sid(&irte, ioapic_id); - /* Set source-id of interrupt request */ - set_ioapic_sid(&irte, apic_id); + modify_irte(irq, &irte); - modify_irte(irq, &irte); + apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " + "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " + "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " + "Avail:%X Vector:%02X Dest:%08X " + "SID:%04X SQ:%X SVT:%X)\n", + attr->ioapic, irte.present, irte.fpd, irte.dst_mode, + irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, + irte.avail, irte.vector, irte.dest_id, + irte.sid, irte.sq, irte.svt); + + memset(entry, 0, sizeof(*entry)); + + entry->index2 = (index >> 15) & 0x1; + entry->zero = 0; + entry->format = 1; + entry->index = (index & 0x7fff); + /* + * IO-APIC RTE will be configured with virtual vector. + * irq handler will do the explicit EOI to the io-apic. + */ + entry->vector = attr->ioapic_pin; + entry->mask = 0; /* enable IRQ */ + entry->trigger = attr->trigger; + entry->polarity = attr->polarity; - ir_entry->index2 = (index >> 15) & 0x1; - ir_entry->zero = 0; - ir_entry->format = 1; - ir_entry->index = (index & 0x7fff); - /* - * IO-APIC RTE will be configured with virtual vector. - * irq handler will do the explicit EOI to the io-apic. - */ - ir_entry->vector = pin; - - apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " - "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " - "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " - "Avail:%X Vector:%02X Dest:%08X " - "SID:%04X SQ:%X SVT:%X)\n", - apic_id, irte.present, irte.fpd, irte.dst_mode, - irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, - irte.avail, irte.vector, irte.dest_id, - irte.sid, irte.sq, irte.svt); - } else { - entry->delivery_mode = apic->irq_delivery_mode; - entry->dest_mode = apic->irq_dest_mode; - entry->dest = destination; - entry->vector = vector; - } + /* Mask level triggered irqs. + * Use IRQ_DELAYED_DISABLE for edge triggered irqs. + */ + if (attr->trigger) + entry->mask = 1; - entry->mask = 0; /* enable IRQ */ - entry->trigger = trigger; - entry->polarity = polarity; + return 0; +} - /* Mask level triggered irqs. +static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, + unsigned int destination, int vector, + struct io_apic_irq_attr *attr) +{ + if (intr_remapping_enabled) + return setup_ir_ioapic_entry(irq, + (struct IR_IO_APIC_route_entry *)entry, + destination, vector, attr); + + memset(entry, 0, sizeof(*entry)); + + entry->delivery_mode = apic->irq_delivery_mode; + entry->dest_mode = apic->irq_dest_mode; + entry->dest = destination; + entry->vector = vector; + entry->mask = 0; /* enable IRQ */ + entry->trigger = attr->trigger; + entry->polarity = attr->polarity; + + /* + * Mask level triggered irqs. * Use IRQ_DELAYED_DISABLE for edge triggered irqs. */ - if (trigger) + if (attr->trigger) entry->mask = 1; + return 0; } -static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq, - struct irq_cfg *cfg, int trigger, int polarity) +static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, + struct io_apic_irq_attr *attr) { struct IO_APIC_route_entry entry; unsigned int dest; @@ -1348,49 +1440,48 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq, apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i Dest:%d)\n", - apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector, - irq, trigger, polarity, dest); - + attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin, + cfg->vector, irq, attr->trigger, attr->polarity, dest); - if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry, - dest, trigger, polarity, cfg->vector, pin)) { - printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", - mpc_ioapic_id(apic_id), pin); + if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) { + pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n", + mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); __clear_irq_vector(irq, cfg); + return; } - ioapic_register_intr(irq, cfg, trigger); + ioapic_register_intr(irq, cfg, attr->trigger); if (irq < legacy_pic->nr_legacy_irqs) legacy_pic->mask(irq); - ioapic_write_entry(apic_id, pin, entry); + ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry); } -static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin) +static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin) { if (idx != -1) return false; apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n", - mpc_ioapic_id(apic_id), pin); + mpc_ioapic_id(ioapic_idx), pin); return true; } -static void __init __io_apic_setup_irqs(unsigned int apic_id) +static void __init __io_apic_setup_irqs(unsigned int ioapic_idx) { int idx, node = cpu_to_node(0); struct io_apic_irq_attr attr; unsigned int pin, irq; - for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) { - idx = find_irq_entry(apic_id, pin, mp_INT); - if (io_apic_pin_not_connected(idx, apic_id, pin)) + for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) { + idx = find_irq_entry(ioapic_idx, pin, mp_INT); + if (io_apic_pin_not_connected(idx, ioapic_idx, pin)) continue; - irq = pin_2_irq(idx, apic_id, pin); + irq = pin_2_irq(idx, ioapic_idx, pin); - if ((apic_id > 0) && (irq > 16)) + if ((ioapic_idx > 0) && (irq > 16)) continue; /* @@ -1398,10 +1489,10 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id) * installed and if it returns 1: */ if (apic->multi_timer_check && - apic->multi_timer_check(apic_id, irq)) + apic->multi_timer_check(ioapic_idx, irq)) continue; - set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), + set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), irq_polarity(idx)); io_apic_setup_irq_pin(irq, node, &attr); @@ -1410,12 +1501,12 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id) static void __init setup_IO_APIC_irqs(void) { - unsigned int apic_id; + unsigned int ioapic_idx; apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); - for (apic_id = 0; apic_id < nr_ioapics; apic_id++) - __io_apic_setup_irqs(apic_id); + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) + __io_apic_setup_irqs(ioapic_idx); } /* @@ -1425,28 +1516,28 @@ static void __init setup_IO_APIC_irqs(void) */ void setup_IO_APIC_irq_extra(u32 gsi) { - int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); + int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0); struct io_apic_irq_attr attr; /* * Convert 'gsi' to 'ioapic.pin'. */ - apic_id = mp_find_ioapic(gsi); - if (apic_id < 0) + ioapic_idx = mp_find_ioapic(gsi); + if (ioapic_idx < 0) return; - pin = mp_find_ioapic_pin(apic_id, gsi); - idx = find_irq_entry(apic_id, pin, mp_INT); + pin = mp_find_ioapic_pin(ioapic_idx, gsi); + idx = find_irq_entry(ioapic_idx, pin, mp_INT); if (idx == -1) return; - irq = pin_2_irq(idx, apic_id, pin); + irq = pin_2_irq(idx, ioapic_idx, pin); /* Only handle the non legacy irqs on secondary ioapics */ - if (apic_id == 0 || irq < NR_IRQS_LEGACY) + if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY) return; - set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), + set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), irq_polarity(idx)); io_apic_setup_irq_pin_once(irq, node, &attr); @@ -1455,8 +1546,8 @@ void setup_IO_APIC_irq_extra(u32 gsi) /* * Set up the timer pin, possibly with the 8259A-master behind. */ -static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, - int vector) +static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, + unsigned int pin, int vector) { struct IO_APIC_route_entry entry; @@ -1487,45 +1578,29 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, /* * Add it to the IO-APIC irq-routing table: */ - ioapic_write_entry(apic_id, pin, entry); + ioapic_write_entry(ioapic_idx, pin, entry); } - -__apicdebuginit(void) print_IO_APIC(void) +__apicdebuginit(void) print_IO_APIC(int ioapic_idx) { - int apic, i; + int i; union IO_APIC_reg_00 reg_00; union IO_APIC_reg_01 reg_01; union IO_APIC_reg_02 reg_02; union IO_APIC_reg_03 reg_03; unsigned long flags; - struct irq_cfg *cfg; - unsigned int irq; - - printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); - for (i = 0; i < nr_ioapics; i++) - printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", - mpc_ioapic_id(i), ioapics[i].nr_registers); - - /* - * We are a bit conservative about what we expect. We have to - * know about every hardware change ASAP. - */ - printk(KERN_INFO "testing the IO APIC.......................\n"); - - for (apic = 0; apic < nr_ioapics; apic++) { raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(apic, 0); - reg_01.raw = io_apic_read(apic, 1); + reg_00.raw = io_apic_read(ioapic_idx, 0); + reg_01.raw = io_apic_read(ioapic_idx, 1); if (reg_01.bits.version >= 0x10) - reg_02.raw = io_apic_read(apic, 2); + reg_02.raw = io_apic_read(ioapic_idx, 2); if (reg_01.bits.version >= 0x20) - reg_03.raw = io_apic_read(apic, 3); + reg_03.raw = io_apic_read(ioapic_idx, 3); raw_spin_unlock_irqrestore(&ioapic_lock, flags); printk("\n"); - printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic)); + printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx)); printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); @@ -1575,7 +1650,7 @@ __apicdebuginit(void) print_IO_APIC(void) struct IO_APIC_route_entry entry; struct IR_IO_APIC_route_entry *ir_entry; - entry = ioapic_read_entry(apic, i); + entry = ioapic_read_entry(ioapic_idx, i); ir_entry = (struct IR_IO_APIC_route_entry *) &entry; printk(KERN_DEBUG " %02x %04X ", i, @@ -1596,7 +1671,7 @@ __apicdebuginit(void) print_IO_APIC(void) } else { struct IO_APIC_route_entry entry; - entry = ioapic_read_entry(apic, i); + entry = ioapic_read_entry(ioapic_idx, i); printk(KERN_DEBUG " %02x %02X ", i, entry.dest @@ -1614,7 +1689,28 @@ __apicdebuginit(void) print_IO_APIC(void) ); } } - } +} + +__apicdebuginit(void) print_IO_APICs(void) +{ + int ioapic_idx; + struct irq_cfg *cfg; + unsigned int irq; + + printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) + printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", + mpc_ioapic_id(ioapic_idx), + ioapics[ioapic_idx].nr_registers); + + /* + * We are a bit conservative about what we expect. We have to + * know about every hardware change ASAP. + */ + printk(KERN_INFO "testing the IO APIC.......................\n"); + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) + print_IO_APIC(ioapic_idx); printk(KERN_DEBUG "IRQ to pin mappings:\n"); for_each_active_irq(irq) { @@ -1633,8 +1729,6 @@ __apicdebuginit(void) print_IO_APIC(void) } printk(KERN_INFO ".................................... done.\n"); - - return; } __apicdebuginit(void) print_APIC_field(int base) @@ -1828,7 +1922,7 @@ __apicdebuginit(int) print_ICs(void) return 0; print_local_APICs(show_lapic); - print_IO_APIC(); + print_IO_APICs(); return 0; } @@ -1953,7 +2047,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) { union IO_APIC_reg_00 reg_00; physid_mask_t phys_id_present_map; - int apic_id; + int ioapic_idx; int i; unsigned char old_id; unsigned long flags; @@ -1967,21 +2061,20 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) /* * Set the IOAPIC ID to the value stored in the MPC table. */ - for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { - + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { /* Read the register 0 value */ raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(apic_id, 0); + reg_00.raw = io_apic_read(ioapic_idx, 0); raw_spin_unlock_irqrestore(&ioapic_lock, flags); - old_id = mpc_ioapic_id(apic_id); + old_id = mpc_ioapic_id(ioapic_idx); - if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) { + if (mpc_ioapic_id(ioapic_idx) >= get_physical_broadcast()) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", - apic_id, mpc_ioapic_id(apic_id)); + ioapic_idx, mpc_ioapic_id(ioapic_idx)); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", reg_00.bits.ID); - ioapics[apic_id].mp_config.apicid = reg_00.bits.ID; + ioapics[ioapic_idx].mp_config.apicid = reg_00.bits.ID; } /* @@ -1990,9 +2083,9 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) * 'stuck on smp_invalidate_needed IPI wait' messages. */ if (apic->check_apicid_used(&phys_id_present_map, - mpc_ioapic_id(apic_id))) { + mpc_ioapic_id(ioapic_idx))) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", - apic_id, mpc_ioapic_id(apic_id)); + ioapic_idx, mpc_ioapic_id(ioapic_idx)); for (i = 0; i < get_physical_broadcast(); i++) if (!physid_isset(i, phys_id_present_map)) break; @@ -2001,14 +2094,14 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); physid_set(i, phys_id_present_map); - ioapics[apic_id].mp_config.apicid = i; + ioapics[ioapic_idx].mp_config.apicid = i; } else { physid_mask_t tmp; - apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id), + apic->apicid_to_cpu_present(mpc_ioapic_id(ioapic_idx), &tmp); apic_printk(APIC_VERBOSE, "Setting %d in the " "phys_id_present_map\n", - mpc_ioapic_id(apic_id)); + mpc_ioapic_id(ioapic_idx)); physids_or(phys_id_present_map, phys_id_present_map, tmp); } @@ -2016,35 +2109,35 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void) * We need to adjust the IRQ routing table * if the ID changed. */ - if (old_id != mpc_ioapic_id(apic_id)) + if (old_id != mpc_ioapic_id(ioapic_idx)) for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].dstapic == old_id) mp_irqs[i].dstapic - = mpc_ioapic_id(apic_id); + = mpc_ioapic_id(ioapic_idx); /* * Update the ID register according to the right value * from the MPC table if they are different. */ - if (mpc_ioapic_id(apic_id) == reg_00.bits.ID) + if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID) continue; apic_printk(APIC_VERBOSE, KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mpc_ioapic_id(apic_id)); + mpc_ioapic_id(ioapic_idx)); - reg_00.bits.ID = mpc_ioapic_id(apic_id); + reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); raw_spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic_id, 0, reg_00.raw); + io_apic_write(ioapic_idx, 0, reg_00.raw); raw_spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(apic_id, 0); + reg_00.raw = io_apic_read(ioapic_idx, 0); raw_spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.bits.ID != mpc_ioapic_id(apic_id)) + if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) printk("could not set ID!\n"); else apic_printk(APIC_VERBOSE, " ok.\n"); @@ -2255,7 +2348,7 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, return ret; } -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP /* * Migrate the IO-APIC irq in the presence of intr-remapping. @@ -2267,6 +2360,9 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, * updated vector information), by using a virtual vector (io-apic pin number). * Real vector that is used for interrupting cpu will be coming from * the interrupt-remapping table entry. + * + * As the migration is a simple atomic update of IRTE, the same mechanism + * is used to migrate MSI irq's in the presence of interrupt-remapping. */ static int ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, @@ -2291,10 +2387,16 @@ ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, irte.dest_id = IRTE_DEST(dest); /* - * Modified the IRTE and flushes the Interrupt entry cache. + * Atomically updates the IRTE with the new destination, vector + * and flushes the interrupt entry cache. */ modify_irte(irq, &irte); + /* + * After this point, all the interrupts will start arriving + * at the new destination. So, time to cleanup the previous + * vector allocation. + */ if (cfg->move_in_progress) send_cleanup_vector(cfg); @@ -2407,48 +2509,6 @@ static void ack_apic_edge(struct irq_data *data) atomic_t irq_mis_count; -/* - * IO-APIC versions below 0x20 don't support EOI register. - * For the record, here is the information about various versions: - * 0Xh 82489DX - * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant - * 2Xh I/O(x)APIC which is PCI 2.2 Compliant - * 30h-FFh Reserved - * - * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic - * version as 0x2. This is an error with documentation and these ICH chips - * use io-apic's of version 0x20. - * - * For IO-APIC's with EOI register, we use that to do an explicit EOI. - * Otherwise, we simulate the EOI message manually by changing the trigger - * mode to edge and then back to level, with RTE being masked during this. -*/ -static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) -{ - struct irq_pin_list *entry; - unsigned long flags; - - raw_spin_lock_irqsave(&ioapic_lock, flags); - for_each_irq_pin(entry, cfg->irq_2_pin) { - if (mpc_ioapic_ver(entry->apic) >= 0x20) { - /* - * Intr-remapping uses pin number as the virtual vector - * in the RTE. Actual vector is programmed in - * intr-remapping table entry. Hence for the io-apic - * EOI we use the pin number. - */ - if (irq_remapped(cfg)) - io_apic_eoi(entry->apic, entry->pin); - else - io_apic_eoi(entry->apic, cfg->vector); - } else { - __mask_and_edge_IO_APIC_irq(entry); - __unmask_and_level_IO_APIC_irq(entry); - } - } - raw_spin_unlock_irqrestore(&ioapic_lock, flags); -} - static void ack_apic_level(struct irq_data *data) { struct irq_cfg *cfg = data->chip_data; @@ -2552,7 +2612,7 @@ static void ack_apic_level(struct irq_data *data) } } -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP static void ir_ack_apic_edge(struct irq_data *data) { ack_APIC_irq(); @@ -2563,7 +2623,23 @@ static void ir_ack_apic_level(struct irq_data *data) ack_APIC_irq(); eoi_ioapic_irq(data->irq, data->chip_data); } -#endif /* CONFIG_INTR_REMAP */ + +static void ir_print_prefix(struct irq_data *data, struct seq_file *p) +{ + seq_printf(p, " IR-%s", data->chip->name); +} + +static void irq_remap_modify_chip_defaults(struct irq_chip *chip) +{ + chip->irq_print_chip = ir_print_prefix; + chip->irq_ack = ir_ack_apic_edge; + chip->irq_eoi = ir_ack_apic_level; + +#ifdef CONFIG_SMP + chip->irq_set_affinity = ir_ioapic_set_affinity; +#endif +} +#endif /* CONFIG_IRQ_REMAP */ static struct irq_chip ioapic_chip __read_mostly = { .name = "IO-APIC", @@ -2578,21 +2654,6 @@ static struct irq_chip ioapic_chip __read_mostly = { .irq_retrigger = ioapic_retrigger_irq, }; -static struct irq_chip ir_ioapic_chip __read_mostly = { - .name = "IR-IO-APIC", - .irq_startup = startup_ioapic_irq, - .irq_mask = mask_ioapic_irq, - .irq_unmask = unmask_ioapic_irq, -#ifdef CONFIG_INTR_REMAP - .irq_ack = ir_ack_apic_edge, - .irq_eoi = ir_ack_apic_level, -#ifdef CONFIG_SMP - .irq_set_affinity = ir_ioapic_set_affinity, -#endif -#endif - .irq_retrigger = ioapic_retrigger_irq, -}; - static inline void init_IO_APIC_traps(void) { struct irq_cfg *cfg; @@ -2944,27 +3005,26 @@ static int __init io_apic_bug_finalize(void) late_initcall(io_apic_bug_finalize); -static void resume_ioapic_id(int ioapic_id) +static void resume_ioapic_id(int ioapic_idx) { unsigned long flags; union IO_APIC_reg_00 reg_00; - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic_id, 0); - if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) { - reg_00.bits.ID = mpc_ioapic_id(ioapic_id); - io_apic_write(ioapic_id, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic_idx, 0); + if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) { + reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); + io_apic_write(ioapic_idx, 0, reg_00.raw); } raw_spin_unlock_irqrestore(&ioapic_lock, flags); } static void ioapic_resume(void) { - int ioapic_id; + int ioapic_idx; - for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--) - resume_ioapic_id(ioapic_id); + for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--) + resume_ioapic_id(ioapic_idx); restore_ioapic_entries(); } @@ -3144,45 +3204,6 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) return 0; } -#ifdef CONFIG_INTR_REMAP -/* - * Migrate the MSI irq to another cpumask. This migration is - * done in the process context using interrupt-remapping hardware. - */ -static int -ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, - bool force) -{ - struct irq_cfg *cfg = data->chip_data; - unsigned int dest, irq = data->irq; - struct irte irte; - - if (get_irte(irq, &irte)) - return -1; - - if (__ioapic_set_affinity(data, mask, &dest)) - return -1; - - irte.vector = cfg->vector; - irte.dest_id = IRTE_DEST(dest); - - /* - * atomically update the IRTE with the new destination and vector. - */ - modify_irte(irq, &irte); - - /* - * After this point, all the interrupts will start arriving - * at the new destination. So, time to cleanup the previous - * vector allocation. - */ - if (cfg->move_in_progress) - send_cleanup_vector(cfg); - - return 0; -} - -#endif #endif /* CONFIG_SMP */ /* @@ -3200,19 +3221,6 @@ static struct irq_chip msi_chip = { .irq_retrigger = ioapic_retrigger_irq, }; -static struct irq_chip msi_ir_chip = { - .name = "IR-PCI-MSI", - .irq_unmask = unmask_msi_irq, - .irq_mask = mask_msi_irq, -#ifdef CONFIG_INTR_REMAP - .irq_ack = ir_ack_apic_edge, -#ifdef CONFIG_SMP - .irq_set_affinity = ir_msi_set_affinity, -#endif -#endif - .irq_retrigger = ioapic_retrigger_irq, -}; - /* * Map the PCI dev to the corresponding remapping hardware unit * and allocate 'nvec' consecutive interrupt-remapping table entries @@ -3255,7 +3263,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) if (irq_remapped(irq_get_chip_data(irq))) { irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); - chip = &msi_ir_chip; + irq_remap_modify_chip_defaults(chip); } irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge"); @@ -3328,7 +3336,7 @@ void native_teardown_msi_irq(unsigned int irq) destroy_irq(irq); } -#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP) +#ifdef CONFIG_DMAR_TABLE #ifdef CONFIG_SMP static int dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, @@ -3409,19 +3417,6 @@ static int hpet_msi_set_affinity(struct irq_data *data, #endif /* CONFIG_SMP */ -static struct irq_chip ir_hpet_msi_type = { - .name = "IR-HPET_MSI", - .irq_unmask = hpet_msi_unmask, - .irq_mask = hpet_msi_mask, -#ifdef CONFIG_INTR_REMAP - .irq_ack = ir_ack_apic_edge, -#ifdef CONFIG_SMP - .irq_set_affinity = ir_msi_set_affinity, -#endif -#endif - .irq_retrigger = ioapic_retrigger_irq, -}; - static struct irq_chip hpet_msi_type = { .name = "HPET_MSI", .irq_unmask = hpet_msi_unmask, @@ -3458,7 +3453,7 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id) hpet_msi_write(irq_get_handler_data(irq), &msg); irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); if (irq_remapped(irq_get_chip_data(irq))) - chip = &ir_hpet_msi_type; + irq_remap_modify_chip_defaults(chip); irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge"); return 0; @@ -3566,26 +3561,25 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) return -EINVAL; ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin); if (!ret) - setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg, - attr->trigger, attr->polarity); + setup_ioapic_irq(irq, cfg, attr); return ret; } int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr) { - unsigned int id = attr->ioapic, pin = attr->ioapic_pin; + unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin; int ret; /* Avoid redundant programming */ - if (test_bit(pin, ioapics[id].pin_programmed)) { + if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) { pr_debug("Pin %d-%d already programmed\n", - mpc_ioapic_id(id), pin); + mpc_ioapic_id(ioapic_idx), pin); return 0; } ret = io_apic_setup_irq_pin(irq, node, attr); if (!ret) - set_bit(pin, ioapics[id].pin_programmed); + set_bit(pin, ioapics[ioapic_idx].pin_programmed); return ret; } @@ -3621,7 +3615,6 @@ int get_nr_irqs_gsi(void) return nr_irqs_gsi; } -#ifdef CONFIG_SPARSE_IRQ int __init arch_probe_nr_irqs(void) { int nr; @@ -3641,7 +3634,6 @@ int __init arch_probe_nr_irqs(void) return NR_IRQS_LEGACY; } -#endif int io_apic_set_pci_routing(struct device *dev, int irq, struct io_apic_irq_attr *irq_attr) diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index b5254ad044ab..0787bb3412f4 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -200,14 +200,8 @@ void __init default_setup_apic_routing(void) * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support */ - if (!cmdline_apic && apic == &apic_default) { - struct apic *bigsmp = generic_bigsmp_probe(); - if (bigsmp) { - apic = bigsmp; - printk(KERN_INFO "Overriding APIC driver with %s\n", - apic->name); - } - } + if (!cmdline_apic && apic == &apic_default) + generic_bigsmp_probe(); #endif if (apic->setup_apic_routing) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index adc66c3a1fef..75be00ecfff2 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | APIC_DM_INIT; uv_write_global_mmr64(pnode, UVH_IPI_INT, val); - mdelay(10); val = (1UL << UVH_IPI_INT_SEND_SHFT) | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | @@ -673,18 +672,11 @@ void __cpuinit uv_cpu_init(void) /* * When NMI is received, print a stack trace. */ -int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) +int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) { unsigned long real_uv_nmi; int bid; - if (reason != DIE_NMIUNKNOWN) - return NOTIFY_OK; - - if (in_crash_kexec) - /* do nothing if entering the crash kernel */ - return NOTIFY_OK; - /* * Each blade has an MMR that indicates when an NMI has been sent * to cpus on the blade. If an NMI is detected, atomically @@ -705,7 +697,7 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) } if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count)) - return NOTIFY_DONE; + return NMI_DONE; __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count; @@ -718,17 +710,12 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) dump_stack(); spin_unlock(&uv_nmi_lock); - return NOTIFY_STOP; + return NMI_HANDLED; } -static struct notifier_block uv_dump_stack_nmi_nb = { - .notifier_call = uv_handle_nmi, - .priority = NMI_LOCAL_LOW_PRIOR - 1, -}; - void uv_register_nmi_notifier(void) { - if (register_die_notifier(&uv_dump_stack_nmi_nb)) + if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv")) printk(KERN_WARNING "UV NMI handler failed to register\n"); } diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 0371c484bb8a..a46bd383953c 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -249,8 +249,6 @@ extern int (*console_blank_hook)(int); #define APM_MINOR_DEV 134 /* - * See Documentation/Config.help for the configuration options. - * * Various options can be changed at boot time as follows: * (We allow underscores for compatibility with the modules code) * apm=on/off enable/disable APM diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 6042981d0309..fe6eb197f848 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -28,10 +28,15 @@ obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o +ifdef CONFIG_PERF_EVENTS +obj-$(CONFIG_CPU_SUP_AMD) += perf_event_amd.o +obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o +endif + obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ -obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o +obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o perf_event_amd_ibs.o quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@ diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 0ed633c5048b..6199232161cf 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -78,27 +78,20 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs) static cpumask_var_t mce_inject_cpumask; -static int mce_raise_notify(struct notifier_block *self, - unsigned long val, void *data) +static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs) { - struct die_args *args = (struct die_args *)data; int cpu = smp_processor_id(); struct mce *m = &__get_cpu_var(injectm); - if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask)) - return NOTIFY_DONE; + if (!cpumask_test_cpu(cpu, mce_inject_cpumask)) + return NMI_DONE; cpumask_clear_cpu(cpu, mce_inject_cpumask); if (m->inject_flags & MCJ_EXCEPTION) - raise_exception(m, args->regs); + raise_exception(m, regs); else if (m->status) raise_poll(m); - return NOTIFY_STOP; + return NMI_HANDLED; } -static struct notifier_block mce_raise_nb = { - .notifier_call = mce_raise_notify, - .priority = NMI_LOCAL_NORMAL_PRIOR, -}; - /* Inject mce on current CPU */ static int raise_local(void) { @@ -216,7 +209,8 @@ static int inject_init(void) return -ENOMEM; printk(KERN_INFO "Machine check injector initialized\n"); mce_chrdev_ops.write = mce_write; - register_die_notifier(&mce_raise_nb); + register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, + "mce_notify"); return 0; } diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 08363b042122..fce51ad1f362 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -908,9 +908,6 @@ void do_machine_check(struct pt_regs *regs, long error_code) percpu_inc(mce_exception_count); - if (notify_die(DIE_NMI, "machine check", regs, error_code, - 18, SIGKILL) == NOTIFY_STOP) - goto out; if (!banks) goto out; @@ -1140,6 +1137,15 @@ static void mce_start_timer(unsigned long data) add_timer_on(t, smp_processor_id()); } +/* Must not be called in IRQ context where del_timer_sync() can deadlock */ +static void mce_timer_delete_all(void) +{ + int cpu; + + for_each_online_cpu(cpu) + del_timer_sync(&per_cpu(mce_timer, cpu)); +} + static void mce_do_trigger(struct work_struct *work) { call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT); @@ -1750,7 +1756,6 @@ static struct syscore_ops mce_syscore_ops = { static void mce_cpu_restart(void *data) { - del_timer_sync(&__get_cpu_var(mce_timer)); if (!mce_available(__this_cpu_ptr(&cpu_info))) return; __mcheck_cpu_init_generic(); @@ -1760,16 +1765,15 @@ static void mce_cpu_restart(void *data) /* Reinit MCEs after user configuration changes */ static void mce_restart(void) { + mce_timer_delete_all(); on_each_cpu(mce_cpu_restart, NULL, 1); } /* Toggle features for corrected errors */ -static void mce_disable_ce(void *all) +static void mce_disable_cmci(void *data) { if (!mce_available(__this_cpu_ptr(&cpu_info))) return; - if (all) - del_timer_sync(&__get_cpu_var(mce_timer)); cmci_clear(); } @@ -1852,7 +1856,8 @@ static ssize_t set_ignore_ce(struct sys_device *s, if (mce_ignore_ce ^ !!new) { if (new) { /* disable ce features */ - on_each_cpu(mce_disable_ce, (void *)1, 1); + mce_timer_delete_all(); + on_each_cpu(mce_disable_cmci, NULL, 1); mce_ignore_ce = 1; } else { /* enable ce features */ @@ -1875,7 +1880,7 @@ static ssize_t set_cmci_disabled(struct sys_device *s, if (mce_cmci_disabled ^ !!new) { if (new) { /* disable cmci */ - on_each_cpu(mce_disable_ce, NULL, 1); + on_each_cpu(mce_disable_cmci, NULL, 1); mce_cmci_disabled = 1; } else { /* enable cmci */ diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 8694ef56459d..38e49bc95ffc 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -28,7 +28,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned); * cmci_discover_lock protects against parallel discovery attempts * which could race against each other. */ -static DEFINE_SPINLOCK(cmci_discover_lock); +static DEFINE_RAW_SPINLOCK(cmci_discover_lock); #define CMCI_THRESHOLD 1 @@ -85,7 +85,7 @@ static void cmci_discover(int banks, int boot) int hdr = 0; int i; - spin_lock_irqsave(&cmci_discover_lock, flags); + raw_spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { u64 val; @@ -116,7 +116,7 @@ static void cmci_discover(int banks, int boot) WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); } } - spin_unlock_irqrestore(&cmci_discover_lock, flags); + raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); if (hdr) printk(KERN_CONT "\n"); } @@ -150,7 +150,7 @@ void cmci_clear(void) if (!cmci_supported(&banks)) return; - spin_lock_irqsave(&cmci_discover_lock, flags); + raw_spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { if (!test_bit(i, __get_cpu_var(mce_banks_owned))) continue; @@ -160,7 +160,7 @@ void cmci_clear(void) wrmsrl(MSR_IA32_MCx_CTL2(i), val); __clear_bit(i, __get_cpu_var(mce_banks_owned)); } - spin_unlock_irqrestore(&cmci_discover_lock, flags); + raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); } /* diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 08119a37e53c..6b96110bb0c3 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -149,7 +149,6 @@ struct set_mtrr_data { */ static int mtrr_rendezvous_handler(void *info) { -#ifdef CONFIG_SMP struct set_mtrr_data *data = info; /* @@ -171,7 +170,6 @@ static int mtrr_rendezvous_handler(void *info) } else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) { mtrr_if->set_all(); } -#endif return 0; } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4ee3abf20ed6..640891014b2a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -32,6 +32,8 @@ #include <asm/smp.h> #include <asm/alternative.h> +#include "perf_event.h" + #if 0 #undef wrmsrl #define wrmsrl(msr, val) \ @@ -43,283 +45,17 @@ do { \ } while (0) #endif -/* - * | NHM/WSM | SNB | - * register ------------------------------- - * | HT | no HT | HT | no HT | - *----------------------------------------- - * offcore | core | core | cpu | core | - * lbr_sel | core | core | cpu | core | - * ld_lat | cpu | core | cpu | core | - *----------------------------------------- - * - * Given that there is a small number of shared regs, - * we can pre-allocate their slot in the per-cpu - * per-core reg tables. - */ -enum extra_reg_type { - EXTRA_REG_NONE = -1, /* not used */ - - EXTRA_REG_RSP_0 = 0, /* offcore_response_0 */ - EXTRA_REG_RSP_1 = 1, /* offcore_response_1 */ - - EXTRA_REG_MAX /* number of entries needed */ -}; - -struct event_constraint { - union { - unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; - u64 idxmsk64; - }; - u64 code; - u64 cmask; - int weight; -}; - -struct amd_nb { - int nb_id; /* NorthBridge id */ - int refcnt; /* reference count */ - struct perf_event *owners[X86_PMC_IDX_MAX]; - struct event_constraint event_constraints[X86_PMC_IDX_MAX]; -}; - -struct intel_percore; - -#define MAX_LBR_ENTRIES 16 - -struct cpu_hw_events { - /* - * Generic x86 PMC bits - */ - struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ - unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; - unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; - int enabled; - - int n_events; - int n_added; - int n_txn; - int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ - u64 tags[X86_PMC_IDX_MAX]; - struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ - - unsigned int group_flag; - - /* - * Intel DebugStore bits - */ - struct debug_store *ds; - u64 pebs_enabled; - - /* - * Intel LBR bits - */ - int lbr_users; - void *lbr_context; - struct perf_branch_stack lbr_stack; - struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES]; - - /* - * manage shared (per-core, per-cpu) registers - * used on Intel NHM/WSM/SNB - */ - struct intel_shared_regs *shared_regs; - - /* - * AMD specific bits - */ - struct amd_nb *amd_nb; -}; - -#define __EVENT_CONSTRAINT(c, n, m, w) {\ - { .idxmsk64 = (n) }, \ - .code = (c), \ - .cmask = (m), \ - .weight = (w), \ -} - -#define EVENT_CONSTRAINT(c, n, m) \ - __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n)) - -/* - * Constraint on the Event code. - */ -#define INTEL_EVENT_CONSTRAINT(c, n) \ - EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT) - -/* - * Constraint on the Event code + UMask + fixed-mask - * - * filter mask to validate fixed counter events. - * the following filters disqualify for fixed counters: - * - inv - * - edge - * - cnt-mask - * The other filters are supported by fixed counters. - * The any-thread option is supported starting with v3. - */ -#define FIXED_EVENT_CONSTRAINT(c, n) \ - EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK) - -/* - * Constraint on the Event code + UMask - */ -#define INTEL_UEVENT_CONSTRAINT(c, n) \ - EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) +struct x86_pmu x86_pmu __read_mostly; -#define EVENT_CONSTRAINT_END \ - EVENT_CONSTRAINT(0, 0, 0) - -#define for_each_event_constraint(e, c) \ - for ((e) = (c); (e)->weight; (e)++) - -/* - * Per register state. - */ -struct er_account { - raw_spinlock_t lock; /* per-core: protect structure */ - u64 config; /* extra MSR config */ - u64 reg; /* extra MSR number */ - atomic_t ref; /* reference count */ -}; - -/* - * Extra registers for specific events. - * - * Some events need large masks and require external MSRs. - * Those extra MSRs end up being shared for all events on - * a PMU and sometimes between PMU of sibling HT threads. - * In either case, the kernel needs to handle conflicting - * accesses to those extra, shared, regs. The data structure - * to manage those registers is stored in cpu_hw_event. - */ -struct extra_reg { - unsigned int event; - unsigned int msr; - u64 config_mask; - u64 valid_mask; - int idx; /* per_xxx->regs[] reg index */ -}; - -#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \ - .event = (e), \ - .msr = (ms), \ - .config_mask = (m), \ - .valid_mask = (vm), \ - .idx = EXTRA_REG_##i \ - } - -#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \ - EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx) - -#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0) - -union perf_capabilities { - struct { - u64 lbr_format : 6; - u64 pebs_trap : 1; - u64 pebs_arch_reg : 1; - u64 pebs_format : 4; - u64 smm_freeze : 1; - }; - u64 capabilities; -}; - -/* - * struct x86_pmu - generic x86 pmu - */ -struct x86_pmu { - /* - * Generic x86 PMC bits - */ - const char *name; - int version; - int (*handle_irq)(struct pt_regs *); - void (*disable_all)(void); - void (*enable_all)(int added); - void (*enable)(struct perf_event *); - void (*disable)(struct perf_event *); - int (*hw_config)(struct perf_event *event); - int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign); - unsigned eventsel; - unsigned perfctr; - u64 (*event_map)(int); - int max_events; - int num_counters; - int num_counters_fixed; - int cntval_bits; - u64 cntval_mask; - int apic; - u64 max_period; - struct event_constraint * - (*get_event_constraints)(struct cpu_hw_events *cpuc, - struct perf_event *event); - - void (*put_event_constraints)(struct cpu_hw_events *cpuc, - struct perf_event *event); - struct event_constraint *event_constraints; - void (*quirks)(void); - int perfctr_second_write; - - int (*cpu_prepare)(int cpu); - void (*cpu_starting)(int cpu); - void (*cpu_dying)(int cpu); - void (*cpu_dead)(int cpu); - - /* - * Intel Arch Perfmon v2+ - */ - u64 intel_ctrl; - union perf_capabilities intel_cap; - - /* - * Intel DebugStore bits - */ - int bts, pebs; - int bts_active, pebs_active; - int pebs_record_size; - void (*drain_pebs)(struct pt_regs *regs); - struct event_constraint *pebs_constraints; - - /* - * Intel LBR - */ - unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */ - int lbr_nr; /* hardware stack size */ - - /* - * Extra registers for events - */ - struct extra_reg *extra_regs; - unsigned int er_flags; -}; - -#define ERF_NO_HT_SHARING 1 -#define ERF_HAS_RSP_1 2 - -static struct x86_pmu x86_pmu __read_mostly; - -static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { +DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, }; -static int x86_perf_event_set_period(struct perf_event *event); - -/* - * Generalized hw caching related hw_event table, filled - * in on a per model basis. A value of 0 means - * 'not supported', -1 means 'hw_event makes no sense on - * this CPU', any other value means the raw hw_event - * ID. - */ - -#define C(x) PERF_COUNT_HW_CACHE_##x - -static u64 __read_mostly hw_cache_event_ids +u64 __read_mostly hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX]; -static u64 __read_mostly hw_cache_extra_regs +u64 __read_mostly hw_cache_extra_regs [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX]; @@ -329,8 +65,7 @@ static u64 __read_mostly hw_cache_extra_regs * Can only be executed on the CPU where the event is active. * Returns the delta events processed. */ -static u64 -x86_perf_event_update(struct perf_event *event) +u64 x86_perf_event_update(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; int shift = 64 - x86_pmu.cntval_bits; @@ -373,30 +108,6 @@ again: return new_raw_count; } -static inline int x86_pmu_addr_offset(int index) -{ - int offset; - - /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */ - alternative_io(ASM_NOP2, - "shll $1, %%eax", - X86_FEATURE_PERFCTR_CORE, - "=a" (offset), - "a" (index)); - - return offset; -} - -static inline unsigned int x86_pmu_config_addr(int index) -{ - return x86_pmu.eventsel + x86_pmu_addr_offset(index); -} - -static inline unsigned int x86_pmu_event_addr(int index) -{ - return x86_pmu.perfctr + x86_pmu_addr_offset(index); -} - /* * Find and validate any extra registers to set up. */ @@ -532,9 +243,6 @@ msr_fail: return false; } -static void reserve_ds_buffers(void); -static void release_ds_buffers(void); - static void hw_perf_event_destroy(struct perf_event *event) { if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) { @@ -583,7 +291,7 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event) return x86_pmu_extra_regs(val, event); } -static int x86_setup_perfctr(struct perf_event *event) +int x86_setup_perfctr(struct perf_event *event) { struct perf_event_attr *attr = &event->attr; struct hw_perf_event *hwc = &event->hw; @@ -647,7 +355,7 @@ static int x86_setup_perfctr(struct perf_event *event) return 0; } -static int x86_pmu_hw_config(struct perf_event *event) +int x86_pmu_hw_config(struct perf_event *event) { if (event->attr.precise_ip) { int precise = 0; @@ -723,7 +431,7 @@ static int __x86_pmu_event_init(struct perf_event *event) return x86_pmu.hw_config(event); } -static void x86_pmu_disable_all(void) +void x86_pmu_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; @@ -758,15 +466,7 @@ static void x86_pmu_disable(struct pmu *pmu) x86_pmu.disable_all(); } -static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, - u64 enable_mask) -{ - if (hwc->extra_reg.reg) - wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config); - wrmsrl(hwc->config_base, hwc->config | enable_mask); -} - -static void x86_pmu_enable_all(int added) +void x86_pmu_enable_all(int added) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; @@ -788,7 +488,7 @@ static inline int is_x86_event(struct perf_event *event) return event->pmu == &pmu; } -static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) +int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) { struct event_constraint *c, *constraints[X86_PMC_IDX_MAX]; unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; @@ -959,7 +659,6 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc, } static void x86_pmu_start(struct perf_event *event, int flags); -static void x86_pmu_stop(struct perf_event *event, int flags); static void x86_pmu_enable(struct pmu *pmu) { @@ -1031,21 +730,13 @@ static void x86_pmu_enable(struct pmu *pmu) x86_pmu.enable_all(added); } -static inline void x86_pmu_disable_event(struct perf_event *event) -{ - struct hw_perf_event *hwc = &event->hw; - - wrmsrl(hwc->config_base, hwc->config); -} - static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); /* * Set the next IRQ period, based on the hwc->period_left value. * To be called with the event disabled in hw: */ -static int -x86_perf_event_set_period(struct perf_event *event) +int x86_perf_event_set_period(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; s64 left = local64_read(&hwc->period_left); @@ -1105,7 +796,7 @@ x86_perf_event_set_period(struct perf_event *event) return ret; } -static void x86_pmu_enable_event(struct perf_event *event) +void x86_pmu_enable_event(struct perf_event *event) { if (__this_cpu_read(cpu_hw_events.enabled)) __x86_pmu_enable_event(&event->hw, @@ -1244,7 +935,7 @@ void perf_event_print_debug(void) local_irq_restore(flags); } -static void x86_pmu_stop(struct perf_event *event, int flags) +void x86_pmu_stop(struct perf_event *event, int flags) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; @@ -1297,7 +988,7 @@ static void x86_pmu_del(struct perf_event *event, int flags) perf_event_update_userpage(event); } -static int x86_pmu_handle_irq(struct pt_regs *regs) +int x86_pmu_handle_irq(struct pt_regs *regs) { struct perf_sample_data data; struct cpu_hw_events *cpuc; @@ -1367,109 +1058,28 @@ void perf_events_lapic_init(void) apic_write(APIC_LVTPC, APIC_DM_NMI); } -struct pmu_nmi_state { - unsigned int marked; - int handled; -}; - -static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi); - static int __kprobes -perf_event_nmi_handler(struct notifier_block *self, - unsigned long cmd, void *__args) +perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) { - struct die_args *args = __args; - unsigned int this_nmi; - int handled; - if (!atomic_read(&active_events)) - return NOTIFY_DONE; - - switch (cmd) { - case DIE_NMI: - break; - case DIE_NMIUNKNOWN: - this_nmi = percpu_read(irq_stat.__nmi_count); - if (this_nmi != __this_cpu_read(pmu_nmi.marked)) - /* let the kernel handle the unknown nmi */ - return NOTIFY_DONE; - /* - * This one is a PMU back-to-back nmi. Two events - * trigger 'simultaneously' raising two back-to-back - * NMIs. If the first NMI handles both, the latter - * will be empty and daze the CPU. So, we drop it to - * avoid false-positive 'unknown nmi' messages. - */ - return NOTIFY_STOP; - default: - return NOTIFY_DONE; - } - - handled = x86_pmu.handle_irq(args->regs); - if (!handled) - return NOTIFY_DONE; - - this_nmi = percpu_read(irq_stat.__nmi_count); - if ((handled > 1) || - /* the next nmi could be a back-to-back nmi */ - ((__this_cpu_read(pmu_nmi.marked) == this_nmi) && - (__this_cpu_read(pmu_nmi.handled) > 1))) { - /* - * We could have two subsequent back-to-back nmis: The - * first handles more than one counter, the 2nd - * handles only one counter and the 3rd handles no - * counter. - * - * This is the 2nd nmi because the previous was - * handling more than one counter. We will mark the - * next (3rd) and then drop it if unhandled. - */ - __this_cpu_write(pmu_nmi.marked, this_nmi + 1); - __this_cpu_write(pmu_nmi.handled, handled); - } + return NMI_DONE; - return NOTIFY_STOP; + return x86_pmu.handle_irq(regs); } -static __read_mostly struct notifier_block perf_event_nmi_notifier = { - .notifier_call = perf_event_nmi_handler, - .next = NULL, - .priority = NMI_LOCAL_LOW_PRIOR, -}; - -static struct event_constraint unconstrained; -static struct event_constraint emptyconstraint; - -static struct event_constraint * -x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) -{ - struct event_constraint *c; - - if (x86_pmu.event_constraints) { - for_each_event_constraint(c, x86_pmu.event_constraints) { - if ((event->hw.config & c->cmask) == c->code) - return c; - } - } - - return &unconstrained; -} - -#include "perf_event_amd.c" -#include "perf_event_p6.c" -#include "perf_event_p4.c" -#include "perf_event_intel_lbr.c" -#include "perf_event_intel_ds.c" -#include "perf_event_intel.c" +struct event_constraint emptyconstraint; +struct event_constraint unconstrained; static int __cpuinit x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; + struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); int ret = NOTIFY_OK; switch (action & ~CPU_TASKS_FROZEN) { case CPU_UP_PREPARE: + cpuc->kfree_on_online = NULL; if (x86_pmu.cpu_prepare) ret = x86_pmu.cpu_prepare(cpu); break; @@ -1479,6 +1089,10 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) x86_pmu.cpu_starting(cpu); break; + case CPU_ONLINE: + kfree(cpuc->kfree_on_online); + break; + case CPU_DYING: if (x86_pmu.cpu_dying) x86_pmu.cpu_dying(cpu); @@ -1557,7 +1171,7 @@ static int __init init_hw_perf_events(void) ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED; perf_events_lapic_init(); - register_die_notifier(&perf_event_nmi_notifier); + register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI"); unconstrained = (struct event_constraint) __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, @@ -1900,6 +1514,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) perf_callchain_store(entry, regs->ip); + if (!current->mm) + return; + if (perf_callchain_user32(regs, entry)) return; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h new file mode 100644 index 000000000000..b9698d40ac4b --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event.h @@ -0,0 +1,505 @@ +/* + * Performance events x86 architecture header + * + * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> + * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar + * Copyright (C) 2009 Jaswinder Singh Rajput + * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter + * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> + * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> + * Copyright (C) 2009 Google, Inc., Stephane Eranian + * + * For licencing details see kernel-base/COPYING + */ + +#include <linux/perf_event.h> + +/* + * | NHM/WSM | SNB | + * register ------------------------------- + * | HT | no HT | HT | no HT | + *----------------------------------------- + * offcore | core | core | cpu | core | + * lbr_sel | core | core | cpu | core | + * ld_lat | cpu | core | cpu | core | + *----------------------------------------- + * + * Given that there is a small number of shared regs, + * we can pre-allocate their slot in the per-cpu + * per-core reg tables. + */ +enum extra_reg_type { + EXTRA_REG_NONE = -1, /* not used */ + + EXTRA_REG_RSP_0 = 0, /* offcore_response_0 */ + EXTRA_REG_RSP_1 = 1, /* offcore_response_1 */ + + EXTRA_REG_MAX /* number of entries needed */ +}; + +struct event_constraint { + union { + unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + u64 idxmsk64; + }; + u64 code; + u64 cmask; + int weight; +}; + +struct amd_nb { + int nb_id; /* NorthBridge id */ + int refcnt; /* reference count */ + struct perf_event *owners[X86_PMC_IDX_MAX]; + struct event_constraint event_constraints[X86_PMC_IDX_MAX]; +}; + +/* The maximal number of PEBS events: */ +#define MAX_PEBS_EVENTS 4 + +/* + * A debug store configuration. + * + * We only support architectures that use 64bit fields. + */ +struct debug_store { + u64 bts_buffer_base; + u64 bts_index; + u64 bts_absolute_maximum; + u64 bts_interrupt_threshold; + u64 pebs_buffer_base; + u64 pebs_index; + u64 pebs_absolute_maximum; + u64 pebs_interrupt_threshold; + u64 pebs_event_reset[MAX_PEBS_EVENTS]; +}; + +/* + * Per register state. + */ +struct er_account { + raw_spinlock_t lock; /* per-core: protect structure */ + u64 config; /* extra MSR config */ + u64 reg; /* extra MSR number */ + atomic_t ref; /* reference count */ +}; + +/* + * Per core/cpu state + * + * Used to coordinate shared registers between HT threads or + * among events on a single PMU. + */ +struct intel_shared_regs { + struct er_account regs[EXTRA_REG_MAX]; + int refcnt; /* per-core: #HT threads */ + unsigned core_id; /* per-core: core id */ +}; + +#define MAX_LBR_ENTRIES 16 + +struct cpu_hw_events { + /* + * Generic x86 PMC bits + */ + struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ + unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + int enabled; + + int n_events; + int n_added; + int n_txn; + int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ + u64 tags[X86_PMC_IDX_MAX]; + struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ + + unsigned int group_flag; + + /* + * Intel DebugStore bits + */ + struct debug_store *ds; + u64 pebs_enabled; + + /* + * Intel LBR bits + */ + int lbr_users; + void *lbr_context; + struct perf_branch_stack lbr_stack; + struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES]; + + /* + * Intel host/guest exclude bits + */ + u64 intel_ctrl_guest_mask; + u64 intel_ctrl_host_mask; + struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX]; + + /* + * manage shared (per-core, per-cpu) registers + * used on Intel NHM/WSM/SNB + */ + struct intel_shared_regs *shared_regs; + + /* + * AMD specific bits + */ + struct amd_nb *amd_nb; + + void *kfree_on_online; +}; + +#define __EVENT_CONSTRAINT(c, n, m, w) {\ + { .idxmsk64 = (n) }, \ + .code = (c), \ + .cmask = (m), \ + .weight = (w), \ +} + +#define EVENT_CONSTRAINT(c, n, m) \ + __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n)) + +/* + * Constraint on the Event code. + */ +#define INTEL_EVENT_CONSTRAINT(c, n) \ + EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT) + +/* + * Constraint on the Event code + UMask + fixed-mask + * + * filter mask to validate fixed counter events. + * the following filters disqualify for fixed counters: + * - inv + * - edge + * - cnt-mask + * The other filters are supported by fixed counters. + * The any-thread option is supported starting with v3. + */ +#define FIXED_EVENT_CONSTRAINT(c, n) \ + EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK) + +/* + * Constraint on the Event code + UMask + */ +#define INTEL_UEVENT_CONSTRAINT(c, n) \ + EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) + +#define EVENT_CONSTRAINT_END \ + EVENT_CONSTRAINT(0, 0, 0) + +#define for_each_event_constraint(e, c) \ + for ((e) = (c); (e)->weight; (e)++) + +/* + * Extra registers for specific events. + * + * Some events need large masks and require external MSRs. + * Those extra MSRs end up being shared for all events on + * a PMU and sometimes between PMU of sibling HT threads. + * In either case, the kernel needs to handle conflicting + * accesses to those extra, shared, regs. The data structure + * to manage those registers is stored in cpu_hw_event. + */ +struct extra_reg { + unsigned int event; + unsigned int msr; + u64 config_mask; + u64 valid_mask; + int idx; /* per_xxx->regs[] reg index */ +}; + +#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \ + .event = (e), \ + .msr = (ms), \ + .config_mask = (m), \ + .valid_mask = (vm), \ + .idx = EXTRA_REG_##i \ + } + +#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \ + EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx) + +#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0) + +union perf_capabilities { + struct { + u64 lbr_format:6; + u64 pebs_trap:1; + u64 pebs_arch_reg:1; + u64 pebs_format:4; + u64 smm_freeze:1; + }; + u64 capabilities; +}; + +/* + * struct x86_pmu - generic x86 pmu + */ +struct x86_pmu { + /* + * Generic x86 PMC bits + */ + const char *name; + int version; + int (*handle_irq)(struct pt_regs *); + void (*disable_all)(void); + void (*enable_all)(int added); + void (*enable)(struct perf_event *); + void (*disable)(struct perf_event *); + int (*hw_config)(struct perf_event *event); + int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign); + unsigned eventsel; + unsigned perfctr; + u64 (*event_map)(int); + int max_events; + int num_counters; + int num_counters_fixed; + int cntval_bits; + u64 cntval_mask; + int apic; + u64 max_period; + struct event_constraint * + (*get_event_constraints)(struct cpu_hw_events *cpuc, + struct perf_event *event); + + void (*put_event_constraints)(struct cpu_hw_events *cpuc, + struct perf_event *event); + struct event_constraint *event_constraints; + void (*quirks)(void); + int perfctr_second_write; + + int (*cpu_prepare)(int cpu); + void (*cpu_starting)(int cpu); + void (*cpu_dying)(int cpu); + void (*cpu_dead)(int cpu); + + /* + * Intel Arch Perfmon v2+ + */ + u64 intel_ctrl; + union perf_capabilities intel_cap; + + /* + * Intel DebugStore bits + */ + int bts, pebs; + int bts_active, pebs_active; + int pebs_record_size; + void (*drain_pebs)(struct pt_regs *regs); + struct event_constraint *pebs_constraints; + + /* + * Intel LBR + */ + unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */ + int lbr_nr; /* hardware stack size */ + + /* + * Extra registers for events + */ + struct extra_reg *extra_regs; + unsigned int er_flags; + + /* + * Intel host/guest support (KVM) + */ + struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr); +}; + +#define ERF_NO_HT_SHARING 1 +#define ERF_HAS_RSP_1 2 + +extern struct x86_pmu x86_pmu __read_mostly; + +DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events); + +int x86_perf_event_set_period(struct perf_event *event); + +/* + * Generalized hw caching related hw_event table, filled + * in on a per model basis. A value of 0 means + * 'not supported', -1 means 'hw_event makes no sense on + * this CPU', any other value means the raw hw_event + * ID. + */ + +#define C(x) PERF_COUNT_HW_CACHE_##x + +extern u64 __read_mostly hw_cache_event_ids + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX]; +extern u64 __read_mostly hw_cache_extra_regs + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX]; + +u64 x86_perf_event_update(struct perf_event *event); + +static inline int x86_pmu_addr_offset(int index) +{ + int offset; + + /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */ + alternative_io(ASM_NOP2, + "shll $1, %%eax", + X86_FEATURE_PERFCTR_CORE, + "=a" (offset), + "a" (index)); + + return offset; +} + +static inline unsigned int x86_pmu_config_addr(int index) +{ + return x86_pmu.eventsel + x86_pmu_addr_offset(index); +} + +static inline unsigned int x86_pmu_event_addr(int index) +{ + return x86_pmu.perfctr + x86_pmu_addr_offset(index); +} + +int x86_setup_perfctr(struct perf_event *event); + +int x86_pmu_hw_config(struct perf_event *event); + +void x86_pmu_disable_all(void); + +static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, + u64 enable_mask) +{ + if (hwc->extra_reg.reg) + wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config); + wrmsrl(hwc->config_base, hwc->config | enable_mask); +} + +void x86_pmu_enable_all(int added); + +int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign); + +void x86_pmu_stop(struct perf_event *event, int flags); + +static inline void x86_pmu_disable_event(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + wrmsrl(hwc->config_base, hwc->config); +} + +void x86_pmu_enable_event(struct perf_event *event); + +int x86_pmu_handle_irq(struct pt_regs *regs); + +extern struct event_constraint emptyconstraint; + +extern struct event_constraint unconstrained; + +#ifdef CONFIG_CPU_SUP_AMD + +int amd_pmu_init(void); + +#else /* CONFIG_CPU_SUP_AMD */ + +static inline int amd_pmu_init(void) +{ + return 0; +} + +#endif /* CONFIG_CPU_SUP_AMD */ + +#ifdef CONFIG_CPU_SUP_INTEL + +int intel_pmu_save_and_restart(struct perf_event *event); + +struct event_constraint * +x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event); + +struct intel_shared_regs *allocate_shared_regs(int cpu); + +int intel_pmu_init(void); + +void init_debug_store_on_cpu(int cpu); + +void fini_debug_store_on_cpu(int cpu); + +void release_ds_buffers(void); + +void reserve_ds_buffers(void); + +extern struct event_constraint bts_constraint; + +void intel_pmu_enable_bts(u64 config); + +void intel_pmu_disable_bts(void); + +int intel_pmu_drain_bts_buffer(void); + +extern struct event_constraint intel_core2_pebs_event_constraints[]; + +extern struct event_constraint intel_atom_pebs_event_constraints[]; + +extern struct event_constraint intel_nehalem_pebs_event_constraints[]; + +extern struct event_constraint intel_westmere_pebs_event_constraints[]; + +extern struct event_constraint intel_snb_pebs_event_constraints[]; + +struct event_constraint *intel_pebs_constraints(struct perf_event *event); + +void intel_pmu_pebs_enable(struct perf_event *event); + +void intel_pmu_pebs_disable(struct perf_event *event); + +void intel_pmu_pebs_enable_all(void); + +void intel_pmu_pebs_disable_all(void); + +void intel_ds_init(void); + +void intel_pmu_lbr_reset(void); + +void intel_pmu_lbr_enable(struct perf_event *event); + +void intel_pmu_lbr_disable(struct perf_event *event); + +void intel_pmu_lbr_enable_all(void); + +void intel_pmu_lbr_disable_all(void); + +void intel_pmu_lbr_read(void); + +void intel_pmu_lbr_init_core(void); + +void intel_pmu_lbr_init_nhm(void); + +void intel_pmu_lbr_init_atom(void); + +int p4_pmu_init(void); + +int p6_pmu_init(void); + +#else /* CONFIG_CPU_SUP_INTEL */ + +static inline void reserve_ds_buffers(void) +{ +} + +static inline void release_ds_buffers(void) +{ +} + +static inline int intel_pmu_init(void) +{ + return 0; +} + +static inline struct intel_shared_regs *allocate_shared_regs(int cpu) +{ + return NULL; +} + +#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 941caa2e449b..aeefd45697a2 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -1,4 +1,10 @@ -#ifdef CONFIG_CPU_SUP_AMD +#include <linux/perf_event.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <asm/apicdef.h> + +#include "perf_event.h" static __initconst const u64 amd_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] @@ -132,6 +138,19 @@ static int amd_pmu_hw_config(struct perf_event *event) if (ret) return ret; + if (event->attr.exclude_host && event->attr.exclude_guest) + /* + * When HO == GO == 1 the hardware treats that as GO == HO == 0 + * and will count in both modes. We don't want to count in that + * case so we emulate no-counting by setting US = OS = 0. + */ + event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR | + ARCH_PERFMON_EVENTSEL_OS); + else if (event->attr.exclude_host) + event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY; + else if (event->attr.exclude_guest) + event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY; + if (event->attr.type != PERF_TYPE_RAW) return 0; @@ -350,7 +369,7 @@ static void amd_pmu_cpu_starting(int cpu) continue; if (nb->nb_id == nb_id) { - kfree(cpuc->amd_nb); + cpuc->kfree_on_online = cpuc->amd_nb; cpuc->amd_nb = nb; break; } @@ -392,7 +411,7 @@ static __initconst const struct x86_pmu amd_pmu = { .perfctr = MSR_K7_PERFCTR0, .event_map = amd_pmu_event_map, .max_events = ARRAY_SIZE(amd_perfmon_event_map), - .num_counters = 4, + .num_counters = AMD64_NUM_COUNTERS, .cntval_bits = 48, .cntval_mask = (1ULL << 48) - 1, .apic = 1, @@ -556,7 +575,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = { .perfctr = MSR_F15H_PERF_CTR, .event_map = amd_pmu_event_map, .max_events = ARRAY_SIZE(amd_perfmon_event_map), - .num_counters = 6, + .num_counters = AMD64_NUM_COUNTERS_F15H, .cntval_bits = 48, .cntval_mask = (1ULL << 48) - 1, .apic = 1, @@ -573,7 +592,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = { #endif }; -static __init int amd_pmu_init(void) +__init int amd_pmu_init(void) { /* Performance-monitoring supported from K7 and later: */ if (boot_cpu_data.x86 < 6) @@ -602,12 +621,3 @@ static __init int amd_pmu_init(void) return 0; } - -#else /* CONFIG_CPU_SUP_AMD */ - -static int amd_pmu_init(void) -{ - return 0; -} - -#endif diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c new file mode 100644 index 000000000000..ab6343d21825 --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -0,0 +1,294 @@ +/* + * Performance events - AMD IBS + * + * Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter + * + * For licencing details see kernel-base/COPYING + */ + +#include <linux/perf_event.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include <asm/apic.h> + +static u32 ibs_caps; + +#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) + +static struct pmu perf_ibs; + +static int perf_ibs_init(struct perf_event *event) +{ + if (perf_ibs.type != event->attr.type) + return -ENOENT; + return 0; +} + +static int perf_ibs_add(struct perf_event *event, int flags) +{ + return 0; +} + +static void perf_ibs_del(struct perf_event *event, int flags) +{ +} + +static struct pmu perf_ibs = { + .event_init= perf_ibs_init, + .add= perf_ibs_add, + .del= perf_ibs_del, +}; + +static __init int perf_event_ibs_init(void) +{ + if (!ibs_caps) + return -ENODEV; /* ibs not supported by the cpu */ + + perf_pmu_register(&perf_ibs, "ibs", -1); + printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps); + + return 0; +} + +#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */ + +static __init int perf_event_ibs_init(void) { return 0; } + +#endif + +/* IBS - apic initialization, for perf and oprofile */ + +static __init u32 __get_ibs_caps(void) +{ + u32 caps; + unsigned int max_level; + + if (!boot_cpu_has(X86_FEATURE_IBS)) + return 0; + + /* check IBS cpuid feature flags */ + max_level = cpuid_eax(0x80000000); + if (max_level < IBS_CPUID_FEATURES) + return IBS_CAPS_DEFAULT; + + caps = cpuid_eax(IBS_CPUID_FEATURES); + if (!(caps & IBS_CAPS_AVAIL)) + /* cpuid flags not valid */ + return IBS_CAPS_DEFAULT; + + return caps; +} + +u32 get_ibs_caps(void) +{ + return ibs_caps; +} + +EXPORT_SYMBOL(get_ibs_caps); + +static inline int get_eilvt(int offset) +{ + return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1); +} + +static inline int put_eilvt(int offset) +{ + return !setup_APIC_eilvt(offset, 0, 0, 1); +} + +/* + * Check and reserve APIC extended interrupt LVT offset for IBS if available. + */ +static inline int ibs_eilvt_valid(void) +{ + int offset; + u64 val; + int valid = 0; + + preempt_disable(); + + rdmsrl(MSR_AMD64_IBSCTL, val); + offset = val & IBSCTL_LVT_OFFSET_MASK; + + if (!(val & IBSCTL_LVT_OFFSET_VALID)) { + pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n", + smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); + goto out; + } + + if (!get_eilvt(offset)) { + pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n", + smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); + goto out; + } + + valid = 1; +out: + preempt_enable(); + + return valid; +} + +static int setup_ibs_ctl(int ibs_eilvt_off) +{ + struct pci_dev *cpu_cfg; + int nodes; + u32 value = 0; + + nodes = 0; + cpu_cfg = NULL; + do { + cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_MISC, + cpu_cfg); + if (!cpu_cfg) + break; + ++nodes; + pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off + | IBSCTL_LVT_OFFSET_VALID); + pci_read_config_dword(cpu_cfg, IBSCTL, &value); + if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) { + pci_dev_put(cpu_cfg); + printk(KERN_DEBUG "Failed to setup IBS LVT offset, " + "IBSCTL = 0x%08x\n", value); + return -EINVAL; + } + } while (1); + + if (!nodes) { + printk(KERN_DEBUG "No CPU node configured for IBS\n"); + return -ENODEV; + } + + return 0; +} + +/* + * This runs only on the current cpu. We try to find an LVT offset and + * setup the local APIC. For this we must disable preemption. On + * success we initialize all nodes with this offset. This updates then + * the offset in the IBS_CTL per-node msr. The per-core APIC setup of + * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that + * is using the new offset. + */ +static int force_ibs_eilvt_setup(void) +{ + int offset; + int ret; + + preempt_disable(); + /* find the next free available EILVT entry, skip offset 0 */ + for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { + if (get_eilvt(offset)) + break; + } + preempt_enable(); + + if (offset == APIC_EILVT_NR_MAX) { + printk(KERN_DEBUG "No EILVT entry available\n"); + return -EBUSY; + } + + ret = setup_ibs_ctl(offset); + if (ret) + goto out; + + if (!ibs_eilvt_valid()) { + ret = -EFAULT; + goto out; + } + + pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); + pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); + + return 0; +out: + preempt_disable(); + put_eilvt(offset); + preempt_enable(); + return ret; +} + +static inline int get_ibs_lvt_offset(void) +{ + u64 val; + + rdmsrl(MSR_AMD64_IBSCTL, val); + if (!(val & IBSCTL_LVT_OFFSET_VALID)) + return -EINVAL; + + return val & IBSCTL_LVT_OFFSET_MASK; +} + +static void setup_APIC_ibs(void *dummy) +{ + int offset; + + offset = get_ibs_lvt_offset(); + if (offset < 0) + goto failed; + + if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0)) + return; +failed: + pr_warn("perf: IBS APIC setup failed on cpu #%d\n", + smp_processor_id()); +} + +static void clear_APIC_ibs(void *dummy) +{ + int offset; + + offset = get_ibs_lvt_offset(); + if (offset >= 0) + setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); +} + +static int __cpuinit +perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + setup_APIC_ibs(NULL); + break; + case CPU_DYING: + clear_APIC_ibs(NULL); + break; + default: + break; + } + + return NOTIFY_OK; +} + +static __init int amd_ibs_init(void) +{ + u32 caps; + int ret; + + caps = __get_ibs_caps(); + if (!caps) + return -ENODEV; /* ibs not supported by the cpu */ + + if (!ibs_eilvt_valid()) { + ret = force_ibs_eilvt_setup(); + if (ret) { + pr_err("Failed to setup IBS, %d\n", ret); + return ret; + } + } + + get_online_cpus(); + ibs_caps = caps; + /* make ibs_caps visible to other cpus: */ + smp_mb(); + perf_cpu_notifier(perf_ibs_cpu_notifier); + smp_call_function(setup_APIC_ibs, NULL, 1); + put_online_cpus(); + + return perf_event_ibs_init(); +} + +/* Since we need the pci subsystem to init ibs we can't do this earlier: */ +device_initcall(amd_ibs_init); diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index f88af2c2a561..e09ca20e86ee 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1,16 +1,19 @@ -#ifdef CONFIG_CPU_SUP_INTEL - /* * Per core/cpu state * * Used to coordinate shared registers between HT threads or * among events on a single PMU. */ -struct intel_shared_regs { - struct er_account regs[EXTRA_REG_MAX]; - int refcnt; /* per-core: #HT threads */ - unsigned core_id; /* per-core: core id */ -}; + +#include <linux/stddef.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/slab.h> + +#include <asm/hardirq.h> +#include <asm/apic.h> + +#include "perf_event.h" /* * Intel PerfMon, used on Core and later. @@ -746,7 +749,8 @@ static void intel_pmu_enable_all(int added) intel_pmu_pebs_enable_all(); intel_pmu_lbr_enable_all(); - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, + x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask); if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { struct perf_event *event = @@ -869,6 +873,7 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc) static void intel_pmu_disable_event(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { intel_pmu_disable_bts(); @@ -876,6 +881,9 @@ static void intel_pmu_disable_event(struct perf_event *event) return; } + cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); + cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); + if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { intel_pmu_disable_fixed(hwc); return; @@ -921,6 +929,7 @@ static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) static void intel_pmu_enable_event(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { if (!__this_cpu_read(cpu_hw_events.enabled)) @@ -930,6 +939,11 @@ static void intel_pmu_enable_event(struct perf_event *event) return; } + if (event->attr.exclude_host) + cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx); + if (event->attr.exclude_guest) + cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); + if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { intel_pmu_enable_fixed(hwc); return; @@ -945,7 +959,7 @@ static void intel_pmu_enable_event(struct perf_event *event) * Save and restart an expired event. Called by NMI contexts, * so it has to be careful about preempting normal event ops: */ -static int intel_pmu_save_and_restart(struct perf_event *event) +int intel_pmu_save_and_restart(struct perf_event *event) { x86_perf_event_update(event); return x86_perf_event_set_period(event); @@ -1197,6 +1211,21 @@ intel_shared_regs_constraints(struct cpu_hw_events *cpuc, return c; } +struct event_constraint * +x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) +{ + struct event_constraint *c; + + if (x86_pmu.event_constraints) { + for_each_event_constraint(c, x86_pmu.event_constraints) { + if ((event->hw.config & c->cmask) == c->code) + return c; + } + } + + return &unconstrained; +} + static struct event_constraint * intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) { @@ -1284,12 +1313,84 @@ static int intel_pmu_hw_config(struct perf_event *event) return 0; } +struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr) +{ + if (x86_pmu.guest_get_msrs) + return x86_pmu.guest_get_msrs(nr); + *nr = 0; + return NULL; +} +EXPORT_SYMBOL_GPL(perf_guest_get_msrs); + +static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs; + + arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL; + arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask; + arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; + + *nr = 1; + return arr; +} + +static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs; + int idx; + + for (idx = 0; idx < x86_pmu.num_counters; idx++) { + struct perf_event *event = cpuc->events[idx]; + + arr[idx].msr = x86_pmu_config_addr(idx); + arr[idx].host = arr[idx].guest = 0; + + if (!test_bit(idx, cpuc->active_mask)) + continue; + + arr[idx].host = arr[idx].guest = + event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE; + + if (event->attr.exclude_host) + arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE; + else if (event->attr.exclude_guest) + arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE; + } + + *nr = x86_pmu.num_counters; + return arr; +} + +static void core_pmu_enable_event(struct perf_event *event) +{ + if (!event->attr.exclude_host) + x86_pmu_enable_event(event); +} + +static void core_pmu_enable_all(int added) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + int idx; + + for (idx = 0; idx < x86_pmu.num_counters; idx++) { + struct hw_perf_event *hwc = &cpuc->events[idx]->hw; + + if (!test_bit(idx, cpuc->active_mask) || + cpuc->events[idx]->attr.exclude_host) + continue; + + __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE); + } +} + static __initconst const struct x86_pmu core_pmu = { .name = "core", .handle_irq = x86_pmu_handle_irq, .disable_all = x86_pmu_disable_all, - .enable_all = x86_pmu_enable_all, - .enable = x86_pmu_enable_event, + .enable_all = core_pmu_enable_all, + .enable = core_pmu_enable_event, .disable = x86_pmu_disable_event, .hw_config = x86_pmu_hw_config, .schedule_events = x86_schedule_events, @@ -1307,9 +1408,10 @@ static __initconst const struct x86_pmu core_pmu = { .get_event_constraints = intel_get_event_constraints, .put_event_constraints = intel_put_event_constraints, .event_constraints = intel_core_event_constraints, + .guest_get_msrs = core_guest_get_msrs, }; -static struct intel_shared_regs *allocate_shared_regs(int cpu) +struct intel_shared_regs *allocate_shared_regs(int cpu) { struct intel_shared_regs *regs; int i; @@ -1362,7 +1464,7 @@ static void intel_pmu_cpu_starting(int cpu) pc = per_cpu(cpu_hw_events, i).shared_regs; if (pc && pc->core_id == core_id) { - kfree(cpuc->shared_regs); + cpuc->kfree_on_online = cpuc->shared_regs; cpuc->shared_regs = pc; break; } @@ -1413,6 +1515,7 @@ static __initconst const struct x86_pmu intel_pmu = { .cpu_prepare = intel_pmu_cpu_prepare, .cpu_starting = intel_pmu_cpu_starting, .cpu_dying = intel_pmu_cpu_dying, + .guest_get_msrs = intel_guest_get_msrs, }; static void intel_clovertown_quirks(void) @@ -1441,7 +1544,7 @@ static void intel_clovertown_quirks(void) x86_pmu.pebs_constraints = NULL; } -static __init int intel_pmu_init(void) +__init int intel_pmu_init(void) { union cpuid10_edx edx; union cpuid10_eax eax; @@ -1597,7 +1700,7 @@ static __init int intel_pmu_init(void) intel_pmu_lbr_init_nhm(); x86_pmu.event_constraints = intel_snb_event_constraints; - x86_pmu.pebs_constraints = intel_snb_pebs_events; + x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; x86_pmu.extra_regs = intel_snb_extra_regs; /* all extra regs are per-cpu when HT is on */ x86_pmu.er_flags |= ERF_HAS_RSP_1; @@ -1628,16 +1731,3 @@ static __init int intel_pmu_init(void) } return 0; } - -#else /* CONFIG_CPU_SUP_INTEL */ - -static int intel_pmu_init(void) -{ - return 0; -} - -static struct intel_shared_regs *allocate_shared_regs(int cpu) -{ - return NULL; -} -#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 1b1ef3addcfd..c0d238f49db8 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -1,7 +1,10 @@ -#ifdef CONFIG_CPU_SUP_INTEL +#include <linux/bitops.h> +#include <linux/types.h> +#include <linux/slab.h> -/* The maximal number of PEBS events: */ -#define MAX_PEBS_EVENTS 4 +#include <asm/perf_event.h> + +#include "perf_event.h" /* The size of a BTS record in bytes: */ #define BTS_RECORD_SIZE 24 @@ -37,24 +40,7 @@ struct pebs_record_nhm { u64 status, dla, dse, lat; }; -/* - * A debug store configuration. - * - * We only support architectures that use 64bit fields. - */ -struct debug_store { - u64 bts_buffer_base; - u64 bts_index; - u64 bts_absolute_maximum; - u64 bts_interrupt_threshold; - u64 pebs_buffer_base; - u64 pebs_index; - u64 pebs_absolute_maximum; - u64 pebs_interrupt_threshold; - u64 pebs_event_reset[MAX_PEBS_EVENTS]; -}; - -static void init_debug_store_on_cpu(int cpu) +void init_debug_store_on_cpu(int cpu) { struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; @@ -66,7 +52,7 @@ static void init_debug_store_on_cpu(int cpu) (u32)((u64)(unsigned long)ds >> 32)); } -static void fini_debug_store_on_cpu(int cpu) +void fini_debug_store_on_cpu(int cpu) { if (!per_cpu(cpu_hw_events, cpu).ds) return; @@ -175,7 +161,7 @@ static void release_ds_buffer(int cpu) kfree(ds); } -static void release_ds_buffers(void) +void release_ds_buffers(void) { int cpu; @@ -194,7 +180,7 @@ static void release_ds_buffers(void) put_online_cpus(); } -static void reserve_ds_buffers(void) +void reserve_ds_buffers(void) { int bts_err = 0, pebs_err = 0; int cpu; @@ -260,10 +246,10 @@ static void reserve_ds_buffers(void) * BTS */ -static struct event_constraint bts_constraint = +struct event_constraint bts_constraint = EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); -static void intel_pmu_enable_bts(u64 config) +void intel_pmu_enable_bts(u64 config) { unsigned long debugctlmsr; @@ -282,7 +268,7 @@ static void intel_pmu_enable_bts(u64 config) update_debugctlmsr(debugctlmsr); } -static void intel_pmu_disable_bts(void) +void intel_pmu_disable_bts(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); unsigned long debugctlmsr; @@ -299,7 +285,7 @@ static void intel_pmu_disable_bts(void) update_debugctlmsr(debugctlmsr); } -static int intel_pmu_drain_bts_buffer(void) +int intel_pmu_drain_bts_buffer(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct debug_store *ds = cpuc->ds; @@ -361,7 +347,7 @@ static int intel_pmu_drain_bts_buffer(void) /* * PEBS */ -static struct event_constraint intel_core2_pebs_event_constraints[] = { +struct event_constraint intel_core2_pebs_event_constraints[] = { INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */ INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */ @@ -370,14 +356,14 @@ static struct event_constraint intel_core2_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; -static struct event_constraint intel_atom_pebs_event_constraints[] = { +struct event_constraint intel_atom_pebs_event_constraints[] = { INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */ INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ EVENT_CONSTRAINT_END }; -static struct event_constraint intel_nehalem_pebs_event_constraints[] = { +struct event_constraint intel_nehalem_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ @@ -392,7 +378,7 @@ static struct event_constraint intel_nehalem_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; -static struct event_constraint intel_westmere_pebs_event_constraints[] = { +struct event_constraint intel_westmere_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ @@ -407,7 +393,7 @@ static struct event_constraint intel_westmere_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; -static struct event_constraint intel_snb_pebs_events[] = { +struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ @@ -428,8 +414,7 @@ static struct event_constraint intel_snb_pebs_events[] = { EVENT_CONSTRAINT_END }; -static struct event_constraint * -intel_pebs_constraints(struct perf_event *event) +struct event_constraint *intel_pebs_constraints(struct perf_event *event) { struct event_constraint *c; @@ -446,7 +431,7 @@ intel_pebs_constraints(struct perf_event *event) return &emptyconstraint; } -static void intel_pmu_pebs_enable(struct perf_event *event) +void intel_pmu_pebs_enable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; @@ -460,7 +445,7 @@ static void intel_pmu_pebs_enable(struct perf_event *event) intel_pmu_lbr_enable(event); } -static void intel_pmu_pebs_disable(struct perf_event *event) +void intel_pmu_pebs_disable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; @@ -475,7 +460,7 @@ static void intel_pmu_pebs_disable(struct perf_event *event) intel_pmu_lbr_disable(event); } -static void intel_pmu_pebs_enable_all(void) +void intel_pmu_pebs_enable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -483,7 +468,7 @@ static void intel_pmu_pebs_enable_all(void) wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); } -static void intel_pmu_pebs_disable_all(void) +void intel_pmu_pebs_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -576,8 +561,6 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) return 0; } -static int intel_pmu_save_and_restart(struct perf_event *event); - static void __intel_pmu_pebs_event(struct perf_event *event, struct pt_regs *iregs, void *__pebs) { @@ -716,7 +699,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) * BTS, PEBS probe and setup */ -static void intel_ds_init(void) +void intel_ds_init(void) { /* * No support for 32bit formats @@ -749,15 +732,3 @@ static void intel_ds_init(void) } } } - -#else /* CONFIG_CPU_SUP_INTEL */ - -static void reserve_ds_buffers(void) -{ -} - -static void release_ds_buffers(void) -{ -} - -#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index d202c1bece1a..3fab3de3ce96 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -1,4 +1,10 @@ -#ifdef CONFIG_CPU_SUP_INTEL +#include <linux/perf_event.h> +#include <linux/types.h> + +#include <asm/perf_event.h> +#include <asm/msr.h> + +#include "perf_event.h" enum { LBR_FORMAT_32 = 0x00, @@ -48,7 +54,7 @@ static void intel_pmu_lbr_reset_64(void) } } -static void intel_pmu_lbr_reset(void) +void intel_pmu_lbr_reset(void) { if (!x86_pmu.lbr_nr) return; @@ -59,7 +65,7 @@ static void intel_pmu_lbr_reset(void) intel_pmu_lbr_reset_64(); } -static void intel_pmu_lbr_enable(struct perf_event *event) +void intel_pmu_lbr_enable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -81,7 +87,7 @@ static void intel_pmu_lbr_enable(struct perf_event *event) cpuc->lbr_users++; } -static void intel_pmu_lbr_disable(struct perf_event *event) +void intel_pmu_lbr_disable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -95,7 +101,7 @@ static void intel_pmu_lbr_disable(struct perf_event *event) __intel_pmu_lbr_disable(); } -static void intel_pmu_lbr_enable_all(void) +void intel_pmu_lbr_enable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -103,7 +109,7 @@ static void intel_pmu_lbr_enable_all(void) __intel_pmu_lbr_enable(); } -static void intel_pmu_lbr_disable_all(void) +void intel_pmu_lbr_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -178,7 +184,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) cpuc->lbr_stack.nr = i; } -static void intel_pmu_lbr_read(void) +void intel_pmu_lbr_read(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -191,7 +197,7 @@ static void intel_pmu_lbr_read(void) intel_pmu_lbr_read_64(cpuc); } -static void intel_pmu_lbr_init_core(void) +void intel_pmu_lbr_init_core(void) { x86_pmu.lbr_nr = 4; x86_pmu.lbr_tos = 0x01c9; @@ -199,7 +205,7 @@ static void intel_pmu_lbr_init_core(void) x86_pmu.lbr_to = 0x60; } -static void intel_pmu_lbr_init_nhm(void) +void intel_pmu_lbr_init_nhm(void) { x86_pmu.lbr_nr = 16; x86_pmu.lbr_tos = 0x01c9; @@ -207,12 +213,10 @@ static void intel_pmu_lbr_init_nhm(void) x86_pmu.lbr_to = 0x6c0; } -static void intel_pmu_lbr_init_atom(void) +void intel_pmu_lbr_init_atom(void) { x86_pmu.lbr_nr = 8; x86_pmu.lbr_tos = 0x01c9; x86_pmu.lbr_from = 0x40; x86_pmu.lbr_to = 0x60; } - -#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 7809d2bcb209..492bf1358a7c 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -7,9 +7,13 @@ * For licencing details see kernel-base/COPYING */ -#ifdef CONFIG_CPU_SUP_INTEL +#include <linux/perf_event.h> #include <asm/perf_event_p4.h> +#include <asm/hardirq.h> +#include <asm/apic.h> + +#include "perf_event.h" #define P4_CNTR_LIMIT 3 /* @@ -1303,7 +1307,7 @@ static __initconst const struct x86_pmu p4_pmu = { .perfctr_second_write = 1, }; -static __init int p4_pmu_init(void) +__init int p4_pmu_init(void) { unsigned int low, high; @@ -1326,5 +1330,3 @@ static __init int p4_pmu_init(void) return 0; } - -#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 20c097e33860..c7181befecde 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -1,4 +1,7 @@ -#ifdef CONFIG_CPU_SUP_INTEL +#include <linux/perf_event.h> +#include <linux/types.h> + +#include "perf_event.h" /* * Not sure about some of these @@ -114,7 +117,7 @@ static __initconst const struct x86_pmu p6_pmu = { .event_constraints = p6_event_constraints, }; -static __init int p6_pmu_init(void) +__init int p6_pmu_init(void) { switch (boot_cpu_data.x86_model) { case 1: @@ -138,5 +141,3 @@ static __init int p6_pmu_init(void) return 0; } - -#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 764c7c2b1811..13ad89971d47 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -32,15 +32,12 @@ int in_crash_kexec; #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) -static void kdump_nmi_callback(int cpu, struct die_args *args) +static void kdump_nmi_callback(int cpu, struct pt_regs *regs) { - struct pt_regs *regs; #ifdef CONFIG_X86_32 struct pt_regs fixed_regs; #endif - regs = args->regs; - #ifdef CONFIG_X86_32 if (!user_mode_vm(regs)) { crash_fixup_ss_esp(&fixed_regs, regs); diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 5c1a91974918..f3f6f5344001 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -54,6 +54,7 @@ #include <asm/ftrace.h> #include <asm/irq_vectors.h> #include <asm/cpufeature.h> +#include <asm/alternative-asm.h> /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ #include <linux/elf-em.h> @@ -873,12 +874,7 @@ ENTRY(simd_coprocessor_error) 661: pushl_cfi $do_general_protection 662: .section .altinstructions,"a" - .balign 4 - .long 661b - .long 663f - .word X86_FEATURE_XMM - .byte 662b-661b - .byte 664f-663f + altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f .previous .section .altinstr_replacement,"ax" 663: pushl $do_simd_coprocessor_error diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 6419bb05ecd5..faf8d5e74b0b 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -331,10 +331,15 @@ ENDPROC(native_usergs_sysret64) 1: incl PER_CPU_VAR(irq_count) jne 2f mov PER_CPU_VAR(irq_stack_ptr),%rsp - EMPTY_FRAME 0 + CFI_DEF_CFA_REGISTER rsi 2: /* Store previous stack value */ pushq %rsi + CFI_ESCAPE 0x0f /* DW_CFA_def_cfa_expression */, 6, \ + 0x77 /* DW_OP_breg7 */, 0, \ + 0x06 /* DW_OP_deref */, \ + 0x08 /* DW_OP_const1u */, SS+8-RBP, \ + 0x22 /* DW_OP_plus */ /* We entered an interrupt context - irqs are off: */ TRACE_IRQS_OFF .endm @@ -788,7 +793,6 @@ END(interrupt) subq $ORIG_RAX-RBP, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP SAVE_ARGS_IRQ - PARTIAL_FRAME 0 call \func .endm @@ -813,10 +817,10 @@ ret_from_intr: /* Restore saved previous stack */ popq %rsi - leaq 16(%rsi), %rsp - + CFI_DEF_CFA_REGISTER rsi + leaq ARGOFFSET-RBP(%rsi), %rsp CFI_DEF_CFA_REGISTER rsp - CFI_ADJUST_CFA_OFFSET -16 + CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET exit_intr: GET_THREAD_INFO(%rcx) diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index 3fee346ef545..cacdd46d184d 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c @@ -42,7 +42,7 @@ void arch_jump_label_transform(struct jump_entry *entry, put_online_cpus(); } -void arch_jump_label_text_poke_early(jump_label_t addr) +void __init_or_module arch_jump_label_text_poke_early(jump_label_t addr) { text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE); diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 00354d4919a9..faba5771acad 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -511,28 +511,37 @@ single_step_cont(struct pt_regs *regs, struct die_args *args) static int was_in_debug_nmi[NR_CPUS]; -static int __kgdb_notify(struct die_args *args, unsigned long cmd) +static int kgdb_nmi_handler(unsigned int cmd, struct pt_regs *regs) { - struct pt_regs *regs = args->regs; - switch (cmd) { - case DIE_NMI: + case NMI_LOCAL: if (atomic_read(&kgdb_active) != -1) { /* KGDB CPU roundup */ kgdb_nmicallback(raw_smp_processor_id(), regs); was_in_debug_nmi[raw_smp_processor_id()] = 1; touch_nmi_watchdog(); - return NOTIFY_STOP; + return NMI_HANDLED; } - return NOTIFY_DONE; + break; - case DIE_NMIUNKNOWN: + case NMI_UNKNOWN: if (was_in_debug_nmi[raw_smp_processor_id()]) { was_in_debug_nmi[raw_smp_processor_id()] = 0; - return NOTIFY_STOP; + return NMI_HANDLED; } - return NOTIFY_DONE; + break; + default: + /* do nothing */ + break; + } + return NMI_DONE; +} + +static int __kgdb_notify(struct die_args *args, unsigned long cmd) +{ + struct pt_regs *regs = args->regs; + switch (cmd) { case DIE_DEBUG: if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { if (user_mode(regs)) @@ -590,11 +599,6 @@ kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) static struct notifier_block kgdb_notifier = { .notifier_call = kgdb_notify, - - /* - * Lowest-prio notifier priority, we want to be notified last: - */ - .priority = NMI_LOCAL_LOW_PRIOR, }; /** @@ -605,7 +609,31 @@ static struct notifier_block kgdb_notifier = { */ int kgdb_arch_init(void) { - return register_die_notifier(&kgdb_notifier); + int retval; + + retval = register_die_notifier(&kgdb_notifier); + if (retval) + goto out; + + retval = register_nmi_handler(NMI_LOCAL, kgdb_nmi_handler, + 0, "kgdb"); + if (retval) + goto out1; + + retval = register_nmi_handler(NMI_UNKNOWN, kgdb_nmi_handler, + 0, "kgdb"); + + if (retval) + goto out2; + + return retval; + +out2: + unregister_nmi_handler(NMI_LOCAL, "kgdb"); +out1: + unregister_die_notifier(&kgdb_notifier); +out: + return retval; } static void kgdb_hw_overflow_handler(struct perf_event *event, @@ -673,6 +701,8 @@ void kgdb_arch_exit(void) breakinfo[i].pev = NULL; } } + unregister_nmi_handler(NMI_UNKNOWN, "kgdb"); + unregister_nmi_handler(NMI_LOCAL, "kgdb"); unregister_die_notifier(&kgdb_notifier); } diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index f1a6244d7d93..7da647d8b64c 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -75,8 +75,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); /* * Undefined/reserved opcodes, conditional jump, Opcode Extension * Groups, and some special opcodes can not boost. + * This is non-const and volatile to keep gcc from statically + * optimizing it out, as variable_test_bit makes gcc think only + * *(unsigned long*) is used. */ -static const u32 twobyte_is_boostable[256 / 32] = { +static volatile u32 twobyte_is_boostable[256 / 32] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ---------------------------------------------- */ W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */ diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c new file mode 100644 index 000000000000..7ec5bd140b87 --- /dev/null +++ b/arch/x86/kernel/nmi.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs + * Copyright (C) 2011 Don Zickus Red Hat, Inc. + * + * Pentium III FXSR, SSE support + * Gareth Hughes <gareth@valinux.com>, May 2000 + */ + +/* + * Handle hardware traps and faults. + */ +#include <linux/spinlock.h> +#include <linux/kprobes.h> +#include <linux/kdebug.h> +#include <linux/nmi.h> +#include <linux/delay.h> +#include <linux/hardirq.h> +#include <linux/slab.h> + +#include <linux/mca.h> + +#if defined(CONFIG_EDAC) +#include <linux/edac.h> +#endif + +#include <linux/atomic.h> +#include <asm/traps.h> +#include <asm/mach_traps.h> +#include <asm/nmi.h> + +#define NMI_MAX_NAMELEN 16 +struct nmiaction { + struct list_head list; + nmi_handler_t handler; + unsigned int flags; + char *name; +}; + +struct nmi_desc { + spinlock_t lock; + struct list_head head; +}; + +static struct nmi_desc nmi_desc[NMI_MAX] = +{ + { + .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[0].lock), + .head = LIST_HEAD_INIT(nmi_desc[0].head), + }, + { + .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock), + .head = LIST_HEAD_INIT(nmi_desc[1].head), + }, + +}; + +struct nmi_stats { + unsigned int normal; + unsigned int unknown; + unsigned int external; + unsigned int swallow; +}; + +static DEFINE_PER_CPU(struct nmi_stats, nmi_stats); + +static int ignore_nmis; + +int unknown_nmi_panic; +/* + * Prevent NMI reason port (0x61) being accessed simultaneously, can + * only be used in NMI handler. + */ +static DEFINE_RAW_SPINLOCK(nmi_reason_lock); + +static int __init setup_unknown_nmi_panic(char *str) +{ + unknown_nmi_panic = 1; + return 1; +} +__setup("unknown_nmi_panic", setup_unknown_nmi_panic); + +#define nmi_to_desc(type) (&nmi_desc[type]) + +static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b) +{ + struct nmi_desc *desc = nmi_to_desc(type); + struct nmiaction *a; + int handled=0; + + rcu_read_lock(); + + /* + * NMIs are edge-triggered, which means if you have enough + * of them concurrently, you can lose some because only one + * can be latched at any given time. Walk the whole list + * to handle those situations. + */ + list_for_each_entry_rcu(a, &desc->head, list) + handled += a->handler(type, regs); + + rcu_read_unlock(); + + /* return total number of NMI events handled */ + return handled; +} + +static int __setup_nmi(unsigned int type, struct nmiaction *action) +{ + struct nmi_desc *desc = nmi_to_desc(type); + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + + /* + * most handlers of type NMI_UNKNOWN never return because + * they just assume the NMI is theirs. Just a sanity check + * to manage expectations + */ + WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head)); + + /* + * some handlers need to be executed first otherwise a fake + * event confuses some handlers (kdump uses this flag) + */ + if (action->flags & NMI_FLAG_FIRST) + list_add_rcu(&action->list, &desc->head); + else + list_add_tail_rcu(&action->list, &desc->head); + + spin_unlock_irqrestore(&desc->lock, flags); + return 0; +} + +static struct nmiaction *__free_nmi(unsigned int type, const char *name) +{ + struct nmi_desc *desc = nmi_to_desc(type); + struct nmiaction *n; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + + list_for_each_entry_rcu(n, &desc->head, list) { + /* + * the name passed in to describe the nmi handler + * is used as the lookup key + */ + if (!strcmp(n->name, name)) { + WARN(in_nmi(), + "Trying to free NMI (%s) from NMI context!\n", n->name); + list_del_rcu(&n->list); + break; + } + } + + spin_unlock_irqrestore(&desc->lock, flags); + synchronize_rcu(); + return (n); +} + +int register_nmi_handler(unsigned int type, nmi_handler_t handler, + unsigned long nmiflags, const char *devname) +{ + struct nmiaction *action; + int retval = -ENOMEM; + + if (!handler) + return -EINVAL; + + action = kzalloc(sizeof(struct nmiaction), GFP_KERNEL); + if (!action) + goto fail_action; + + action->handler = handler; + action->flags = nmiflags; + action->name = kstrndup(devname, NMI_MAX_NAMELEN, GFP_KERNEL); + if (!action->name) + goto fail_action_name; + + retval = __setup_nmi(type, action); + + if (retval) + goto fail_setup_nmi; + + return retval; + +fail_setup_nmi: + kfree(action->name); +fail_action_name: + kfree(action); +fail_action: + + return retval; +} +EXPORT_SYMBOL_GPL(register_nmi_handler); + +void unregister_nmi_handler(unsigned int type, const char *name) +{ + struct nmiaction *a; + + a = __free_nmi(type, name); + if (a) { + kfree(a->name); + kfree(a); + } +} + +EXPORT_SYMBOL_GPL(unregister_nmi_handler); + +static notrace __kprobes void +pci_serr_error(unsigned char reason, struct pt_regs *regs) +{ + pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n", + reason, smp_processor_id()); + + /* + * On some machines, PCI SERR line is used to report memory + * errors. EDAC makes use of it. + */ +#if defined(CONFIG_EDAC) + if (edac_handler_set()) { + edac_atomic_assert_error(); + return; + } +#endif + + if (panic_on_unrecovered_nmi) + panic("NMI: Not continuing"); + + pr_emerg("Dazed and confused, but trying to continue\n"); + + /* Clear and disable the PCI SERR error line. */ + reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR; + outb(reason, NMI_REASON_PORT); +} + +static notrace __kprobes void +io_check_error(unsigned char reason, struct pt_regs *regs) +{ + unsigned long i; + + pr_emerg( + "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n", + reason, smp_processor_id()); + show_registers(regs); + + if (panic_on_io_nmi) + panic("NMI IOCK error: Not continuing"); + + /* Re-enable the IOCK line, wait for a few seconds */ + reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK; + outb(reason, NMI_REASON_PORT); + + i = 20000; + while (--i) { + touch_nmi_watchdog(); + udelay(100); + } + + reason &= ~NMI_REASON_CLEAR_IOCHK; + outb(reason, NMI_REASON_PORT); +} + +static notrace __kprobes void +unknown_nmi_error(unsigned char reason, struct pt_regs *regs) +{ + int handled; + + /* + * Use 'false' as back-to-back NMIs are dealt with one level up. + * Of course this makes having multiple 'unknown' handlers useless + * as only the first one is ever run (unless it can actually determine + * if it caused the NMI) + */ + handled = nmi_handle(NMI_UNKNOWN, regs, false); + if (handled) { + __this_cpu_add(nmi_stats.unknown, handled); + return; + } + + __this_cpu_add(nmi_stats.unknown, 1); + +#ifdef CONFIG_MCA + /* + * Might actually be able to figure out what the guilty party + * is: + */ + if (MCA_bus) { + mca_handle_nmi(); + return; + } +#endif + pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", + reason, smp_processor_id()); + + pr_emerg("Do you have a strange power saving mode enabled?\n"); + if (unknown_nmi_panic || panic_on_unrecovered_nmi) + panic("NMI: Not continuing"); + + pr_emerg("Dazed and confused, but trying to continue\n"); +} + +static DEFINE_PER_CPU(bool, swallow_nmi); +static DEFINE_PER_CPU(unsigned long, last_nmi_rip); + +static notrace __kprobes void default_do_nmi(struct pt_regs *regs) +{ + unsigned char reason = 0; + int handled; + bool b2b = false; + + /* + * CPU-specific NMI must be processed before non-CPU-specific + * NMI, otherwise we may lose it, because the CPU-specific + * NMI can not be detected/processed on other CPUs. + */ + + /* + * Back-to-back NMIs are interesting because they can either + * be two NMI or more than two NMIs (any thing over two is dropped + * due to NMI being edge-triggered). If this is the second half + * of the back-to-back NMI, assume we dropped things and process + * more handlers. Otherwise reset the 'swallow' NMI behaviour + */ + if (regs->ip == __this_cpu_read(last_nmi_rip)) + b2b = true; + else + __this_cpu_write(swallow_nmi, false); + + __this_cpu_write(last_nmi_rip, regs->ip); + + handled = nmi_handle(NMI_LOCAL, regs, b2b); + __this_cpu_add(nmi_stats.normal, handled); + if (handled) { + /* + * There are cases when a NMI handler handles multiple + * events in the current NMI. One of these events may + * be queued for in the next NMI. Because the event is + * already handled, the next NMI will result in an unknown + * NMI. Instead lets flag this for a potential NMI to + * swallow. + */ + if (handled > 1) + __this_cpu_write(swallow_nmi, true); + return; + } + + /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ + raw_spin_lock(&nmi_reason_lock); + reason = get_nmi_reason(); + + if (reason & NMI_REASON_MASK) { + if (reason & NMI_REASON_SERR) + pci_serr_error(reason, regs); + else if (reason & NMI_REASON_IOCHK) + io_check_error(reason, regs); +#ifdef CONFIG_X86_32 + /* + * Reassert NMI in case it became active + * meanwhile as it's edge-triggered: + */ + reassert_nmi(); +#endif + __this_cpu_add(nmi_stats.external, 1); + raw_spin_unlock(&nmi_reason_lock); + return; + } + raw_spin_unlock(&nmi_reason_lock); + + /* + * Only one NMI can be latched at a time. To handle + * this we may process multiple nmi handlers at once to + * cover the case where an NMI is dropped. The downside + * to this approach is we may process an NMI prematurely, + * while its real NMI is sitting latched. This will cause + * an unknown NMI on the next run of the NMI processing. + * + * We tried to flag that condition above, by setting the + * swallow_nmi flag when we process more than one event. + * This condition is also only present on the second half + * of a back-to-back NMI, so we flag that condition too. + * + * If both are true, we assume we already processed this + * NMI previously and we swallow it. Otherwise we reset + * the logic. + * + * There are scenarios where we may accidentally swallow + * a 'real' unknown NMI. For example, while processing + * a perf NMI another perf NMI comes in along with a + * 'real' unknown NMI. These two NMIs get combined into + * one (as descibed above). When the next NMI gets + * processed, it will be flagged by perf as handled, but + * noone will know that there was a 'real' unknown NMI sent + * also. As a result it gets swallowed. Or if the first + * perf NMI returns two events handled then the second + * NMI will get eaten by the logic below, again losing a + * 'real' unknown NMI. But this is the best we can do + * for now. + */ + if (b2b && __this_cpu_read(swallow_nmi)) + __this_cpu_add(nmi_stats.swallow, 1); + else + unknown_nmi_error(reason, regs); +} + +dotraplinkage notrace __kprobes void +do_nmi(struct pt_regs *regs, long error_code) +{ + nmi_enter(); + + inc_irq_stat(__nmi_count); + + if (!ignore_nmis) + default_do_nmi(regs); + + nmi_exit(); +} + +void stop_nmi(void) +{ + ignore_nmis++; +} + +void restart_nmi(void) +{ + ignore_nmis--; +} + +/* reset the back-to-back NMI logic */ +void local_touch_nmi(void) +{ + __this_cpu_write(last_nmi_rip, 0); +} diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index b49d00da2aed..622872054fbe 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -117,8 +117,8 @@ again: } /* - * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter - * documentation. + * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel + * parameter documentation. */ static __init int iommu_setup(char *p) { diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 7a3b65107a27..795b79f984c2 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -57,6 +57,7 @@ #include <asm/idle.h> #include <asm/syscalls.h> #include <asm/debugreg.h> +#include <asm/nmi.h> asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -107,6 +108,7 @@ void cpu_idle(void) if (cpu_is_offline(cpu)) play_dead(); + local_touch_nmi(); local_irq_disable(); /* Don't trace irqs off for idle */ stop_critical_timings(); @@ -262,7 +264,7 @@ EXPORT_SYMBOL_GPL(start_thread); /* - * switch_to(x,yn) should switch tasks from x to y. + * switch_to(x,y) should switch tasks from x to y. * * We fsave/fwait so that an exception goes off at the right time * (as a call from the fsave or fwait in effect) rather than to diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index f693e44e1bf6..3bd7e6eebf31 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -51,6 +51,7 @@ #include <asm/idle.h> #include <asm/syscalls.h> #include <asm/debugreg.h> +#include <asm/nmi.h> asmlinkage extern void ret_from_fork(void); @@ -133,6 +134,7 @@ void cpu_idle(void) * from here on, until they go to idle. * Otherwise, idle callbacks can misfire. */ + local_touch_nmi(); local_irq_disable(); enter_idle(); /* Don't trace irqs off for idle */ diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 9242436e9937..e334be1182b9 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -464,7 +464,7 @@ static inline void kb_wait(void) } } -static void vmxoff_nmi(int cpu, struct die_args *args) +static void vmxoff_nmi(int cpu, struct pt_regs *regs) { cpu_emergency_vmxoff(); } @@ -736,14 +736,10 @@ static nmi_shootdown_cb shootdown_callback; static atomic_t waiting_for_crash_ipi; -static int crash_nmi_callback(struct notifier_block *self, - unsigned long val, void *data) +static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) { int cpu; - if (val != DIE_NMI) - return NOTIFY_OK; - cpu = raw_smp_processor_id(); /* Don't do anything if this handler is invoked on crashing cpu. @@ -751,10 +747,10 @@ static int crash_nmi_callback(struct notifier_block *self, * an NMI if system was initially booted with nmi_watchdog parameter. */ if (cpu == crashing_cpu) - return NOTIFY_STOP; + return NMI_HANDLED; local_irq_disable(); - shootdown_callback(cpu, (struct die_args *)data); + shootdown_callback(cpu, regs); atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ @@ -762,7 +758,7 @@ static int crash_nmi_callback(struct notifier_block *self, for (;;) cpu_relax(); - return 1; + return NMI_HANDLED; } static void smp_send_nmi_allbutself(void) @@ -770,12 +766,6 @@ static void smp_send_nmi_allbutself(void) apic->send_IPI_allbutself(NMI_VECTOR); } -static struct notifier_block crash_nmi_nb = { - .notifier_call = crash_nmi_callback, - /* we want to be the first one called */ - .priority = NMI_LOCAL_HIGH_PRIOR+1, -}; - /* Halt all other CPUs, calling the specified function on each of them * * This function can be used to halt all other CPUs on crash @@ -794,7 +784,8 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); /* Would it be better to replace the trap vector here? */ - if (register_die_notifier(&crash_nmi_nb)) + if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback, + NMI_FLAG_FIRST, "crash")) return; /* return what? */ /* Ensure the new callback function is set before sending * out the NMI diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 3f2ad2640d85..ccdbc16b8941 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -42,8 +42,11 @@ int mach_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + unsigned long flags; int retval = 0; + spin_lock_irqsave(&rtc_lock, flags); + /* tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -93,12 +96,17 @@ int mach_set_rtc_mmss(unsigned long nowtime) CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock_irqrestore(&rtc_lock, flags); + return retval; } unsigned long mach_get_cmos_time(void) { unsigned int status, year, mon, day, hour, min, sec, century = 0; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); /* * If UIP is clear, then we have >= 244 microseconds before @@ -125,6 +133,8 @@ unsigned long mach_get_cmos_time(void) status = CMOS_READ(RTC_CONTROL); WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY)); + spin_unlock_irqrestore(&rtc_lock, flags); + if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) { sec = bcd2bin(sec); min = bcd2bin(min); @@ -169,24 +179,15 @@ EXPORT_SYMBOL(rtc_cmos_write); int update_persistent_clock(struct timespec now) { - unsigned long flags; - int retval; - - spin_lock_irqsave(&rtc_lock, flags); - retval = x86_platform.set_wallclock(now.tv_sec); - spin_unlock_irqrestore(&rtc_lock, flags); - - return retval; + return x86_platform.set_wallclock(now.tv_sec); } /* not static: needed by APM */ void read_persistent_clock(struct timespec *ts) { - unsigned long retval, flags; + unsigned long retval; - spin_lock_irqsave(&rtc_lock, flags); retval = x86_platform.get_wallclock(); - spin_unlock_irqrestore(&rtc_lock, flags); ts->tv_sec = retval; ts->tv_nsec = 0; diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index fbb0a045a1a2..bc19be332bc9 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -168,7 +168,7 @@ ENTRY(sys_call_table) .long ptregs_vm86 .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* Old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 6913369c234c..a8e3eb83466c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -81,15 +81,6 @@ gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, }; DECLARE_BITMAP(used_vectors, NR_VECTORS); EXPORT_SYMBOL_GPL(used_vectors); -static int ignore_nmis; - -int unknown_nmi_panic; -/* - * Prevent NMI reason port (0x61) being accessed simultaneously, can - * only be used in NMI handler. - */ -static DEFINE_RAW_SPINLOCK(nmi_reason_lock); - static inline void conditional_sti(struct pt_regs *regs) { if (regs->flags & X86_EFLAGS_IF) @@ -307,152 +298,6 @@ gp_in_kernel: die("general protection fault", regs, error_code); } -static int __init setup_unknown_nmi_panic(char *str) -{ - unknown_nmi_panic = 1; - return 1; -} -__setup("unknown_nmi_panic", setup_unknown_nmi_panic); - -static notrace __kprobes void -pci_serr_error(unsigned char reason, struct pt_regs *regs) -{ - pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n", - reason, smp_processor_id()); - - /* - * On some machines, PCI SERR line is used to report memory - * errors. EDAC makes use of it. - */ -#if defined(CONFIG_EDAC) - if (edac_handler_set()) { - edac_atomic_assert_error(); - return; - } -#endif - - if (panic_on_unrecovered_nmi) - panic("NMI: Not continuing"); - - pr_emerg("Dazed and confused, but trying to continue\n"); - - /* Clear and disable the PCI SERR error line. */ - reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR; - outb(reason, NMI_REASON_PORT); -} - -static notrace __kprobes void -io_check_error(unsigned char reason, struct pt_regs *regs) -{ - unsigned long i; - - pr_emerg( - "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n", - reason, smp_processor_id()); - show_registers(regs); - - if (panic_on_io_nmi) - panic("NMI IOCK error: Not continuing"); - - /* Re-enable the IOCK line, wait for a few seconds */ - reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK; - outb(reason, NMI_REASON_PORT); - - i = 20000; - while (--i) { - touch_nmi_watchdog(); - udelay(100); - } - - reason &= ~NMI_REASON_CLEAR_IOCHK; - outb(reason, NMI_REASON_PORT); -} - -static notrace __kprobes void -unknown_nmi_error(unsigned char reason, struct pt_regs *regs) -{ - if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == - NOTIFY_STOP) - return; -#ifdef CONFIG_MCA - /* - * Might actually be able to figure out what the guilty party - * is: - */ - if (MCA_bus) { - mca_handle_nmi(); - return; - } -#endif - pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", - reason, smp_processor_id()); - - pr_emerg("Do you have a strange power saving mode enabled?\n"); - if (unknown_nmi_panic || panic_on_unrecovered_nmi) - panic("NMI: Not continuing"); - - pr_emerg("Dazed and confused, but trying to continue\n"); -} - -static notrace __kprobes void default_do_nmi(struct pt_regs *regs) -{ - unsigned char reason = 0; - - /* - * CPU-specific NMI must be processed before non-CPU-specific - * NMI, otherwise we may lose it, because the CPU-specific - * NMI can not be detected/processed on other CPUs. - */ - if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP) - return; - - /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ - raw_spin_lock(&nmi_reason_lock); - reason = get_nmi_reason(); - - if (reason & NMI_REASON_MASK) { - if (reason & NMI_REASON_SERR) - pci_serr_error(reason, regs); - else if (reason & NMI_REASON_IOCHK) - io_check_error(reason, regs); -#ifdef CONFIG_X86_32 - /* - * Reassert NMI in case it became active - * meanwhile as it's edge-triggered: - */ - reassert_nmi(); -#endif - raw_spin_unlock(&nmi_reason_lock); - return; - } - raw_spin_unlock(&nmi_reason_lock); - - unknown_nmi_error(reason, regs); -} - -dotraplinkage notrace __kprobes void -do_nmi(struct pt_regs *regs, long error_code) -{ - nmi_enter(); - - inc_irq_stat(__nmi_count); - - if (!ignore_nmis) - default_do_nmi(regs); - - nmi_exit(); -} - -void stop_nmi(void) -{ - ignore_nmis++; -} - -void restart_nmi(void) -{ - ignore_nmis--; -} - /* May run on IST stack. */ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) { diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 18ae83dd1cd7..b56c65de384d 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -56,7 +56,7 @@ DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) = .lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock), }; -static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE; +static enum { EMULATE, NATIVE, NONE } vsyscall_mode = NATIVE; static int __init vsyscall_setup(char *str) { diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 6f08bc940fa8..8b4cc5f067de 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3603,7 +3603,7 @@ done_prefixes: break; case Src2CL: ctxt->src2.bytes = 1; - ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0x8; + ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0xff; break; case Src2ImmByte: rc = decode_imm(ctxt, &ctxt->src2, 1, true); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 1c5b69373a00..8e8da7960dbe 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -400,7 +400,8 @@ static u64 __update_clear_spte_slow(u64 *sptep, u64 spte) /* xchg acts as a barrier before the setting of the high bits */ orig.spte_low = xchg(&ssptep->spte_low, sspte.spte_low); - orig.spte_high = ssptep->spte_high = sspte.spte_high; + orig.spte_high = ssptep->spte_high; + ssptep->spte_high = sspte.spte_high; count_spte_clear(sptep, spte); return orig.spte; diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 9f33b984d0ef..374562ed6704 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c @@ -22,14 +22,23 @@ #include <asm/inat.h> #include <asm/insn.h> -#define get_next(t, insn) \ - ({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; }) +/* Verify next sizeof(t) bytes can be on the same instruction */ +#define validate_next(t, insn, n) \ + ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE) + +#define __get_next(t, insn) \ + ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; }) + +#define __peek_nbyte_next(t, insn, n) \ + ({ t r = *(t*)((insn)->next_byte + n); r; }) -#define peek_next(t, insn) \ - ({t r; r = *(t*)insn->next_byte; r; }) +#define get_next(t, insn) \ + ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) #define peek_nbyte_next(t, insn, n) \ - ({t r; r = *(t*)((insn)->next_byte + n); r; }) + ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); }) + +#define peek_next(t, insn) peek_nbyte_next(t, insn, 0) /** * insn_init() - initialize struct insn @@ -158,6 +167,8 @@ vex_end: insn->vex_prefix.got = 1; prefixes->got = 1; + +err_out: return; } @@ -208,6 +219,9 @@ void insn_get_opcode(struct insn *insn) insn->attr = 0; /* This instruction is bad */ end: opcode->got = 1; + +err_out: + return; } /** @@ -241,6 +255,9 @@ void insn_get_modrm(struct insn *insn) if (insn->x86_64 && inat_is_force64(insn->attr)) insn->opnd_bytes = 8; modrm->got = 1; + +err_out: + return; } @@ -290,6 +307,9 @@ void insn_get_sib(struct insn *insn) } } insn->sib.got = 1; + +err_out: + return; } @@ -351,6 +371,9 @@ void insn_get_displacement(struct insn *insn) } out: insn->displacement.got = 1; + +err_out: + return; } /* Decode moffset16/32/64 */ @@ -373,6 +396,9 @@ static void __get_moffset(struct insn *insn) break; } insn->moffset1.got = insn->moffset2.got = 1; + +err_out: + return; } /* Decode imm v32(Iz) */ @@ -389,6 +415,9 @@ static void __get_immv32(struct insn *insn) insn->immediate.nbytes = 4; break; } + +err_out: + return; } /* Decode imm v64(Iv/Ov) */ @@ -411,6 +440,9 @@ static void __get_immv(struct insn *insn) break; } insn->immediate1.got = insn->immediate2.got = 1; + +err_out: + return; } /* Decode ptr16:16/32(Ap) */ @@ -432,6 +464,9 @@ static void __get_immptr(struct insn *insn) insn->immediate2.value = get_next(unsigned short, insn); insn->immediate2.nbytes = 2; insn->immediate1.got = insn->immediate2.got = 1; + +err_out: + return; } /** @@ -496,6 +531,9 @@ void insn_get_immediate(struct insn *insn) } done: insn->immediate.got = 1; + +err_out: + return; } /** diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 0d17c8c50acd..9c7378df740a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -420,12 +420,14 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) return 0; } +#ifdef CONFIG_CPU_SUP_AMD static const char errata93_warning[] = KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n" "******* Working around it, but it may cause SEGVs or burn power.\n" "******* Please consider a BIOS update.\n" "******* Disabling USB legacy in the BIOS may also help.\n"; +#endif /* * No vm86 mode in 64-bit mode: @@ -505,7 +507,11 @@ bad: */ static int is_errata93(struct pt_regs *regs, unsigned long address) { -#ifdef CONFIG_X86_64 +#if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD) + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD + || boot_cpu_data.x86 != 0xf) + return 0; + if (address != regs->ip) return 0; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 30326443ab81..87488b93a65c 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -63,9 +63,8 @@ static void __init find_early_table_space(unsigned long end, int use_pse, #ifdef CONFIG_X86_32 /* for fixmap */ tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE); - - good_end = max_pfn_mapped << PAGE_SHIFT; #endif + good_end = max_pfn_mapped << PAGE_SHIFT; base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE); if (base == MEMBLOCK_ERROR) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 68894fdc034b..75f9528e0372 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -61,26 +61,15 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, } -static int profile_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) +static int profile_exceptions_notify(unsigned int val, struct pt_regs *regs) { - struct die_args *args = (struct die_args *)data; - int ret = NOTIFY_DONE; - - switch (val) { - case DIE_NMI: - if (ctr_running) - model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs)); - else if (!nmi_enabled) - break; - else - model->stop(&__get_cpu_var(cpu_msrs)); - ret = NOTIFY_STOP; - break; - default: - break; - } - return ret; + if (ctr_running) + model->check_ctrs(regs, &__get_cpu_var(cpu_msrs)); + else if (!nmi_enabled) + return NMI_DONE; + else + model->stop(&__get_cpu_var(cpu_msrs)); + return NMI_HANDLED; } static void nmi_cpu_save_registers(struct op_msrs *msrs) @@ -355,20 +344,14 @@ static void nmi_cpu_setup(void *dummy) int cpu = smp_processor_id(); struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu); nmi_cpu_save_registers(msrs); - spin_lock(&oprofilefs_lock); + raw_spin_lock(&oprofilefs_lock); model->setup_ctrs(model, msrs); nmi_cpu_setup_mux(cpu, msrs); - spin_unlock(&oprofilefs_lock); + raw_spin_unlock(&oprofilefs_lock); per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC); apic_write(APIC_LVTPC, APIC_DM_NMI); } -static struct notifier_block profile_exceptions_nb = { - .notifier_call = profile_exceptions_notify, - .next = NULL, - .priority = NMI_LOCAL_LOW_PRIOR, -}; - static void nmi_cpu_restore_registers(struct op_msrs *msrs) { struct op_msr *counters = msrs->counters; @@ -402,8 +385,6 @@ static void nmi_cpu_shutdown(void *dummy) apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu)); apic_write(APIC_LVTERR, v); nmi_cpu_restore_registers(msrs); - if (model->cpu_down) - model->cpu_down(); } static void nmi_cpu_up(void *dummy) @@ -508,7 +489,8 @@ static int nmi_setup(void) ctr_running = 0; /* make variables visible to the nmi handler: */ smp_mb(); - err = register_die_notifier(&profile_exceptions_nb); + err = register_nmi_handler(NMI_LOCAL, profile_exceptions_notify, + 0, "oprofile"); if (err) goto fail; @@ -538,7 +520,7 @@ static void nmi_shutdown(void) put_online_cpus(); /* make variables visible to the nmi handler: */ smp_mb(); - unregister_die_notifier(&profile_exceptions_nb); + unregister_nmi_handler(NMI_LOCAL, "oprofile"); msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); free_msrs(); diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c index 720bf5a53c51..7f8052cd6620 100644 --- a/arch/x86/oprofile/nmi_timer_int.c +++ b/arch/x86/oprofile/nmi_timer_int.c @@ -18,32 +18,16 @@ #include <asm/apic.h> #include <asm/ptrace.h> -static int profile_timer_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) +static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs) { - struct die_args *args = (struct die_args *)data; - int ret = NOTIFY_DONE; - - switch (val) { - case DIE_NMI: - oprofile_add_sample(args->regs, 0); - ret = NOTIFY_STOP; - break; - default: - break; - } - return ret; + oprofile_add_sample(regs, 0); + return NMI_HANDLED; } -static struct notifier_block profile_timer_exceptions_nb = { - .notifier_call = profile_timer_exceptions_notify, - .next = NULL, - .priority = NMI_LOW_PRIOR, -}; - static int timer_start(void) { - if (register_die_notifier(&profile_timer_exceptions_nb)) + if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify, + 0, "oprofile-timer")) return 1; return 0; } @@ -51,7 +35,7 @@ static int timer_start(void) static void timer_stop(void) { - unregister_die_notifier(&profile_timer_exceptions_nb); + unregister_nmi_handler(NMI_LOCAL, "oprofile-timer"); synchronize_sched(); /* Allow already-started NMIs to complete. */ } diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9cbb710dc94b..303f08637826 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -29,8 +29,6 @@ #include "op_x86_model.h" #include "op_counter.h" -#define NUM_COUNTERS 4 -#define NUM_COUNTERS_F15H 6 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX #define NUM_VIRT_COUNTERS 32 #else @@ -70,62 +68,12 @@ static struct ibs_config ibs_config; static struct ibs_state ibs_state; /* - * IBS cpuid feature detection - */ - -#define IBS_CPUID_FEATURES 0x8000001b - -/* - * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but - * bit 0 is used to indicate the existence of IBS. - */ -#define IBS_CAPS_AVAIL (1U<<0) -#define IBS_CAPS_FETCHSAM (1U<<1) -#define IBS_CAPS_OPSAM (1U<<2) -#define IBS_CAPS_RDWROPCNT (1U<<3) -#define IBS_CAPS_OPCNT (1U<<4) -#define IBS_CAPS_BRNTRGT (1U<<5) -#define IBS_CAPS_OPCNTEXT (1U<<6) - -#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ - | IBS_CAPS_FETCHSAM \ - | IBS_CAPS_OPSAM) - -/* - * IBS APIC setup - */ -#define IBSCTL 0x1cc -#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8) -#define IBSCTL_LVT_OFFSET_MASK 0x0F - -/* * IBS randomization macros */ #define IBS_RANDOM_BITS 12 #define IBS_RANDOM_MASK ((1ULL << IBS_RANDOM_BITS) - 1) #define IBS_RANDOM_MAXCNT_OFFSET (1ULL << (IBS_RANDOM_BITS - 5)) -static u32 get_ibs_caps(void) -{ - u32 ibs_caps; - unsigned int max_level; - - if (!boot_cpu_has(X86_FEATURE_IBS)) - return 0; - - /* check IBS cpuid feature flags */ - max_level = cpuid_eax(0x80000000); - if (max_level < IBS_CPUID_FEATURES) - return IBS_CAPS_DEFAULT; - - ibs_caps = cpuid_eax(IBS_CPUID_FEATURES); - if (!(ibs_caps & IBS_CAPS_AVAIL)) - /* cpuid flags not valid */ - return IBS_CAPS_DEFAULT; - - return ibs_caps; -} - /* * 16-bit Linear Feedback Shift Register (LFSR) * @@ -316,81 +264,6 @@ static void op_amd_stop_ibs(void) wrmsrl(MSR_AMD64_IBSOPCTL, 0); } -static inline int get_eilvt(int offset) -{ - return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1); -} - -static inline int put_eilvt(int offset) -{ - return !setup_APIC_eilvt(offset, 0, 0, 1); -} - -static inline int ibs_eilvt_valid(void) -{ - int offset; - u64 val; - int valid = 0; - - preempt_disable(); - - rdmsrl(MSR_AMD64_IBSCTL, val); - offset = val & IBSCTL_LVT_OFFSET_MASK; - - if (!(val & IBSCTL_LVT_OFFSET_VALID)) { - pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n", - smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); - goto out; - } - - if (!get_eilvt(offset)) { - pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n", - smp_processor_id(), offset, MSR_AMD64_IBSCTL, val); - goto out; - } - - valid = 1; -out: - preempt_enable(); - - return valid; -} - -static inline int get_ibs_offset(void) -{ - u64 val; - - rdmsrl(MSR_AMD64_IBSCTL, val); - if (!(val & IBSCTL_LVT_OFFSET_VALID)) - return -EINVAL; - - return val & IBSCTL_LVT_OFFSET_MASK; -} - -static void setup_APIC_ibs(void) -{ - int offset; - - offset = get_ibs_offset(); - if (offset < 0) - goto failed; - - if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0)) - return; -failed: - pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n", - smp_processor_id()); -} - -static void clear_APIC_ibs(void) -{ - int offset; - - offset = get_ibs_offset(); - if (offset >= 0) - setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); -} - #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX static void op_mux_switch_ctrl(struct op_x86_model_spec const *model, @@ -439,7 +312,7 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs) goto fail; } /* both registers must be reserved */ - if (num_counters == NUM_COUNTERS_F15H) { + if (num_counters == AMD64_NUM_COUNTERS_F15H) { msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1); msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1); } else { @@ -504,15 +377,6 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, val |= op_x86_get_ctrl(model, &counter_config[virt]); wrmsrl(msrs->controls[i].addr, val); } - - if (ibs_caps) - setup_APIC_ibs(); -} - -static void op_amd_cpu_shutdown(void) -{ - if (ibs_caps) - clear_APIC_ibs(); } static int op_amd_check_ctrs(struct pt_regs * const regs, @@ -575,86 +439,6 @@ static void op_amd_stop(struct op_msrs const * const msrs) op_amd_stop_ibs(); } -static int setup_ibs_ctl(int ibs_eilvt_off) -{ - struct pci_dev *cpu_cfg; - int nodes; - u32 value = 0; - - nodes = 0; - cpu_cfg = NULL; - do { - cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_10H_NB_MISC, - cpu_cfg); - if (!cpu_cfg) - break; - ++nodes; - pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off - | IBSCTL_LVT_OFFSET_VALID); - pci_read_config_dword(cpu_cfg, IBSCTL, &value); - if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) { - pci_dev_put(cpu_cfg); - printk(KERN_DEBUG "Failed to setup IBS LVT offset, " - "IBSCTL = 0x%08x\n", value); - return -EINVAL; - } - } while (1); - - if (!nodes) { - printk(KERN_DEBUG "No CPU node configured for IBS\n"); - return -ENODEV; - } - - return 0; -} - -/* - * This runs only on the current cpu. We try to find an LVT offset and - * setup the local APIC. For this we must disable preemption. On - * success we initialize all nodes with this offset. This updates then - * the offset in the IBS_CTL per-node msr. The per-core APIC setup of - * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_- - * amd_cpu_shutdown() using the new offset. - */ -static int force_ibs_eilvt_setup(void) -{ - int offset; - int ret; - - preempt_disable(); - /* find the next free available EILVT entry, skip offset 0 */ - for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { - if (get_eilvt(offset)) - break; - } - preempt_enable(); - - if (offset == APIC_EILVT_NR_MAX) { - printk(KERN_DEBUG "No EILVT entry available\n"); - return -EBUSY; - } - - ret = setup_ibs_ctl(offset); - if (ret) - goto out; - - if (!ibs_eilvt_valid()) { - ret = -EFAULT; - goto out; - } - - pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); - pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); - - return 0; -out: - preempt_disable(); - put_eilvt(offset); - preempt_enable(); - return ret; -} - /* * check and reserve APIC extended interrupt LVT offset for IBS if * available @@ -667,17 +451,6 @@ static void init_ibs(void) if (!ibs_caps) return; - if (ibs_eilvt_valid()) - goto out; - - if (!force_ibs_eilvt_setup()) - goto out; - - /* Failed to setup ibs */ - ibs_caps = 0; - return; - -out: printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); } @@ -741,9 +514,9 @@ static int op_amd_init(struct oprofile_operations *ops) ops->create_files = setup_ibs_files; if (boot_cpu_data.x86 == 0x15) { - num_counters = NUM_COUNTERS_F15H; + num_counters = AMD64_NUM_COUNTERS_F15H; } else { - num_counters = NUM_COUNTERS; + num_counters = AMD64_NUM_COUNTERS; } op_amd_spec.num_counters = num_counters; @@ -760,7 +533,6 @@ struct op_x86_model_spec op_amd_spec = { .init = op_amd_init, .fill_in_addresses = &op_amd_fill_in_addresses, .setup_ctrs = &op_amd_setup_ctrs, - .cpu_down = &op_amd_cpu_shutdown, .check_ctrs = &op_amd_check_ctrs, .start = &op_amd_start, .stop = &op_amd_stop, diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index 94b745045e45..d90528ea5412 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -28,7 +28,7 @@ static int counter_width = 32; #define MSR_PPRO_EVENTSEL_RESERVED ((0xFFFFFFFFULL<<32)|(1ULL<<21)) -static u64 *reset_value; +static u64 reset_value[OP_MAX_COUNTER]; static void ppro_shutdown(struct op_msrs const * const msrs) { @@ -40,10 +40,6 @@ static void ppro_shutdown(struct op_msrs const * const msrs) release_perfctr_nmi(MSR_P6_PERFCTR0 + i); release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); } - if (reset_value) { - kfree(reset_value); - reset_value = NULL; - } } static int ppro_fill_in_addresses(struct op_msrs * const msrs) @@ -79,13 +75,6 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, u64 val; int i; - if (!reset_value) { - reset_value = kzalloc(sizeof(reset_value[0]) * num_counters, - GFP_ATOMIC); - if (!reset_value) - return; - } - if (cpu_has_arch_perfmon) { union cpuid10_eax eax; eax.full = cpuid_eax(0xa); @@ -141,13 +130,6 @@ static int ppro_check_ctrs(struct pt_regs * const regs, u64 val; int i; - /* - * This can happen if perf counters are in use when - * we steal the die notifier NMI. - */ - if (unlikely(!reset_value)) - goto out; - for (i = 0; i < num_counters; ++i) { if (!reset_value[i]) continue; @@ -158,7 +140,6 @@ static int ppro_check_ctrs(struct pt_regs * const regs, wrmsrl(msrs->counters[i].addr, -reset_value[i]); } -out: /* Only P6 based Pentium M need to re-unmask the apic vector but it * doesn't hurt other P6 variant */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); @@ -179,8 +160,6 @@ static void ppro_start(struct op_msrs const * const msrs) u64 val; int i; - if (!reset_value) - return; for (i = 0; i < num_counters; ++i) { if (reset_value[i]) { rdmsrl(msrs->controls[i].addr, val); @@ -196,8 +175,6 @@ static void ppro_stop(struct op_msrs const * const msrs) u64 val; int i; - if (!reset_value) - return; for (i = 0; i < num_counters; ++i) { if (!reset_value[i]) continue; @@ -242,7 +219,7 @@ static void arch_perfmon_setup_counters(void) eax.split.bit_width = 40; } - num_counters = eax.split.num_counters; + num_counters = min((int)eax.split.num_counters, OP_MAX_COUNTER); op_arch_perfmon_spec.num_counters = num_counters; op_arch_perfmon_spec.num_controls = num_counters; diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 89017fa1fd63..71e8a67337e2 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -43,7 +43,6 @@ struct op_x86_model_spec { int (*fill_in_addresses)(struct op_msrs * const msrs); void (*setup_ctrs)(struct op_x86_model_spec const *model, struct op_msrs const * const msrs); - void (*cpu_down)(void); int (*check_ctrs)(struct pt_regs * const regs, struct op_msrs const * const msrs); void (*start)(struct op_msrs const * const msrs); diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index c95330267f08..404f21a3ff9e 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -43,6 +43,17 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"), }, }, + /* https://bugzilla.kernel.org/show_bug.cgi?id=30552 */ + /* 2006 AMD HT/VIA system with two host bridges */ + { + .callback = set_use_crs, + .ident = "ASUS M2V-MX SE", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2V-MX SE"), + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + }, + }, {} }; @@ -365,8 +376,13 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) */ if (bus) { struct pci_bus *child; - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child, child->self->pcie_mpss); + list_for_each_entry(child, &bus->children, node) { + struct pci_dev *self = child->self; + if (!self) + continue; + + pcie_bus_configure_settings(child, self->pcie_mpss); + } } if (!bus) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 1017c7bee388..492ade8c978e 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -175,8 +175,10 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) "pcifront-msi-x" : "pcifront-msi", DOMID_SELF); - if (irq < 0) + if (irq < 0) { + ret = irq; goto free; + } i++; } kfree(v); @@ -221,8 +223,10 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) if (msg.data != XEN_PIRQ_MSI_DATA || xen_irq_from_pirq(pirq) < 0) { pirq = xen_allocate_pirq_msi(dev, msidesc); - if (pirq < 0) + if (pirq < 0) { + irq = -ENODEV; goto error; + } xen_msi_compose_msg(dev, pirq, &msg); __write_msi_msg(msidesc, &msg); dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); @@ -244,10 +248,12 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) error: dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); - return -ENODEV; + return irq; } #ifdef CONFIG_XEN_DOM0 +static bool __read_mostly pci_seg_supported = true; + static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { int ret = 0; @@ -265,10 +271,11 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) memset(&map_irq, 0, sizeof(map_irq)); map_irq.domid = domid; - map_irq.type = MAP_PIRQ_TYPE_MSI; + map_irq.type = MAP_PIRQ_TYPE_MSI_SEG; map_irq.index = -1; map_irq.pirq = -1; - map_irq.bus = dev->bus->number; + map_irq.bus = dev->bus->number | + (pci_domain_nr(dev->bus) << 16); map_irq.devfn = dev->devfn; if (type == PCI_CAP_ID_MSIX) { @@ -285,7 +292,20 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) map_irq.entry_nr = msidesc->msi_attrib.entry_nr; } - ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); + ret = -EINVAL; + if (pci_seg_supported) + ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, + &map_irq); + if (ret == -EINVAL && !pci_domain_nr(dev->bus)) { + map_irq.type = MAP_PIRQ_TYPE_MSI; + map_irq.index = -1; + map_irq.pirq = -1; + map_irq.bus = dev->bus->number; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, + &map_irq); + if (ret != -EINVAL) + pci_seg_supported = false; + } if (ret) { dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n", ret, domid); diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 7000e74b3087..e6379526675b 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -14,6 +14,8 @@ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/scatterlist.h> #include <linux/sfi.h> #include <linux/intel_pmic_gpio.h> #include <linux/spi/spi.h> @@ -392,6 +394,7 @@ static void __init *max3111_platform_data(void *info) struct spi_board_info *spi_info = info; int intr = get_gpio_by_name("max3111_int"); + spi_info->mode = SPI_MODE_0; if (intr == -1) return NULL; spi_info->irq = intr + MRST_IRQ_OFFSET; @@ -678,36 +681,40 @@ static int __init sfi_parse_devs(struct sfi_table_header *table) pentry = (struct sfi_device_table_entry *)sb->pentry; for (i = 0; i < num; i++, pentry++) { - if (pentry->irq != (u8)0xff) { /* native RTE case */ + int irq = pentry->irq; + + if (irq != (u8)0xff) { /* native RTE case */ /* these SPI2 devices are not exposed to system as PCI * devices, but they have separate RTE entry in IOAPIC * so we have to enable them one by one here */ - ioapic = mp_find_ioapic(pentry->irq); + ioapic = mp_find_ioapic(irq); irq_attr.ioapic = ioapic; - irq_attr.ioapic_pin = pentry->irq; + irq_attr.ioapic_pin = irq; irq_attr.trigger = 1; irq_attr.polarity = 1; - io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); - } + io_apic_set_pci_routing(NULL, irq, &irq_attr); + } else + irq = 0; /* No irq */ + switch (pentry->type) { case SFI_DEV_TYPE_IPC: /* ID as IRQ is a hack that will go away */ - pdev = platform_device_alloc(pentry->name, pentry->irq); + pdev = platform_device_alloc(pentry->name, irq); if (pdev == NULL) { pr_err("out of memory for SFI platform device '%s'.\n", pentry->name); continue; } - install_irq_resource(pdev, pentry->irq); + install_irq_resource(pdev, irq); pr_debug("info[%2d]: IPC bus, name = %16.16s, " - "irq = 0x%2x\n", i, pentry->name, pentry->irq); + "irq = 0x%2x\n", i, pentry->name, irq); sfi_handle_ipc_dev(pdev); break; case SFI_DEV_TYPE_SPI: memset(&spi_info, 0, sizeof(spi_info)); strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); - spi_info.irq = pentry->irq; + spi_info.irq = irq; spi_info.bus_num = pentry->host_num; spi_info.chip_select = pentry->addr; spi_info.max_speed_hz = pentry->max_freq; @@ -724,7 +731,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table) memset(&i2c_info, 0, sizeof(i2c_info)); bus = pentry->host_num; strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); - i2c_info.irq = pentry->irq; + i2c_info.irq = irq; i2c_info.addr = pentry->addr; pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " "irq = 0x%2x, addr = 0x%x\n", i, bus, diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c index 73d70d65e76e..6d5dbcdd444a 100644 --- a/arch/x86/platform/mrst/vrtc.c +++ b/arch/x86/platform/mrst/vrtc.c @@ -58,8 +58,11 @@ EXPORT_SYMBOL_GPL(vrtc_cmos_write); unsigned long vrtc_get_time(void) { u8 sec, min, hour, mday, mon; + unsigned long flags; u32 year; + spin_lock_irqsave(&rtc_lock, flags); + while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) cpu_relax(); @@ -70,6 +73,8 @@ unsigned long vrtc_get_time(void) mon = vrtc_cmos_read(RTC_MONTH); year = vrtc_cmos_read(RTC_YEAR); + spin_unlock_irqrestore(&rtc_lock, flags); + /* vRTC YEAR reg contains the offset to 1960 */ year += 1960; @@ -83,8 +88,10 @@ unsigned long vrtc_get_time(void) int vrtc_set_mmss(unsigned long nowtime) { int real_sec, real_min; + unsigned long flags; int vrtc_min; + spin_lock_irqsave(&rtc_lock, flags); vrtc_min = vrtc_cmos_read(RTC_MINUTES); real_sec = nowtime % 60; @@ -95,6 +102,8 @@ int vrtc_set_mmss(unsigned long nowtime) vrtc_cmos_write(real_sec, RTC_SECONDS); vrtc_cmos_write(real_min, RTC_MINUTES); + spin_unlock_irqrestore(&rtc_lock, flags); + return 0; } diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index 8b9940e78e2f..7cce722667b8 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -161,13 +161,13 @@ restart: if (inbuf && inlen) { /* write data to EC */ for (i = 0; i < inlen; i++) { + pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); + outb(inbuf[i], 0x68); if (wait_on_ibf(0x6c, 0)) { printk(KERN_ERR "olpc-ec: timeout waiting for" " EC accept data!\n"); goto err; } - pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); - outb(inbuf[i], 0x68); } } if (outbuf && outlen) { diff --git a/arch/x86/vdso/vdso32/sysenter.S b/arch/x86/vdso/vdso32/sysenter.S index e2800affa754..e354bceee0e0 100644 --- a/arch/x86/vdso/vdso32/sysenter.S +++ b/arch/x86/vdso/vdso32/sysenter.S @@ -43,7 +43,7 @@ __kernel_vsyscall: .space 7,0x90 /* 14: System call restart point is here! (SYSENTER_RETURN-2) */ - jmp .Lenter_kernel + int $0x80 /* 16: System call normal return point is here! */ VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */ pop %ebp diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 5cc821cb2e09..26c731a106af 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig @@ -25,8 +25,7 @@ config XEN_PRIVILEGED_GUEST config XEN_PVHVM def_bool y - depends on XEN - depends on X86_LOCAL_APIC + depends on XEN && PCI && X86_LOCAL_APIC config XEN_MAX_DOMAIN_MEMORY int @@ -49,11 +48,3 @@ config XEN_DEBUG_FS help Enable statistics output and various tuning options in debugfs. Enabling this option may incur a significant performance overhead. - -config XEN_DEBUG - bool "Enable Xen debug checks" - depends on XEN - default n - help - Enable various WARN_ON checks in the Xen MMU code. - Enabling this option WILL incur a significant performance overhead. diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 2d69617950f7..da8afd576a6b 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -251,6 +251,7 @@ static void __init xen_init_cpuid_mask(void) ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ (1 << X86_FEATURE_ACPI)); /* disable ACPI */ ax = 1; + cx = 0; xen_cpuid(&ax, &bx, &cx, &dx); xsave_mask = diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 20a614275064..87f6673b1207 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -495,41 +495,6 @@ static pte_t xen_make_pte(pteval_t pte) } PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); -#ifdef CONFIG_XEN_DEBUG -pte_t xen_make_pte_debug(pteval_t pte) -{ - phys_addr_t addr = (pte & PTE_PFN_MASK); - phys_addr_t other_addr; - bool io_page = false; - pte_t _pte; - - if (pte & _PAGE_IOMAP) - io_page = true; - - _pte = xen_make_pte(pte); - - if (!addr) - return _pte; - - if (io_page && - (xen_initial_domain() || addr >= ISA_END_ADDRESS)) { - other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT; - WARN_ONCE(addr != other_addr, - "0x%lx is using VM_IO, but it is 0x%lx!\n", - (unsigned long)addr, (unsigned long)other_addr); - } else { - pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP; - other_addr = (_pte.pte & PTE_PFN_MASK); - WARN_ONCE((addr == other_addr) && (!io_page) && (!iomap_set), - "0x%lx is missing VM_IO (and wasn't fixed)!\n", - (unsigned long)addr); - } - - return _pte; -} -PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug); -#endif - static pgd_t xen_make_pgd(pgdval_t pgd) { pgd = pte_pfn_to_mfn(pgd); @@ -1721,10 +1686,8 @@ void __init xen_setup_machphys_mapping(void) machine_to_phys_nr = MACH2PHYS_NR_ENTRIES; } #ifdef CONFIG_X86_32 - if ((machine_to_phys_mapping + machine_to_phys_nr) - < machine_to_phys_mapping) - machine_to_phys_nr = (unsigned long *)NULL - - machine_to_phys_mapping; + WARN_ON((machine_to_phys_mapping + (machine_to_phys_nr - 1)) + < machine_to_phys_mapping); #endif } @@ -1994,9 +1957,6 @@ void __init xen_ident_map_ISA(void) static void __init xen_post_allocator_init(void) { -#ifdef CONFIG_XEN_DEBUG - pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); -#endif pv_mmu_ops.set_pte = xen_set_pte; pv_mmu_ops.set_pmd = xen_set_pmd; pv_mmu_ops.set_pud = xen_set_pud; @@ -2406,17 +2366,3 @@ out: return err; } EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); - -#ifdef CONFIG_XEN_DEBUG_FS -static int p2m_dump_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, p2m_dump_show, NULL); -} - -static const struct file_operations p2m_dump_fops = { - .open = p2m_dump_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_XEN_DEBUG_FS */ diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 58efeb9d5440..1b267e75158d 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -161,7 +161,9 @@ #include <asm/xen/page.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> +#include <xen/grant_table.h> +#include "multicalls.h" #include "xen-ops.h" static void __init m2p_override_init(void); @@ -676,7 +678,8 @@ static unsigned long mfn_hash(unsigned long mfn) } /* Add an MFN override for a particular page */ -int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte) +int m2p_add_override(unsigned long mfn, struct page *page, + struct gnttab_map_grant_ref *kmap_op) { unsigned long flags; unsigned long pfn; @@ -692,16 +695,28 @@ int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte) "m2p_add_override: pfn %lx not mapped", pfn)) return -EINVAL; } - - page->private = mfn; + WARN_ON(PagePrivate(page)); + SetPagePrivate(page); + set_page_private(page, mfn); page->index = pfn_to_mfn(pfn); if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) return -ENOMEM; - if (clear_pte && !PageHighMem(page)) - /* Just zap old mapping for now */ - pte_clear(&init_mm, address, ptep); + if (kmap_op != NULL) { + if (!PageHighMem(page)) { + struct multicall_space mcs = + xen_mc_entry(sizeof(*kmap_op)); + + MULTI_grant_table_op(mcs.mc, + GNTTABOP_map_grant_ref, kmap_op, 1); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + } + /* let's use dev_bus_addr to record the old mfn instead */ + kmap_op->dev_bus_addr = page->index; + page->index = (unsigned long) kmap_op; + } spin_lock_irqsave(&m2p_override_lock, flags); list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); spin_unlock_irqrestore(&m2p_override_lock, flags); @@ -735,13 +750,56 @@ int m2p_remove_override(struct page *page, bool clear_pte) spin_lock_irqsave(&m2p_override_lock, flags); list_del(&page->lru); spin_unlock_irqrestore(&m2p_override_lock, flags); - set_phys_to_machine(pfn, page->index); + WARN_ON(!PagePrivate(page)); + ClearPagePrivate(page); - if (clear_pte && !PageHighMem(page)) - set_pte_at(&init_mm, address, ptep, - pfn_pte(pfn, PAGE_KERNEL)); - /* No tlb flush necessary because the caller already - * left the pte unmapped. */ + if (clear_pte) { + struct gnttab_map_grant_ref *map_op = + (struct gnttab_map_grant_ref *) page->index; + set_phys_to_machine(pfn, map_op->dev_bus_addr); + if (!PageHighMem(page)) { + struct multicall_space mcs; + struct gnttab_unmap_grant_ref *unmap_op; + + /* + * It might be that we queued all the m2p grant table + * hypercalls in a multicall, then m2p_remove_override + * get called before the multicall has actually been + * issued. In this case handle is going to -1 because + * it hasn't been modified yet. + */ + if (map_op->handle == -1) + xen_mc_flush(); + /* + * Now if map_op->handle is negative it means that the + * hypercall actually returned an error. + */ + if (map_op->handle == GNTST_general_error) { + printk(KERN_WARNING "m2p_remove_override: " + "pfn %lx mfn %lx, failed to modify kernel mappings", + pfn, mfn); + return -1; + } + + mcs = xen_mc_entry( + sizeof(struct gnttab_unmap_grant_ref)); + unmap_op = mcs.args; + unmap_op->host_addr = map_op->host_addr; + unmap_op->handle = map_op->handle; + unmap_op->dev_bus_addr = 0; + + MULTI_grant_table_op(mcs.mc, + GNTTABOP_unmap_grant_ref, unmap_op, 1); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + set_pte_at(&init_mm, address, ptep, + pfn_pte(pfn, PAGE_KERNEL)); + __flush_tlb_single(address); + map_op->host_addr = 0; + } + } else + set_phys_to_machine(pfn, page->index); return 0; } @@ -758,7 +816,7 @@ struct page *m2p_find_override(unsigned long mfn) spin_lock_irqsave(&m2p_override_lock, flags); list_for_each_entry(p, bucket, lru) { - if (p->private == mfn) { + if (page_private(p) == mfn) { ret = p; break; } @@ -782,17 +840,21 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn) EXPORT_SYMBOL_GPL(m2p_find_override_pfn); #ifdef CONFIG_XEN_DEBUG_FS - -int p2m_dump_show(struct seq_file *m, void *v) +#include <linux/debugfs.h> +#include "debugfs.h" +static int p2m_dump_show(struct seq_file *m, void *v) { static const char * const level_name[] = { "top", "middle", - "entry", "abnormal" }; - static const char * const type_name[] = { "identity", "missing", - "pfn", "abnormal"}; + "entry", "abnormal", "error"}; #define TYPE_IDENTITY 0 #define TYPE_MISSING 1 #define TYPE_PFN 2 #define TYPE_UNKNOWN 3 + static const char * const type_name[] = { + [TYPE_IDENTITY] = "identity", + [TYPE_MISSING] = "missing", + [TYPE_PFN] = "pfn", + [TYPE_UNKNOWN] = "abnormal"}; unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0; unsigned int uninitialized_var(prev_level); unsigned int uninitialized_var(prev_type); @@ -856,4 +918,32 @@ int p2m_dump_show(struct seq_file *m, void *v) #undef TYPE_PFN #undef TYPE_UNKNOWN } -#endif + +static int p2m_dump_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, p2m_dump_show, NULL); +} + +static const struct file_operations p2m_dump_fops = { + .open = p2m_dump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *d_mmu_debug; + +static int __init xen_p2m_debugfs(void) +{ + struct dentry *d_xen = xen_init_debugfs(); + + if (d_xen == NULL) + return -ENOMEM; + + d_mmu_debug = debugfs_create_dir("mmu", d_xen); + + debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); + return 0; +} +fs_initcall(xen_p2m_debugfs); +#endif /* CONFIG_XEN_DEBUG_FS */ diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index df118a825f39..38d0af4fefec 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -37,7 +37,10 @@ extern void xen_syscall_target(void); extern void xen_syscall32_target(void); /* Amount of extra memory space we add to the e820 ranges */ -phys_addr_t xen_extra_mem_start, xen_extra_mem_size; +struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata; + +/* Number of pages released from the initial allocation. */ +unsigned long xen_released_pages; /* * The maximum amount of extra memory compared to the base size. The @@ -51,48 +54,47 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size; */ #define EXTRA_MEM_RATIO (10) -static void __init xen_add_extra_mem(unsigned long pages) +static void __init xen_add_extra_mem(u64 start, u64 size) { unsigned long pfn; + int i; - u64 size = (u64)pages * PAGE_SIZE; - u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; - - if (!pages) - return; - - e820_add_region(extra_start, size, E820_RAM); - sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); - - memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA"); + for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { + /* Add new region. */ + if (xen_extra_mem[i].size == 0) { + xen_extra_mem[i].start = start; + xen_extra_mem[i].size = size; + break; + } + /* Append to existing region. */ + if (xen_extra_mem[i].start + xen_extra_mem[i].size == start) { + xen_extra_mem[i].size += size; + break; + } + } + if (i == XEN_EXTRA_MEM_MAX_REGIONS) + printk(KERN_WARNING "Warning: not enough extra memory regions\n"); - xen_extra_mem_size += size; + memblock_x86_reserve_range(start, start + size, "XEN EXTRA"); - xen_max_p2m_pfn = PFN_DOWN(extra_start + size); + xen_max_p2m_pfn = PFN_DOWN(start + size); - for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++) + for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++) __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); } -static unsigned long __init xen_release_chunk(phys_addr_t start_addr, - phys_addr_t end_addr) +static unsigned long __init xen_release_chunk(unsigned long start, + unsigned long end) { struct xen_memory_reservation reservation = { .address_bits = 0, .extent_order = 0, .domid = DOMID_SELF }; - unsigned long start, end; unsigned long len = 0; unsigned long pfn; int ret; - start = PFN_UP(start_addr); - end = PFN_DOWN(end_addr); - - if (end <= start) - return 0; - for(pfn = start; pfn < end; pfn++) { unsigned long mfn = pfn_to_mfn(pfn); @@ -117,88 +119,92 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr, return len; } -static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, - const struct e820map *e820) +static unsigned long __init xen_set_identity_and_release( + const struct e820entry *list, size_t map_size, unsigned long nr_pages) { - phys_addr_t max_addr = PFN_PHYS(max_pfn); - phys_addr_t last_end = ISA_END_ADDRESS; + phys_addr_t start = 0; unsigned long released = 0; + unsigned long identity = 0; + const struct e820entry *entry; int i; - /* Free any unused memory above the low 1Mbyte. */ - for (i = 0; i < e820->nr_map && last_end < max_addr; i++) { - phys_addr_t end = e820->map[i].addr; - end = min(max_addr, end); + /* + * Combine non-RAM regions and gaps until a RAM region (or the + * end of the map) is reached, then set the 1:1 map and + * release the pages (if available) in those non-RAM regions. + * + * The combined non-RAM regions are rounded to a whole number + * of pages so any partial pages are accessible via the 1:1 + * mapping. This is needed for some BIOSes that put (for + * example) the DMI tables in a reserved region that begins on + * a non-page boundary. + */ + for (i = 0, entry = list; i < map_size; i++, entry++) { + phys_addr_t end = entry->addr + entry->size; + + if (entry->type == E820_RAM || i == map_size - 1) { + unsigned long start_pfn = PFN_DOWN(start); + unsigned long end_pfn = PFN_UP(end); - if (last_end < end) - released += xen_release_chunk(last_end, end); - last_end = max(last_end, e820->map[i].addr + e820->map[i].size); + if (entry->type == E820_RAM) + end_pfn = PFN_UP(entry->addr); + + if (start_pfn < end_pfn) { + if (start_pfn < nr_pages) + released += xen_release_chunk( + start_pfn, min(end_pfn, nr_pages)); + + identity += set_phys_range_identity( + start_pfn, end_pfn); + } + start = end; + } } - if (last_end < max_addr) - released += xen_release_chunk(last_end, max_addr); + printk(KERN_INFO "Released %lu pages of unused memory\n", released); + printk(KERN_INFO "Set %ld page(s) to 1-1 mapping\n", identity); - printk(KERN_INFO "released %lu pages of unused memory\n", released); return released; } -static unsigned long __init xen_set_identity(const struct e820entry *list, - ssize_t map_size) +static unsigned long __init xen_get_max_pages(void) { - phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS; - phys_addr_t start_pci = last; - const struct e820entry *entry; - unsigned long identity = 0; - int i; - - for (i = 0, entry = list; i < map_size; i++, entry++) { - phys_addr_t start = entry->addr; - phys_addr_t end = start + entry->size; - - if (start < last) - start = last; - - if (end <= start) - continue; + unsigned long max_pages = MAX_DOMAIN_PAGES; + domid_t domid = DOMID_SELF; + int ret; - /* Skip over the 1MB region. */ - if (last > end) - continue; + ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); + if (ret > 0) + max_pages = ret; + return min(max_pages, MAX_DOMAIN_PAGES); +} - if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) { - if (start > start_pci) - identity += set_phys_range_identity( - PFN_UP(start_pci), PFN_DOWN(start)); +static void xen_align_and_add_e820_region(u64 start, u64 size, int type) +{ + u64 end = start + size; - /* Without saving 'last' we would gooble RAM too - * at the end of the loop. */ - last = end; - start_pci = end; - continue; - } - start_pci = min(start, start_pci); - last = end; + /* Align RAM regions to page boundaries. */ + if (type == E820_RAM) { + start = PAGE_ALIGN(start); + end &= ~((u64)PAGE_SIZE - 1); } - if (last > start_pci) - identity += set_phys_range_identity( - PFN_UP(start_pci), PFN_DOWN(last)); - return identity; + + e820_add_region(start, end - start, type); } + /** * machine_specific_memory_setup - Hook for machine specific memory setup. **/ char * __init xen_memory_setup(void) { static struct e820entry map[E820MAX] __initdata; - static struct e820entry map_raw[E820MAX] __initdata; unsigned long max_pfn = xen_start_info->nr_pages; unsigned long long mem_end; int rc; struct xen_memory_map memmap; + unsigned long max_pages; unsigned long extra_pages = 0; - unsigned long extra_limit; - unsigned long identity_pages = 0; int i; int op; @@ -224,58 +230,65 @@ char * __init xen_memory_setup(void) } BUG_ON(rc); - memcpy(map_raw, map, sizeof(map)); - e820.nr_map = 0; - xen_extra_mem_start = mem_end; - for (i = 0; i < memmap.nr_entries; i++) { - unsigned long long end; - - /* Guard against non-page aligned E820 entries. */ - if (map[i].type == E820_RAM) - map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE; - - end = map[i].addr + map[i].size; - if (map[i].type == E820_RAM && end > mem_end) { - /* RAM off the end - may be partially included */ - u64 delta = min(map[i].size, end - mem_end); - - map[i].size -= delta; - end -= delta; - - extra_pages += PFN_DOWN(delta); - /* - * Set RAM below 4GB that is not for us to be unusable. - * This prevents "System RAM" address space from being - * used as potential resource for I/O address (happens - * when 'allocate_resource' is called). - */ - if (delta && - (xen_initial_domain() && end < 0x100000000ULL)) - e820_add_region(end, delta, E820_UNUSABLE); + /* Make sure the Xen-supplied memory map is well-ordered. */ + sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries); + + max_pages = xen_get_max_pages(); + if (max_pages > max_pfn) + extra_pages += max_pages - max_pfn; + + /* + * Set P2M for all non-RAM pages and E820 gaps to be identity + * type PFNs. Any RAM pages that would be made inaccesible by + * this are first released. + */ + xen_released_pages = xen_set_identity_and_release( + map, memmap.nr_entries, max_pfn); + extra_pages += xen_released_pages; + + /* + * Clamp the amount of extra memory to a EXTRA_MEM_RATIO + * factor the base size. On non-highmem systems, the base + * size is the full initial memory allocation; on highmem it + * is limited to the max size of lowmem, so that it doesn't + * get completely filled. + * + * In principle there could be a problem in lowmem systems if + * the initial memory is also very large with respect to + * lowmem, but we won't try to deal with that here. + */ + extra_pages = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)), + extra_pages); + + i = 0; + while (i < memmap.nr_entries) { + u64 addr = map[i].addr; + u64 size = map[i].size; + u32 type = map[i].type; + + if (type == E820_RAM) { + if (addr < mem_end) { + size = min(size, mem_end - addr); + } else if (extra_pages) { + size = min(size, (u64)extra_pages * PAGE_SIZE); + extra_pages -= size / PAGE_SIZE; + xen_add_extra_mem(addr, size); + } else + type = E820_UNUSABLE; } - if (map[i].size > 0 && end > xen_extra_mem_start) - xen_extra_mem_start = end; + xen_align_and_add_e820_region(addr, size, type); - /* Add region if any remains */ - if (map[i].size > 0) - e820_add_region(map[i].addr, map[i].size, map[i].type); + map[i].addr += size; + map[i].size -= size; + if (map[i].size == 0) + i++; } - /* Align the balloon area so that max_low_pfn does not get set - * to be at the _end_ of the PCI gap at the far end (fee01000). - * Note that xen_extra_mem_start gets set in the loop above to be - * past the last E820 region. */ - if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32))) - xen_extra_mem_start = (1ULL<<32); /* * In domU, the ISA region is normal, usable memory, but we * reserve ISA memory anyway because too many things poke * about in there. - * - * In Dom0, the host E820 information can leave gaps in the - * ISA range, which would cause us to release those pages. To - * avoid this, we unconditionally reserve them here. */ e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, E820_RESERVED); @@ -292,36 +305,6 @@ char * __init xen_memory_setup(void) sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); - extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820); - - /* - * Clamp the amount of extra memory to a EXTRA_MEM_RATIO - * factor the base size. On non-highmem systems, the base - * size is the full initial memory allocation; on highmem it - * is limited to the max size of lowmem, so that it doesn't - * get completely filled. - * - * In principle there could be a problem in lowmem systems if - * the initial memory is also very large with respect to - * lowmem, but we won't try to deal with that here. - */ - extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)), - max_pfn + extra_pages); - - if (extra_limit >= max_pfn) - extra_pages = extra_limit - max_pfn; - else - extra_pages = 0; - - xen_add_extra_mem(extra_pages); - - /* - * Set P2M for all non-RAM pages and E820 gaps to be identity - * type PFNs. We supply it with the non-sanitized version - * of the E820. - */ - identity_pages = xen_set_identity(map_raw, memmap.nr_entries); - printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages); return "Xen"; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index e79dbb95482b..041d4fe9dfe4 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -32,6 +32,7 @@ #include <xen/page.h> #include <xen/events.h> +#include <xen/hvc-console.h> #include "xen-ops.h" #include "mmu.h" @@ -207,6 +208,15 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) unsigned cpu; unsigned int i; + if (skip_ioapic_setup) { + char *m = (max_cpus == 0) ? + "The nosmp parameter is incompatible with Xen; " \ + "use Xen dom0_max_vcpus=1 parameter" : + "The noapic parameter is incompatible with Xen"; + + xen_raw_printk(m); + panic(m); + } xen_init_lock_cpu(0); smp_store_cpu_info(0); @@ -522,7 +532,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) WARN_ON(xen_smp_intr_init(0)); xen_init_lock_cpu(0); - xen_init_spinlocks(); } static int __cpuinit xen_hvm_cpu_up(unsigned int cpu) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 5158c505bef9..163b4679556e 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -168,9 +168,10 @@ cycle_t xen_clocksource_read(void) struct pvclock_vcpu_time_info *src; cycle_t ret; - src = &get_cpu_var(xen_vcpu)->time; + preempt_disable_notrace(); + src = &__get_cpu_var(xen_vcpu)->time; ret = pvclock_clocksource_read(src); - put_cpu_var(xen_vcpu); + preempt_enable_notrace(); return ret; } diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 22a2093b5862..b040b0e518ca 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -113,11 +113,13 @@ xen_iret_start_crit: /* * If there's something pending, mask events again so we can - * jump back into xen_hypervisor_callback + * jump back into xen_hypervisor_callback. Otherwise do not + * touch XEN_vcpu_info_mask. */ - sete XEN_vcpu_info_mask(%eax) + jne 1f + movb $1, XEN_vcpu_info_mask(%eax) - popl %eax +1: popl %eax /* * From this point on the registers are restored and the stack diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig index 0234cd198c54..f932b30b47fb 100644 --- a/arch/xtensa/configs/iss_defconfig +++ b/arch/xtensa/configs/iss_defconfig @@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_NO_IOPORT=y CONFIG_HZ=100 -CONFIG_GENERIC_TIME=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig index 4891abbf16bc..550e8ed5b5c6 100644 --- a/arch/xtensa/configs/s6105_defconfig +++ b/arch/xtensa/configs/s6105_defconfig @@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_NO_IOPORT=y CONFIG_HZ=100 -CONFIG_GENERIC_TIME=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index a6f934f37f1a..798ee6d285a1 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -455,7 +455,7 @@ __SYSCALL(203, sys_reboot, 3) #define __NR_quotactl 204 __SYSCALL(204, sys_quotactl, 4) #define __NR_nfsservctl 205 -__SYSCALL(205, sys_nfsservctl, 3) +__SYSCALL(205, sys_ni_syscall, 0) #define __NR__sysctl 206 __SYSCALL(206, sys_sysctl, 1) #define __NR_bdflush 207 diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index f717e20d961b..7dde24456427 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -633,7 +633,7 @@ static const struct net_device_ops iss_netdev_ops = { .ndo_set_mac_address = iss_net_set_mac, //.ndo_do_ioctl = iss_net_ioctl, .ndo_tx_timeout = iss_net_tx_timeout, - .ndo_set_multicast_list = iss_net_set_multicast_list, + .ndo_set_rx_mode = iss_net_set_multicast_list, }; static int iss_net_configure(int index, char *init) |