summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.davemloft.net>2004-04-22 01:25:25 -0700
committerDavid S. Miller <davem@nuts.davemloft.net>2004-04-22 01:25:25 -0700
commit88d0505c93f592c135ea730df4cebad96fd0df64 (patch)
tree950f1cf8636de5a1aab640b59cd92764b0f14c7c
parent16a76bdbafd6c681dd15419183308bba1dd58063 (diff)
parent98a5d354daf5357590bfc25521c91d67dc93de96 (diff)
Merge nuts.davemloft.net:/disk1/BK/network-2.6
into nuts.davemloft.net:/disk1/BK/net-2.6
-rw-r--r--CREDITS6
-rw-r--r--Documentation/s390/crypto/crypto-API.txt83
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/kernel/irq.c14
-rw-r--r--arch/alpha/kernel/traps.c12
-rw-r--r--arch/arm/Kconfig15
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/boot/Makefile3
-rw-r--r--arch/arm/kernel/debug.S29
-rw-r--r--arch/arm/kernel/entry-armv.S31
-rw-r--r--arch/arm/lib/findbit.S57
-rw-r--r--arch/arm/mach-versatile/Makefile5
-rw-r--r--arch/arm/mach-versatile/core.c507
-rw-r--r--arch/arm/mm/Kconfig5
-rw-r--r--arch/arm26/kernel/traps.c12
-rw-r--r--arch/cris/kernel/traps.c8
-rw-r--r--arch/h8300/kernel/traps.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi.c45
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c257
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c31
-rw-r--r--arch/i386/kernel/i8259.c2
-rw-r--r--arch/i386/kernel/nmi.c3
-rw-r--r--arch/i386/kernel/traps.c10
-rw-r--r--arch/i386/mm/hugetlbpage.c9
-rw-r--r--arch/mips/kernel/traps.c5
-rw-r--r--arch/parisc/kernel/traps.c5
-rw-r--r--arch/ppc64/kernel/process.c6
-rw-r--r--arch/s390/Makefile2
-rw-r--r--arch/s390/crypto/Makefile8
-rw-r--r--arch/s390/crypto/crypt_z990.h374
-rw-r--r--arch/s390/crypto/crypt_z990_query.c111
-rw-r--r--arch/s390/crypto/crypto_des.h18
-rw-r--r--arch/s390/crypto/des_check_key.c130
-rw-r--r--arch/s390/crypto/des_z990.c284
-rw-r--r--arch/s390/crypto/sha1_z990.c167
-rw-r--r--arch/s390/defconfig48
-rw-r--r--arch/s390/kernel/binfmt_elf32.c2
-rw-r--r--arch/s390/kernel/compat_linux.c88
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/s390/kernel/entry.S6
-rw-r--r--arch/s390/kernel/entry64.S6
-rw-r--r--arch/s390/kernel/setup.c4
-rw-r--r--arch/s390/kernel/smp.c4
-rw-r--r--arch/s390/kernel/traps.c11
-rw-r--r--arch/sh/kernel/traps.c6
-rw-r--r--arch/sparc64/kernel/traps.c7
-rw-r--r--arch/um/kernel/sysrq.c11
-rw-r--r--arch/v850/kernel/process.c7
-rw-r--r--arch/x86_64/kernel/traps.c10
-rw-r--r--crypto/Kconfig12
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/cdrom/viocd.c87
-rw-r--r--drivers/char/drm/i810_dma.c3
-rw-r--r--drivers/char/viotape.c41
-rw-r--r--drivers/char/watchdog/Kconfig13
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/amd7xx_tco.c374
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c6
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/ide/ide-disk.c1
-rw-r--r--drivers/ide/ide-probe.c1
-rw-r--r--drivers/ide/legacy/ide-cs.c2
-rw-r--r--drivers/input/keyboard/lkkbd.c149
-rw-r--r--drivers/input/mouse/Kconfig2
-rw-r--r--drivers/input/mouse/vsxxxaa.c130
-rw-r--r--drivers/input/serio/Kconfig10
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/i8042-io.h2
-rw-r--r--drivers/input/serio/i8042-ip22io.h76
-rw-r--r--drivers/input/serio/i8042-jazzio.h69
-rw-r--r--drivers/input/serio/i8042.h8
-rw-r--r--drivers/input/serio/maceps2.c160
-rw-r--r--drivers/md/dm.c71
-rw-r--r--drivers/net/iseries_veth.c14
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/s390/block/dasd.c15
-rw-r--r--drivers/s390/block/dasd_3990_erp.c3
-rw-r--r--drivers/s390/block/dasd_eckd.c5
-rw-r--r--drivers/s390/block/dasd_int.h6
-rw-r--r--drivers/s390/char/raw3270.c4
-rw-r--r--drivers/s390/cio/cio.c67
-rw-r--r--drivers/s390/cio/device_fsm.c3
-rw-r--r--drivers/s390/cio/qdio.c12
-rw-r--r--drivers/s390/net/iucv.c7
-rw-r--r--drivers/s390/net/netiucv.c18
-rw-r--r--drivers/s390/net/qeth.h5
-rw-r--r--drivers/s390/net/qeth_main.c326
-rw-r--r--drivers/s390/scsi/zfcp_aux.c16
-rw-r--r--drivers/s390/scsi/zfcp_def.h15
-rw-r--r--drivers/s390/scsi/zfcp_erp.c25
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c41
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c11
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c6
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/video/fbcmap.c2
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/block_dev.c1
-rw-r--r--fs/buffer.c71
-rw-r--r--fs/compat.c2
-rw-r--r--fs/compat_ioctl.c4
-rw-r--r--fs/exec.c31
-rw-r--r--fs/jbd/journal.c1
-rw-r--r--fs/nfs/nfsroot.c32
-rw-r--r--fs/reiserfs/super.c2
-rw-r--r--fs/super.c8
-rw-r--r--fs/xfs/linux/xfs_ioctl.c5
-rw-r--r--fs/xfs/linux/xfs_lrw.c2
-rw-r--r--fs/xfs/linux/xfs_super.c24
-rw-r--r--fs/xfs/linux/xfs_vfs.c12
-rw-r--r--fs/xfs/linux/xfs_vfs.h5
-rw-r--r--fs/xfs/xfs_fsops.c66
-rw-r--r--fs/xfs/xfs_fsops.h8
-rw-r--r--fs/xfs/xfs_log.c2
-rw-r--r--fs/xfs/xfs_mount.c61
-rw-r--r--fs/xfs/xfs_mount.h14
-rw-r--r--fs/xfs/xfs_trans.c4
-rw-r--r--fs/xfs/xfs_vfsops.c15
-rw-r--r--include/asm-arm/arch-versatile/dma.h27
-rw-r--r--include/asm-arm/arch-versatile/hardware.h45
-rw-r--r--include/asm-arm/arch-versatile/io.h29
-rw-r--r--include/asm-arm/arch-versatile/irqs.h211
-rw-r--r--include/asm-arm/arch-versatile/memory.h61
-rw-r--r--include/asm-arm/arch-versatile/param.h19
-rw-r--r--include/asm-arm/arch-versatile/platform.h488
-rw-r--r--include/asm-arm/arch-versatile/serial.h37
-rw-r--r--include/asm-arm/arch-versatile/system.h51
-rw-r--r--include/asm-arm/arch-versatile/time.h158
-rw-r--r--include/asm-arm/arch-versatile/timex.h23
-rw-r--r--include/asm-arm/arch-versatile/uncompress.h54
-rw-r--r--include/asm-arm/arch-versatile/vmalloc.h33
-rw-r--r--include/asm-arm/bitops.h9
-rw-r--r--include/asm-ppc/processor.h2
-rw-r--r--include/asm-ppc64/processor.h2
-rw-r--r--include/linux/buffer_head.h2
-rw-r--r--include/linux/compat_ioctl.h16
-rw-r--r--include/linux/fs.h16
-rw-r--r--include/linux/proc_fs.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/security.h18
-rw-r--r--include/linux/sunrpc/svcauth_gss.h1
-rw-r--r--init/Kconfig2
-rw-r--r--init/main.c21
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c7
-rw-r--r--security/capability.c2
-rw-r--r--security/commoncap.c38
-rw-r--r--security/dummy.c31
-rw-r--r--security/root_plug.c2
-rw-r--r--security/selinux/Kconfig15
-rw-r--r--security/selinux/hooks.c61
-rw-r--r--security/selinux/selinuxfs.c62
-rw-r--r--security/selinux/ss/services.c6
155 files changed, 4875 insertions, 1374 deletions
diff --git a/CREDITS b/CREDITS
index 1d61e296472d..f30565f12cf2 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1944,6 +1944,12 @@ S: 8786 Niwot Road
S: Niwot, Colorado 80503
S: USA
+N: Pete Popov
+E: pete_popov@yahoo.com
+D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
+S: San Jose, CA 95134
+S: USA
+
N: Robert M. Love
E: rml@tech9.net
E: rml@ufl.edu
diff --git a/Documentation/s390/crypto/crypto-API.txt b/Documentation/s390/crypto/crypto-API.txt
new file mode 100644
index 000000000000..78a77624a716
--- /dev/null
+++ b/Documentation/s390/crypto/crypto-API.txt
@@ -0,0 +1,83 @@
+crypto-API support for z990 Message Security Assist (MSA) instructions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+AUTHOR: Thomas Spatzier (tspat@de.ibm.com)
+
+
+1. Introduction crypto-API
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+See Documentation/crypto/api-intro.txt for an introduction/description of the
+kernel crypto API.
+According to api-intro.txt support for z990 crypto instructions has been added
+in the algorithm api layer of the crypto API. Several files containing z990
+optimized implementations of crypto algorithms are placed in the
+arch/s390/crypto directory.
+
+
+2. Probing for availability of MSA
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It should be possible to use Kernels with the z990 crypto implementations both
+on machines with MSA available an on those without MSA (pre z990 or z990
+without MSA). Therefore a simple probing mechanisms has been implemented:
+In the init function of each crypto module the availability of MSA and of the
+respective crypto algorithm in particular will be tested. If the algorithm is
+available the module will load and register its algorithm with the crypto API.
+
+If the respective crypto algorithm is not available, the init function will
+return -ENOSYS. In that case a fallback to the standard software implementation
+of the crypto algorithm must be taken ( -> the standard crypto modules are
+also build when compiling the kernel).
+
+
+3. Ensuring z990 crypto module preference
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If z990 crypto instructions are available the optimized modules should be
+preferred instead of standard modules.
+
+3.1. compiled-in modules
+~~~~~~~~~~~~~~~~~~~~~~~~
+For compiled-in modules it has to be ensured that the z990 modules are linked
+before the standard crypto modules. Then, on system startup the init functions
+of z990 crypto modules will be called first and query for availability of z990
+crypto instructions. If instruction is available, the z990 module will register
+its crypto algorithm implementation -> the load of the standard module will fail
+since the algorithm is already registered.
+If z990 crypto instruction is not available the load of the z990 module will
+fail -> the standard module will load and register its algorithm.
+
+3.2. dynamic modules
+~~~~~~~~~~~~~~~~~~~~
+A system administrator has to take care of giving preference to z990 crypto
+modules. If MSA is available appropriate lines have to be added to
+/etc/modprobe.conf.
+
+Example: z990 crypto instruction for SHA1 algorithm is available
+
+ add the following line to /etc/modprobe.conf (assuming the
+ z990 crypto modules for SHA1 is called sha1_z990):
+
+ alias sha1 sha1_z990
+
+ -> when the sha1 algorithm is requested through the crypto API
+ (which has a module autoloader) the z990 module will be loaded.
+
+TBD: a userspace module probin mechanism
+ something like 'probe sha1 sha1_z990 sha1' in modprobe.conf
+ -> try module sha1_z990, if it fails to load load standard module sha1
+ the 'probe' statement is currently not supported in modprobe.conf
+
+
+4. Currently implemented z990 crypto algorithms
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The following crypto algorithms with z990 MSA support are currently implemented.
+The name of each algorithm under which it is registered in crypto API and the
+name of the respective module is given in square brackets.
+
+- SHA1 Digest Algorithm [sha1 -> sha1_z990]
+- DES Encrypt/Decrypt Algorithm (64bit key) [des -> des_z990]
+- Tripple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990]
+- Tripple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990]
+
+In order to load, for example, the sha1_z990 module when the sha1 algorithm is
+requested (see 3.2.) add 'alias sha1 sha1_z990' to /etc/modprobe.conf.
+
diff --git a/Makefile b/Makefile
index 806058fe3d2d..93a3212b9443 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 6
-EXTRAVERSION =-rc1
+EXTRAVERSION =-rc2
NAME=Zonked Quokka
# *DOCUMENTATION*
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index 0e317230f81e..c51bf8dbfc8a 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -415,16 +415,12 @@ init_irq_proc (void)
#endif
/*
- * Create entries for all existing IRQs. If the number of IRQs
- * is greater the 1/4 the total dynamic inode space for /proc,
- * don't pollute the inode space
+ * Create entries for all existing IRQs.
*/
- if (ACTUAL_NR_IRQS < (PROC_NDYNAMIC / 4)) {
- for (i = 0; i < ACTUAL_NR_IRQS; i++) {
- if (irq_desc[i].handler == &no_irq_type)
- continue;
- register_irq_proc(i);
- }
+ for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+ if (irq_desc[i].handler == &no_irq_type)
+ continue;
+ register_irq_proc(i);
}
}
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 8906f66b65e7..52348791ce1e 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -137,18 +137,6 @@ dik_show_trace(unsigned long *sp)
printk("\n");
}
-void show_trace_task(struct task_struct * tsk)
-{
- struct thread_info *ti = tsk->thread_info;
- unsigned long fp, sp = ti->pcb.ksp, base = (unsigned long) ti;
-
- if (sp > base && sp+6*8 < base + 16*1024) {
- fp = ((unsigned long*)sp)[6];
- if (fp > sp && fp < base + 16*1024)
- dik_show_trace((unsigned long *)fp);
- }
-}
-
static int kstack_depth_to_print = 24;
void show_stack(struct task_struct *task, unsigned long *sp)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3a1fd4205e01..43329eaf2f9b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -145,6 +145,11 @@ config ARCH_S3C2410
config ARCH_OMAP
bool "TI OMAP"
+config ARCH_VERSATILE_PB
+ bool "Versatile PB"
+ help
+ This enables support for ARM Ltd Versatile PB board.
+
endchoice
source "arch/arm/mach-clps711x/Kconfig"
@@ -262,7 +267,7 @@ config ICST525
config ARM_AMBA
bool
- depends on ARCH_INTEGRATOR
+ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB
default y
config ISA
@@ -514,7 +519,7 @@ config CMDLINE
config LEDS
bool "Timer and CPU usage LEDs"
- depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP
+ depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
help
If you say Y here, the LEDs on your machine will be used
to provide useful information about your current system status.
@@ -527,8 +532,8 @@ config LEDS
system, but the driver will do nothing.
config LEDS_TIMER
- bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T)
- depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP
+ bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
+ depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
default y if ARCH_EBSA110
help
If you say Y here, one of the system LEDs (the green one on the
@@ -543,7 +548,7 @@ config LEDS_TIMER
config LEDS_CPU
bool "CPU usage LED"
- depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T)
+ depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
help
If you say Y here, the red LED will be used to give a good real
time indication of CPU usage, by lighting whenever the idle task
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1f9f913fb63f..0dea4d3f5b4a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_ADIFCC) := adifcc
machine-$(CONFIG_ARCH_OMAP) := omap
machine-$(CONFIG_ARCH_S3C2410) := s3c2410
+ machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
TEXTADDR := $(textaddr-y)
ifeq ($(incdir-y),)
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 32581b7883c3..65ba5bf38ae6 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -56,6 +56,9 @@ params_phys-$(CONFIG_ARCH_OMAP) := 0x10000100
initrd_phys-$(CONFIG_ARCH_OMAP) := 0x10800000
zreladdr-$(CONFIG_ARCH_S3C2410) := 0x30008000
params_phys-$(CONFIG_ARCH_S3C2410) := 0x30000100
+ zreladdr-$(CONFIG_ARCH_VERSATILE_PB) := 0x00008000
+params_phys-$(CONFIG_ARCH_VERSATILE_PB) := 0x00000100
+initrd_phys-$(CONFIG_ARCH_VERSATILE_PB) := 0x00800000
ZRELADDR := $(zreladdr-y)
ZTEXTADDR := $(ztextaddr-y)
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 5db32be694c0..319b21e4fc78 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -550,6 +550,35 @@
1002: @ exit busyuart
.endm
+
+#elif defined(CONFIG_ARCH_VERSATILE_PB)
+
+#include <asm/hardware/amba_serial.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ moveq \rx, #0x10000000
+ movne \rx, #0xf1000000 @ virtual base
+ orr \rx, \rx, #0x001F0000
+ orr \rx, \rx, #0x00001000
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #UART01x_DR]
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
+ bne 1001b
+ .endm
#else
#error Unknown architecture
#endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f65d5d21c1c..0bb77b9fb0ab 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -463,6 +463,37 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table
.endm
+#elif defined(CONFIG_ARCH_VERSATILE_PB)
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
+ ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
+ mov \irqnr, #0
+ teq \irqstat, #0
+ beq 1003f
+
+1001: tst \irqstat, #15
+ bne 1002f
+ add \irqnr, \irqnr, #4
+ movs \irqstat, \irqstat, lsr #4
+ bne 1001b
+1002: tst \irqstat, #1
+ bne 1003f
+ add \irqnr, \irqnr, #1
+ movs \irqstat, \irqstat, lsr #1
+ bne 1002b
+1003: /* EQ will be set if no irqs pending */
+
+@ clz \irqnr, \irqstat
+@1003: /* EQ will be set if we reach MAXIRQNUM */
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
#elif defined(CONFIG_ARCH_CLPS711X)
#include <asm/hardware/clps7111.h>
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 304d7bc469e6..d3a81da57c3e 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -51,6 +51,39 @@ ENTRY(_find_next_zero_bit_le)
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
+/*
+ * Purpose : Find a 'one' bit
+ * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
+ */
+ENTRY(_find_first_bit_le)
+ teq r1, #0
+ beq 3f
+ mov r2, #0
+1: ldrb r3, [r0, r2, lsr #3]
+ movs r3, r3
+ bne .found @ any now set - found zero bit
+ add r2, r2, #8 @ next bit pointer
+2: cmp r2, r1 @ any more?
+ blo 1b
+3: mov r0, r1 @ no free bits
+ RETINSTR(mov,pc,lr)
+
+/*
+ * Purpose : Find next 'one' bit
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
+ */
+ENTRY(_find_next_bit_le)
+ teq r1, #0
+ beq 2b
+ ands ip, r2, #7
+ beq 1b @ If new byte, goto old routine
+ ldrb r3, [r0, r2, lsr #3]
+ movs r3, r3, lsr ip @ shift off unused bits
+ bne .found
+ orr r2, r2, #7 @ if zero, then no bits here
+ add r2, r2, #1 @ align bit pointer
+ b 2b @ loop for next bit
+
#ifdef __ARMEB__
ENTRY(_find_first_zero_bit_be)
@@ -78,6 +111,30 @@ ENTRY(_find_next_zero_bit_be)
addeq r2, r2, #1 @ align bit pointer
beq 2b @ loop for next bit
+ENTRY(_find_first_bit_be)
+ teq r1, #0
+ beq 3f
+ mov r2, #0
+1: eor r3, r2, #0x18 @ big endian byte ordering
+ ldrb r3, [r0, r3, lsr #3]
+ movs r3, r3
+ bne .found @ any now set - found zero bit
+ add r2, r2, #8 @ next bit pointer
+2: cmp r2, r1 @ any more?
+ blo 1b
+3: mov r0, r1 @ no free bits
+ RETINSTR(mov,pc,lr)
+
+ENTRY(_find_next_bit_be)
+ ands ip, r2, #7
+ beq 1b @ If new byte, goto old routine
+ eor r3, r2, #0x18 @ big endian byte ordering
+ ldrb r3, [r0, r3, lsr #3]
+ movs r3, r3, lsr ip @ shift off unused bits
+ orreq r2, r2, #7 @ if zero, then no bits here
+ addeq r2, r2, #1 @ align bit pointer
+ beq 2b @ loop for next bit
+
#endif
/*
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
new file mode 100644
index 000000000000..fbf6db8a2cbe
--- /dev/null
+++ b/arch/arm/mach-versatile/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := core.o
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
new file mode 100644
index 000000000000..22c0254b4d0d
--- /dev/null
+++ b/arch/arm/mach-versatile/core.c
@@ -0,0 +1,507 @@
+/*
+ * linux/arch/arm/mach-versatile/core.c
+ *
+ * Copyright (C) 1999 - 2003 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/amba.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/mmc.h>
+
+/*
+ * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
+ * is the (PA >> 12).
+ *
+ * Setup a VA for the Versatile Vectored Interrupt Controller.
+ */
+#define VA_VIC_BASE IO_ADDRESS(VERSATILE_VIC_BASE)
+#define VA_SIC_BASE IO_ADDRESS(VERSATILE_SIC_BASE)
+
+static void vic_mask_irq(unsigned int irq)
+{
+ irq -= IRQ_VIC_START;
+ writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
+}
+
+static void vic_unmask_irq(unsigned int irq)
+{
+ irq -= IRQ_VIC_START;
+ writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE);
+}
+
+static struct irqchip vic_chip = {
+ .ack = vic_mask_irq,
+ .mask = vic_mask_irq,
+ .unmask = vic_unmask_irq,
+};
+
+static void sic_mask_irq(unsigned int irq)
+{
+ irq -= IRQ_SIC_START;
+ writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
+}
+
+static void sic_unmask_irq(unsigned int irq)
+{
+ irq -= IRQ_SIC_START;
+ writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
+}
+
+static struct irqchip sic_chip = {
+ .ack = sic_mask_irq,
+ .mask = sic_mask_irq,
+ .unmask = sic_unmask_irq,
+};
+
+static void
+sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
+
+ if (status == 0) {
+ do_bad_IRQ(irq, desc, regs);
+ return;
+ }
+
+ do {
+ irq = ffs(status) - 1;
+ status &= ~(1 << irq);
+
+ irq += IRQ_SIC_START;
+
+ desc = irq_desc + irq;
+ desc->handle(irq, desc, regs);
+ } while (status);
+}
+
+#if 1
+#define IRQ_MMCI0A IRQ_VICSOURCE22
+#define IRQ_MMCI1A IRQ_VICSOURCE23
+#define IRQ_AACI IRQ_VICSOURCE24
+#define IRQ_ETH IRQ_VICSOURCE25
+#define PIC_MASK 0xFFD00000
+#else
+#define IRQ_MMCI0A IRQ_SIC_MMCI0A
+#define IRQ_MMCI1A IRQ_SIC_MMCI1A
+#define IRQ_AACI IRQ_SIC_AACI
+#define IRQ_ETH IRQ_SIC_ETH
+#define PIC_MASK 0
+#endif
+
+static void __init versatile_init_irq(void)
+{
+ unsigned int i, value;
+
+ /* Disable all interrupts initially. */
+
+ writel(0, VA_VIC_BASE + VIC_INT_SELECT);
+ writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE);
+ writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
+ writel(0, VA_VIC_BASE + VIC_IRQ_STATUS);
+ writel(0, VA_VIC_BASE + VIC_ITCR);
+ writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR);
+
+ /*
+ * Make sure we clear all existing interrupts
+ */
+ writel(0, VA_VIC_BASE + VIC_VECT_ADDR);
+ for (i = 0; i < 19; i++) {
+ value = readl(VA_VIC_BASE + VIC_VECT_ADDR);
+ writel(value, VA_VIC_BASE + VIC_VECT_ADDR);
+ }
+
+ for (i = 0; i < 16; i++) {
+ value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
+ writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
+ }
+
+ writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR);
+
+ for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) {
+ if (i != IRQ_VICSOURCE31) {
+ set_irq_chip(i, &vic_chip);
+ set_irq_handler(i, do_level_IRQ);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+ }
+
+ set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
+ vic_unmask_irq(IRQ_VICSOURCE31);
+
+ /* Do second interrupt controller */
+ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
+
+ for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
+ if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
+ set_irq_chip(i, &sic_chip);
+ set_irq_handler(i, do_level_IRQ);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+ }
+
+ /*
+ * Interrupts on secondary controller from 0 to 8 are routed to
+ * source 31 on PIC.
+ * Interrupts from 21 to 31 are routed directly to the VIC on
+ * the corresponding number on primary controller. This is controlled
+ * by setting PIC_ENABLEx.
+ */
+ writel(PIC_MASK, VA_SIC_BASE + SIC_INT_PIC_ENABLE);
+}
+
+static struct map_desc versatile_io_desc[] __initdata = {
+ { IO_ADDRESS(VERSATILE_SYS_BASE), VERSATILE_SYS_BASE, SZ_4K, MT_DEVICE },
+ { IO_ADDRESS(VERSATILE_SIC_BASE), VERSATILE_SIC_BASE, SZ_4K, MT_DEVICE },
+ { IO_ADDRESS(VERSATILE_VIC_BASE), VERSATILE_VIC_BASE, SZ_4K, MT_DEVICE },
+ { IO_ADDRESS(VERSATILE_SCTL_BASE), VERSATILE_SCTL_BASE, SZ_4K * 9, MT_DEVICE },
+#ifdef CONFIG_DEBUG_LL
+ { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
+#endif
+#ifdef FIXME
+ { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
+ { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
+ { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
+ { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE },
+#endif
+};
+
+static void __init versatile_map_io(void)
+{
+ iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
+}
+
+#define VERSATILE_REFCOUNTER (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
+
+/*
+ * This is the VersatilePB sched_clock implementation. This has
+ * a resolution of 41.7ns, and a maximum value of about 179s.
+ */
+unsigned long long sched_clock(void)
+{
+ unsigned long long v;
+
+ v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125;
+ do_div(v, 3);
+
+ return v;
+}
+
+
+#define VERSATILE_FLASHCTRL (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
+
+static int versatile_flash_init(void)
+{
+ u32 val;
+
+ val = __raw_readl(VERSATILE_FLASHCTRL);
+ val &= ~VERSATILE_FLASHPROG_FLVPPEN;
+ __raw_writel(val, VERSATILE_FLASHCTRL);
+
+ return 0;
+}
+
+static void versatile_flash_exit(void)
+{
+ u32 val;
+
+ val = __raw_readl(VERSATILE_FLASHCTRL);
+ val &= ~VERSATILE_FLASHPROG_FLVPPEN;
+ __raw_writel(val, VERSATILE_FLASHCTRL);
+}
+
+static void versatile_flash_set_vpp(int on)
+{
+ u32 val;
+
+ val = __raw_readl(VERSATILE_FLASHCTRL);
+ if (on)
+ val |= VERSATILE_FLASHPROG_FLVPPEN;
+ else
+ val &= ~VERSATILE_FLASHPROG_FLVPPEN;
+ __raw_writel(val, VERSATILE_FLASHCTRL);
+}
+
+static struct flash_platform_data versatile_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 4,
+ .init = versatile_flash_init,
+ .exit = versatile_flash_exit,
+ .set_vpp = versatile_flash_set_vpp,
+};
+
+static struct resource versatile_flash_resource = {
+ .start = VERSATILE_FLASH_BASE,
+ .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device versatile_flash_device = {
+ .name = "armflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &versatile_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &versatile_flash_resource,
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = VERSATILE_ETH_BASE,
+ .end = VERSATILE_ETH_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ETH,
+ .end = IRQ_ETH,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+#define VERSATILE_SYSMCI (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
+
+static unsigned int mmc_status(struct device *dev)
+{
+ struct amba_device *adev = container_of(dev, struct amba_device, dev);
+ u32 mask;
+
+ if (adev->res.start == VERSATILE_MMCI0_BASE)
+ mask = 1;
+ else
+ mask = 2;
+
+ return readl(VERSATILE_SYSMCI) & mask;
+}
+
+static struct mmc_platform_data mmc0_plat_data = {
+ .mclk = 33000000,
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+};
+
+static struct mmc_platform_data mmc1_plat_data = {
+ .mclk = 33000000,
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+};
+
+#define AMBA_DEVICE(name,busid,base,plat) \
+static struct amba_device name##_device = { \
+ .dev = { \
+ .coherent_dma_mask = ~0, \
+ .bus_id = busid, \
+ .platform_data = plat, \
+ }, \
+ .res = { \
+ .start = VERSATILE_##base##_BASE, \
+ .end = (VERSATILE_##base##_BASE) + SZ_4K - 1,\
+ .flags = IORESOURCE_MEM, \
+ }, \
+ .irq = base##_IRQ, \
+ .dma = base##_DMA, \
+}
+
+#define AACI_IRQ { IRQ_AACI, NO_IRQ }
+#define AACI_DMA { 0x80, 0x81 }
+#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B }
+#define MMCI0_DMA { 0x84, 0 }
+#define KMI0_IRQ { IRQ_SIC_KMI0, NO_IRQ }
+#define KMI0_DMA { 0, 0 }
+#define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ }
+#define KMI1_DMA { 0, 0 }
+#define UART3_IRQ { IRQ_SIC_UART3, NO_IRQ }
+#define UART3_DMA { 0x86, 0x87 }
+#define SCI1_IRQ { IRQ_SIC_SCI3, NO_IRQ }
+#define SCI1_DMA { 0x88, 0x89 }
+#define MMCI1_IRQ { IRQ_MMCI1A, IRQ_SIC_MMCI1B }
+#define MMCI1_DMA { 0x85, 0 }
+
+/*
+ * These devices are connected directly to the multi-layer AHB switch
+ */
+#define SMC_IRQ { NO_IRQ, NO_IRQ }
+#define SMC_DMA { 0, 0 }
+#define MPMC_IRQ { NO_IRQ, NO_IRQ }
+#define MPMC_DMA { 0, 0 }
+#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
+#define CLCD_DMA { 0, 0 }
+#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
+#define DMAC_DMA { 0, 0 }
+
+/*
+ * These devices are connected via the core APB bridge
+ */
+#define SCTL_IRQ { NO_IRQ, NO_IRQ }
+#define SCTL_DMA { 0, 0 }
+#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
+#define WATCHDOG_DMA { 0, 0 }
+#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
+#define GPIO0_DMA { 0, 0 }
+#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
+#define GPIO1_DMA { 0, 0 }
+#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
+#define GPIO2_DMA { 0, 0 }
+#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
+#define GPIO3_DMA { 0, 0 }
+#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
+#define RTC_DMA { 0, 0 }
+
+/*
+ * These devices are connected via the DMA APB bridge
+ */
+#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
+#define SCI_DMA { 7, 6 }
+#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
+#define UART0_DMA { 15, 14 }
+#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
+#define UART1_DMA { 13, 12 }
+#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
+#define UART2_DMA { 11, 10 }
+#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
+#define SSP_DMA { 9, 8 }
+
+/* FPGA Primecells */
+AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
+AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &mmc0_plat_data);
+AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
+AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
+AMBA_DEVICE(uart3, "fpga:09", UART3, NULL);
+AMBA_DEVICE(sci1, "fpga:0a", SCI1, NULL);
+AMBA_DEVICE(mmc1, "fpga:0b", MMCI1, &mmc1_plat_data);
+
+/* DevChip Primecells */
+AMBA_DEVICE(smc, "dev:00", SMC, NULL);
+AMBA_DEVICE(mpmc, "dev:10", MPMC, NULL);
+AMBA_DEVICE(clcd, "dev:20", CLCD, NULL);
+AMBA_DEVICE(dmac, "dev:30", DMAC, NULL);
+AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
+AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL);
+AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL);
+AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
+AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
+AMBA_DEVICE(gpio3, "dev:e7", GPIO3, NULL);
+AMBA_DEVICE(rtc, "dev:e8", RTC, NULL);
+AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
+AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
+AMBA_DEVICE(uart1, "dev:f2", UART1, NULL);
+AMBA_DEVICE(uart2, "dev:f3", UART2, NULL);
+AMBA_DEVICE(ssp0, "dev:f4", SSP, NULL);
+
+static struct amba_device *amba_devs[] __initdata = {
+ &dmac_device,
+ &uart0_device,
+ &uart1_device,
+ &uart2_device,
+ &uart3_device,
+ &smc_device,
+ &mpmc_device,
+ &clcd_device,
+ &sctl_device,
+ &wdog_device,
+ &gpio0_device,
+ &gpio1_device,
+ &gpio2_device,
+ &gpio3_device,
+ &rtc_device,
+ &sci0_device,
+ &ssp0_device,
+ &aaci_device,
+ &mmc0_device,
+ &kmi0_device,
+ &kmi1_device,
+ &sci1_device,
+ &mmc1_device,
+};
+
+#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
+
+static void versatile_leds_event(led_event_t ledevt)
+{
+ unsigned long flags;
+ u32 val;
+
+ local_irq_save(flags);
+ val = readl(VA_LEDS_BASE);
+
+ switch (ledevt) {
+ case led_idle_start:
+ val = val & ~VERSATILE_SYS_LED0;
+ break;
+
+ case led_idle_end:
+ val = val | VERSATILE_SYS_LED0;
+ break;
+
+ case led_timer:
+ val = val ^ VERSATILE_SYS_LED1;
+ break;
+
+ case led_halted:
+ val = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ writel(val, VA_LEDS_BASE);
+ local_irq_restore(flags);
+}
+
+static void __init versatile_init(void)
+{
+ int i;
+
+ platform_add_device(&versatile_flash_device);
+ platform_add_device(&smc91x_device);
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
+
+ leds_event = versatile_leds_event;
+}
+
+MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
+ MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
+ BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000)
+ BOOT_PARAMS(0x00000100)
+ MAPIO(versatile_map_io)
+ INITIRQ(versatile_init_irq)
+ INIT_MACHINE(versatile_init)
+MACHINE_END
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 67c0834959ac..d7968d6896ee 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -114,8 +114,9 @@ config CPU_ARM925T
# ARM926T
config CPU_ARM926T
- bool "Support ARM926T processor"
- depends on ARCH_INTEGRATOR || ARCH_OMAP1610
+ bool "Support ARM926T processor" if ARCH_INTEGRATOR
+ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || ARCH_OMAP1610
+ default y if ARCH_VERSATILE_PB
select CPU_32v5
select CPU_ABRT_EV5TJ
select CPU_COPY_V4WB
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index d2ffd9016c07..f0a49fec0d9e 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -165,18 +165,6 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
c_backtrace(fp, processor_mode(regs));
}
-/*
- * This is called from SysRq-T (show_task) to display the current
- * call trace for each process. Very useful.
- */
-void show_trace_task(struct task_struct *tsk)
-{
- if (tsk != current) {
- unsigned int fp = thread_saved_fp(tsk);
- c_backtrace(fp, 0x10);
- }
-}
-
/* FIXME - this is probably wrong.. */
void show_stack(struct task_struct *task, unsigned long *sp) {
dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info);
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
index 2a757b825c44..d9e6565655f4 100644
--- a/arch/cris/kernel/traps.c
+++ b/arch/cris/kernel/traps.c
@@ -60,14 +60,6 @@ void show_trace(unsigned long * stack)
}
}
-void show_trace_task(struct task_struct *tsk)
-{
- /* TODO, this is not really useful since its called from
- * SysRq-T and we don't have a keyboard.. :)
- */
-}
-
-
/*
* These constants are for searching for possible module text
* segments. MODULE_RANGE is a guess of how much space is likely
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
index 300e3279ca5a..253c87bc5b32 100644
--- a/arch/h8300/kernel/traps.c
+++ b/arch/h8300/kernel/traps.c
@@ -156,14 +156,8 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- show_stack(tsk,(unsigned long *)tsk->thread.esp0);
-}
-
void dump_stack(void)
{
show_stack(NULL,NULL);
}
-
EXPORT_SYMBOL(dump_stack);
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
index 12ff2d16f13f..8c056882df27 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c
@@ -238,6 +238,34 @@ acpi_cpufreq_verify (
}
+static unsigned long
+acpi_cpufreq_guess_freq (
+ struct cpufreq_acpi_io *data,
+ unsigned int cpu)
+{
+ if (cpu_khz) {
+ /* search the closest match to cpu_khz */
+ unsigned int i;
+ unsigned long freq;
+ unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
+
+ for (i=0; i < (data->acpi_data.state_count - 1); i++) {
+ freq = freqn;
+ freqn = data->acpi_data.states[i+1].core_frequency * 1000;
+ if ((2 * cpu_khz) > (freqn + freq)) {
+ data->acpi_data.state = i;
+ return (freq);
+ }
+ }
+ data->acpi_data.state = data->acpi_data.state_count - 1;
+ return (freqn);
+ } else
+ /* assume CPU is at P0... */
+ data->acpi_data.state = 0;
+ return data->acpi_data.states[0].core_frequency * 1000;
+
+}
+
static int
acpi_cpufreq_cpu_init (
struct cpufreq_policy *policy)
@@ -290,11 +318,8 @@ acpi_cpufreq_cpu_init (
}
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- /*
- * The current speed is unknown and not detectable by ACPI... argh! Assume
- * it's P0, it will be set to this value later during initialization.
- */
- policy->cur = data->acpi_data.states[0].core_frequency * 1000;
+ /* The current speed is unknown and not detectable by ACPI... */
+ policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
/* table init */
for (i=0; i<=data->acpi_data.state_count; i++)
@@ -306,7 +331,7 @@ acpi_cpufreq_cpu_init (
data->freq_table[i].frequency = CPUFREQ_TABLE_END;
}
- result = cpufreq_frequency_table_cpuinfo(policy, &data->freq_table[0]);
+ result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
if (result) {
goto err_freqfree;
}
@@ -321,6 +346,7 @@ acpi_cpufreq_cpu_init (
(u32) data->acpi_data.states[i].power,
(u32) data->acpi_data.states[i].transition_latency);
+ cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
return_VALUE(result);
err_freqfree:
@@ -345,6 +371,7 @@ acpi_cpufreq_cpu_exit (
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit");
if (data) {
+ cpufreq_frequency_table_put_attr(policy->cpu);
acpi_io_data[policy->cpu] = NULL;
acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
kfree(data);
@@ -354,6 +381,11 @@ acpi_cpufreq_cpu_exit (
}
+static struct freq_attr* acpi_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
static struct cpufreq_driver acpi_cpufreq_driver = {
.verify = acpi_cpufreq_verify,
.target = acpi_cpufreq_target,
@@ -361,6 +393,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.exit = acpi_cpufreq_cpu_exit,
.name = "acpi-cpufreq",
.owner = THIS_MODULE,
+ .attr = acpi_cpufreq_attr,
};
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 8b95e88c95d3..65246256fd07 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -17,6 +17,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/slab.h>
@@ -27,6 +28,11 @@
#include <asm/io.h>
#include <asm/system.h>
+#ifdef CONFIG_ACPI_PROCESSOR
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#endif
+
#include "powernow-k7.h"
#define DEBUG
@@ -57,6 +63,17 @@ struct pst_s {
u8 numpstates;
};
+#ifdef CONFIG_ACPI_PROCESSOR
+union powernow_acpi_control_t {
+ struct {
+ unsigned long fid:5,
+ vid:5,
+ sgtc:20,
+ res1:2;
+ } bits;
+ unsigned long val;
+};
+#endif
/* divide by 1000 to get VID. */
static int mobile_vid_table[32] = {
@@ -74,6 +91,12 @@ static int fid_codes[32] = {
150, 225, 160, 165, 170, 180, -1, -1,
};
+/* This parameter is used in order to force ACPI instead of legacy method for
+ * configuration purpose.
+ */
+
+static int powernow_acpi_force;
+
static struct cpufreq_frequency_table *powernow_table;
static unsigned int can_scale_bus;
@@ -85,6 +108,14 @@ static unsigned int fsb;
static unsigned int latency;
static char have_a0;
+static int check_fsb(unsigned int fsbspeed)
+{
+ int delta;
+ unsigned int f = fsb / 1000;
+
+ delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
+ return (delta < 5);
+}
static int check_powernow(void)
{
@@ -140,7 +171,8 @@ static int check_powernow(void)
static int get_ranges (unsigned char *pst)
{
- unsigned int j, speed;
+ unsigned int j;
+ unsigned int speed;
u8 fid, vid;
powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
@@ -151,12 +183,12 @@ static int get_ranges (unsigned char *pst)
for (j=0 ; j < number_scales; j++) {
fid = *pst++;
- powernow_table[j].frequency = fsb * fid_codes[fid] * 100;
+ powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
powernow_table[j].index = fid; /* lower 8 bits */
- speed = fsb * (fid_codes[fid]/10);
+ speed = powernow_table[j].frequency;
+
if ((fid_codes[fid] % 10)==5) {
- speed += fsb/2;
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
if (have_a0 == 1)
powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
@@ -164,7 +196,7 @@ static int get_ranges (unsigned char *pst)
}
dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid,
- fid_codes[fid] / 10, fid_codes[fid] % 10, speed);
+ fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
if (speed < minimum_speed)
minimum_speed = speed;
@@ -176,8 +208,6 @@ static int get_ranges (unsigned char *pst)
dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000,
mobile_vid_table[vid]%1000);
}
- dprintk ("\n");
-
powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
powernow_table[number_scales].index = 0;
@@ -234,7 +264,8 @@ static void change_speed (unsigned int index)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
cfid = fidvidstatus.bits.CFID;
- freqs.old = fsb * fid_codes[cfid] * 100;
+ freqs.old = fsb * fid_codes[cfid] / 10;
+
freqs.new = powernow_table[index].frequency;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -262,19 +293,136 @@ static void change_speed (unsigned int index)
}
+#ifdef CONFIG_ACPI_PROCESSOR
+
+struct acpi_processor_performance *acpi_processor_perf;
+
+static int powernow_acpi_init(void)
+{
+ int i;
+ int retval = 0;
+ union powernow_acpi_control_t pc;
+
+ if (acpi_processor_perf != NULL && powernow_table != NULL) {
+ retval = -EINVAL;
+ goto err0;
+ }
+
+ acpi_processor_perf = kmalloc(sizeof(struct acpi_processor_performance),
+ GFP_KERNEL);
+
+ if (!acpi_processor_perf) {
+ retval = -ENOMEM;
+ goto err0;
+ }
+
+ memset(acpi_processor_perf, 0, sizeof(struct acpi_processor_performance));
+
+ if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
+ retval = -EIO;
+ goto err1;
+ }
+
+ if (acpi_processor_perf->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
+ retval = -ENODEV;
+ goto err2;
+ }
+
+ if (acpi_processor_perf->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
+ retval = -ENODEV;
+ goto err2;
+ }
+
+ number_scales = acpi_processor_perf->state_count;
+
+ if (number_scales < 2) {
+ retval = -ENODEV;
+ goto err2;
+ }
+
+ powernow_table = kmalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL);
+ if (!powernow_table) {
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ memset(powernow_table, 0, ((number_scales + 1) * sizeof(struct cpufreq_frequency_table)));
+
+ pc.val = (unsigned long) acpi_processor_perf->states[0].control;
+ for (i = 0; i < number_scales; i++) {
+ u8 fid, vid;
+ unsigned int speed;
+
+ pc.val = (unsigned long) acpi_processor_perf->states[i].control;
+ dprintk (KERN_INFO PFX "acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
+ i,
+ (u32) acpi_processor_perf->states[i].core_frequency,
+ (u32) acpi_processor_perf->states[i].power,
+ (u32) acpi_processor_perf->states[i].transition_latency,
+ (u32) acpi_processor_perf->states[i].control,
+ pc.bits.sgtc);
+
+ vid = pc.bits.vid;
+ fid = pc.bits.fid;
+
+ powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
+ powernow_table[i].index = fid; /* lower 8 bits */
+ powernow_table[i].index |= (vid << 8); /* upper 8 bits */
+
+ speed = powernow_table[i].frequency;
+
+ if ((fid_codes[fid] % 10)==5) {
+ if (have_a0 == 1)
+ powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+ }
+
+ dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid,
+ fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
+ dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000,
+ mobile_vid_table[vid]%1000);
+
+ if (latency < pc.bits.sgtc)
+ latency = pc.bits.sgtc;
+
+ if (speed < minimum_speed)
+ minimum_speed = speed;
+ if (speed > maximum_speed)
+ maximum_speed = speed;
+ }
+
+ powernow_table[i].frequency = CPUFREQ_TABLE_END;
+ powernow_table[i].index = 0;
+
+ return 0;
+
+err2:
+ acpi_processor_unregister_performance(acpi_processor_perf, 0);
+err1:
+ kfree(acpi_processor_perf);
+err0:
+ printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
+ acpi_processor_perf = NULL;
+ return retval;
+}
+#else
+static int powernow_acpi_init(void)
+{
+ printk(KERN_INFO PFX "no support for ACPI processor found."
+ " Please recompile your kernel with ACPI processor\n");
+ return -EINVAL;
+}
+#endif
+
static int powernow_decode_bios (int maxfid, int startvid)
{
struct psb_s *psb;
struct pst_s *pst;
- struct cpuinfo_x86 *c = cpu_data;
unsigned int i, j;
unsigned char *p;
unsigned int etuple;
unsigned int ret;
etuple = cpuid_eax(0x80000001);
- etuple &= 0xf00;
- etuple |= (c->x86_model<<4)|(c->x86_mask);
for (i=0xC0000; i < 0xffff0 ; i+=16) {
@@ -305,7 +453,6 @@ static int powernow_decode_bios (int maxfid, int startvid)
}
dprintk (KERN_INFO PFX "Settling Time: %d microseconds.\n", psb->settlingtime);
dprintk (KERN_INFO PFX "Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst);
- latency *= 100; /* SGTC needs to be in units of 10ns */
p += sizeof (struct psb_s);
@@ -315,7 +462,8 @@ static int powernow_decode_bios (int maxfid, int startvid)
pst = (struct pst_s *) p;
number_scales = pst->numpstates;
- if ((etuple == pst->cpuid) && (maxfid==pst->maxfid) && (startvid==pst->startvid))
+ if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
+ (maxfid==pst->maxfid) && (startvid==pst->startvid))
{
dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);
dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid);
@@ -323,7 +471,6 @@ static int powernow_decode_bios (int maxfid, int startvid)
dprintk ("maxFID: 0x%x\t", pst->maxfid);
dprintk ("startvid: 0x%x\n", pst->startvid);
- fsb = pst->fsbspeed;
ret = get_ranges ((char *) pst + sizeof (struct pst_s));
return ret;
@@ -335,7 +482,7 @@ static int powernow_decode_bios (int maxfid, int startvid)
}
printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");
- printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n");
+
return -EINVAL;
}
p++;
@@ -365,6 +512,33 @@ static int powernow_verify (struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, powernow_table);
}
+/*
+ * We use the fact that the bus frequency is somehow
+ * a multiple of 100000/3 khz, then we compute sgtc according
+ * to this multiple.
+ * That way, we match more how AMD thinks all of that work.
+ * We will then get the same kind of behaviour already tested under
+ * the "well-known" other OS.
+ */
+static int __init fixup_sgtc(void)
+{
+ unsigned int sgtc;
+ unsigned int m;
+
+ m = fsb / 3333;
+ if ((m % 10) >= 5)
+ m += 5;
+
+ m /= 10;
+
+ sgtc = 100 * m * latency;
+ sgtc = sgtc / 3;
+ if (sgtc > 0xfffff) {
+ printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
+ sgtc = 0xfffff;
+ }
+ return sgtc;
+}
static int __init powernow_cpu_init (struct cpufreq_policy *policy)
{
@@ -376,18 +550,45 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
- result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
+ /* A K7 with powernow technology is set to max frequency by BIOS */
+ fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
+ if (!fsb) {
+ printk(KERN_WARNING PFX "can not determine bus frequency\n");
+ return -EINVAL;
+ }
+ dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
+
+ if ((dmi_broken & BROKEN_CPUFREQ) || powernow_acpi_force) {
+ printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
+ result = powernow_acpi_init();
+ } else {
+ result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
+ if (result) {
+ printk (KERN_INFO PFX "Trying ACPI perflib\n");
+ maximum_speed = 0;
+ minimum_speed = -1;
+ latency = 0;
+ result = powernow_acpi_init();
+ if (result) {
+ printk (KERN_INFO PFX "ACPI and legacy methods failed\n");
+ printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n");
+ }
+ } else {
+ /* SGTC use the bus clock as timer */
+ latency = fixup_sgtc();
+ printk(KERN_INFO PFX "SGTC: %d\n", latency);
+ }
+ }
+
if (result)
return result;
printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
- minimum_speed, maximum_speed);
+ minimum_speed/1000, maximum_speed/1000);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- /* latency is in 10 ns (look for SGTC above) for each VID
- * and FID transition, so multiply that value with 20 */
- policy->cpuinfo.transition_latency = latency * 20;
+ policy->cpuinfo.transition_latency = 20 * latency / fsb;
policy->cur = maximum_speed;
@@ -418,10 +619,6 @@ static struct cpufreq_driver powernow_driver = {
static int __init powernow_init (void)
{
- if (dmi_broken & BROKEN_CPUFREQ) {
- printk (KERN_INFO PFX "Disabled at boot time by DMI,\n");
- return -ENODEV;
- }
if (check_powernow()==0)
return -ENODEV;
return cpufreq_register_driver(&powernow_driver);
@@ -430,15 +627,25 @@ static int __init powernow_init (void)
static void __exit powernow_exit (void)
{
+#ifdef CONFIG_ACPI_PROCESSOR
+ if (acpi_processor_perf) {
+ acpi_processor_unregister_performance(acpi_processor_perf, 0);
+ kfree(acpi_processor_perf);
+ }
+#endif
cpufreq_unregister_driver(&powernow_driver);
if (powernow_table)
kfree(powernow_table);
}
+module_param(powernow_acpi_force, int, 0444);
+
+MODULE_PARM_DESC(acpi_force, "Force ACPI to be used");
+
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
MODULE_LICENSE ("GPL");
-module_init(powernow_init);
+late_initcall(powernow_init);
module_exit(powernow_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index aa387c4b46eb..862bcf5dd997 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -32,7 +32,7 @@
#include <asm/io.h>
#include <asm/delay.h>
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
+#ifdef CONFIG_ACPI_PROCESSOR
#include <linux/acpi.h>
#include <acpi/processor.h>
#endif
@@ -269,7 +269,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
dprintk(KERN_DEBUG PFX
"ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
- smp_processor_id();
+ smp_processor_id(),
data->currfid, data->currvid, reqvid, data->rvo);
while (data->currvid > reqvid) {
@@ -666,7 +666,7 @@ static int find_psb_table(struct powernow_k8_data *data)
return -ENODEV;
}
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
+#ifdef CONFIG_ACPI_PROCESSOR
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
{
if (!data->acpi_data.state_count)
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 921d032c3764..20564ef0858c 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -29,7 +29,7 @@ struct powernow_k8_data {
* frequency is in kHz */
struct cpufreq_frequency_table *powernow_table;
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
+#ifdef CONFIG_ACPI_PROCESSOR
/* the acpi table needs to be kept. it's only available if ACPI was
* used to determine valid frequency/vid/fid states */
struct acpi_processor_performance acpi_data;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 2adb46c0ac78..da46fb82edc9 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -195,21 +195,6 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
struct cpu_model *model;
- if (!cpu_has(cpu, X86_FEATURE_EST))
- return -ENODEV;
-
- /* Only Intel Pentium M stepping 5 for now - add new CPUs as
- they appear after making sure they use PERF_CTL in the same
- way. */
- if (cpu->x86_vendor != X86_VENDOR_INTEL ||
- cpu->x86 != 6 ||
- cpu->x86_model != 9 ||
- cpu->x86_mask != 5) {
- printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
- "send /proc/cpuinfo to " MAINTAINER "\n");
- return -ENODEV;
- }
-
for(model = models; model->model_name != NULL; model++)
if (strcmp(cpu->x86_model_id, model->model_name) == 0)
break;
@@ -361,6 +346,7 @@ static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return
static int centrino_cpu_init(struct cpufreq_policy *policy)
{
+ struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
unsigned freq;
unsigned l, h;
int ret;
@@ -368,6 +354,21 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -ENODEV;
+ if (!cpu_has(cpu, X86_FEATURE_EST))
+ return -ENODEV;
+
+ /* Only Intel Pentium M stepping 5 for now - add new CPUs as
+ they appear after making sure they use PERF_CTL in the same
+ way. */
+ if (cpu->x86_vendor != X86_VENDOR_INTEL ||
+ cpu->x86 != 6 ||
+ cpu->x86_model != 9 ||
+ cpu->x86_mask != 5) {
+ printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
+ "send /proc/cpuinfo to " MAINTAINER "\n");
+ return -ENODEV;
+ }
+
if (centrino_cpu_init_acpi(policy)) {
if (centrino_cpu_init_table(policy)) {
return -ENODEV;
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index f424fc369fb1..0be8d6b87cf7 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -445,5 +445,5 @@ void __init init_IRQ(void)
if (boot_cpu_data.hard_math && !cpu_has_fpu)
setup_irq(FPU_IRQ, &fpu_irq);
- irq_ctx_init(current_thread_info()->cpu);
+ irq_ctx_init(smp_processor_id());
}
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index d74fb46abd31..574ae5814333 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -462,8 +462,7 @@ void nmi_watchdog_tick (struct pt_regs * regs)
/* 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);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
}
wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index cf8da7ba4cdb..c770d878cbcf 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -123,16 +123,6 @@ void show_trace(struct task_struct *task, unsigned long * stack)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- unsigned long esp = tsk->thread.esp;
-
- /* User space on another CPU? */
- if ((esp ^ (unsigned long)tsk->thread_info) & ~(THREAD_SIZE - 1))
- return;
- show_trace(tsk, (unsigned long *)esp);
-}
-
void show_stack(struct task_struct *task, unsigned long *esp)
{
unsigned long *stack;
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 6bc3a824b0a9..1b2b4937052f 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -210,19 +210,18 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
{
struct mm_struct *mm = vma->vm_mm;
unsigned long address;
- pte_t *pte;
+ pte_t pte;
struct page *page;
BUG_ON(start & (HPAGE_SIZE - 1));
BUG_ON(end & (HPAGE_SIZE - 1));
for (address = start; address < end; address += HPAGE_SIZE) {
- pte = huge_pte_offset(mm, address);
- if (pte_none(*pte))
+ pte = ptep_get_and_clear(huge_pte_offset(mm, address));
+ if (pte_none(pte))
continue;
- page = pte_page(*pte);
+ page = pte_page(pte);
huge_page_release(page);
- pte_clear(pte);
}
mm->rss -= (end - start) >> PAGE_SHIFT;
flush_tlb_range(vma, start, end);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index d72026927fec..752dbd3e93fb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -126,11 +126,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- show_trace(tsk, (long *)tsk->thread.reg29);
-}
-
/*
* The architecture-independent dump_stack generator
*/
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index f83053a37644..6f1f6f738d6c 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -202,11 +202,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- show_trace(tsk, (unsigned long *)tsk->thread.regs.ksp);
-}
-
void die_if_kernel(char *str, struct pt_regs *regs, long err)
{
if (user_mode(regs)) {
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index f74b14d7e58e..7c153dc24895 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -536,10 +536,4 @@ void dump_stack(void)
{
show_stack(current, (unsigned long *)__get_SP());
}
-
EXPORT_SYMBOL(dump_stack);
-
-void show_trace_task(struct task_struct *tsk)
-{
- show_stack(tsk, (unsigned long *)tsk->thread.ksp);
-}
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 9525ee20aa0e..a4a727aab6f7 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -44,7 +44,7 @@ head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o
head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o
head-y += arch/$(ARCH)/kernel/init_task.o
-core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ \
+core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
arch/$(ARCH)/appldata/
libs-y += arch/$(ARCH)/lib/
drivers-y += drivers/s390/
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
new file mode 100644
index 000000000000..96a05e6b51e0
--- /dev/null
+++ b/arch/s390/crypto/Makefile
@@ -0,0 +1,8 @@
+#
+# Cryptographic API
+#
+
+obj-$(CONFIG_CRYPTO_SHA1_Z990) += sha1_z990.o
+obj-$(CONFIG_CRYPTO_DES_Z990) += des_z990.o des_check_key.o
+
+obj-$(CONFIG_CRYPTO_TEST) += crypt_z990_query.o
diff --git a/arch/s390/crypto/crypt_z990.h b/arch/s390/crypto/crypt_z990.h
new file mode 100644
index 000000000000..4df660b99e5a
--- /dev/null
+++ b/arch/s390/crypto/crypt_z990.h
@@ -0,0 +1,374 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for z990 cryptographic instructions.
+ *
+ * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_ARCH_S390_CRYPT_Z990_H
+#define _CRYPTO_ARCH_S390_CRYPT_Z990_H
+
+#include <asm/errno.h>
+
+#define CRYPT_Z990_OP_MASK 0xFF00
+#define CRYPT_Z990_FUNC_MASK 0x00FF
+
+
+/*z990 cryptographic operations*/
+enum crypt_z990_operations {
+ CRYPT_Z990_KM = 0x0100,
+ CRYPT_Z990_KMC = 0x0200,
+ CRYPT_Z990_KIMD = 0x0300,
+ CRYPT_Z990_KLMD = 0x0400,
+ CRYPT_Z990_KMAC = 0x0500
+};
+
+/*function codes for KM (CIPHER MESSAGE) instruction*/
+enum crypt_z990_km_func {
+ KM_QUERY = CRYPT_Z990_KM | 0,
+ KM_DEA_ENCRYPT = CRYPT_Z990_KM | 1,
+ KM_DEA_DECRYPT = CRYPT_Z990_KM | 1 | 0x80, //modifier bit->decipher
+ KM_TDEA_128_ENCRYPT = CRYPT_Z990_KM | 2,
+ KM_TDEA_128_DECRYPT = CRYPT_Z990_KM | 2 | 0x80,
+ KM_TDEA_192_ENCRYPT = CRYPT_Z990_KM | 3,
+ KM_TDEA_192_DECRYPT = CRYPT_Z990_KM | 3 | 0x80,
+};
+
+/*function codes for KMC (CIPHER MESSAGE WITH CHAINING) instruction*/
+enum crypt_z990_kmc_func {
+ KMC_QUERY = CRYPT_Z990_KMC | 0,
+ KMC_DEA_ENCRYPT = CRYPT_Z990_KMC | 1,
+ KMC_DEA_DECRYPT = CRYPT_Z990_KMC | 1 | 0x80, //modifier bit->decipher
+ KMC_TDEA_128_ENCRYPT = CRYPT_Z990_KMC | 2,
+ KMC_TDEA_128_DECRYPT = CRYPT_Z990_KMC | 2 | 0x80,
+ KMC_TDEA_192_ENCRYPT = CRYPT_Z990_KMC | 3,
+ KMC_TDEA_192_DECRYPT = CRYPT_Z990_KMC | 3 | 0x80,
+};
+
+/*function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) instruction*/
+enum crypt_z990_kimd_func {
+ KIMD_QUERY = CRYPT_Z990_KIMD | 0,
+ KIMD_SHA_1 = CRYPT_Z990_KIMD | 1,
+};
+
+/*function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) instruction*/
+enum crypt_z990_klmd_func {
+ KLMD_QUERY = CRYPT_Z990_KLMD | 0,
+ KLMD_SHA_1 = CRYPT_Z990_KLMD | 1,
+};
+
+/*function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) instruction*/
+enum crypt_z990_kmac_func {
+ KMAC_QUERY = CRYPT_Z990_KMAC | 0,
+ KMAC_DEA = CRYPT_Z990_KMAC | 1,
+ KMAC_TDEA_128 = CRYPT_Z990_KMAC | 2,
+ KMAC_TDEA_192 = CRYPT_Z990_KMAC | 3
+};
+
+/*status word for z990 crypto instructions' QUERY functions*/
+struct crypt_z990_query_status {
+ u64 high;
+ u64 low;
+};
+
+/*
+ * Standard fixup and ex_table sections for crypt_z990 inline functions.
+ * label 0: the z990 crypto operation
+ * label 1: just after 1 to catch illegal operation exception on non-z990
+ * label 6: the return point after fixup
+ * label 7: set error value if exception _in_ crypto operation
+ * label 8: set error value if illegal operation exception
+ * [ret] is the variable to receive the error code
+ * [ERR] is the error code value
+ */
+#ifndef __s390x__
+#define __crypt_z990_fixup \
+ ".section .fixup,\"ax\" \n" \
+ "7: lhi %0,%h[e1] \n" \
+ " bras 1,9f \n" \
+ " .long 6b \n" \
+ "8: lhi %0,%h[e2] \n" \
+ " bras 1,9f \n" \
+ " .long 6b \n" \
+ "9: l 1,0(1) \n" \
+ " br 1 \n" \
+ ".previous \n" \
+ ".section __ex_table,\"a\" \n" \
+ " .align 4 \n" \
+ " .long 0b,7b \n" \
+ " .long 1b,8b \n" \
+ ".previous"
+#else /* __s390x__ */
+#define __crypt_z990_fixup \
+ ".section .fixup,\"ax\" \n" \
+ "7: lhi %0,%h[e1] \n" \
+ " jg 6b \n" \
+ "8: lhi %0,%h[e2] \n" \
+ " jg 6b \n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\" \n" \
+ " .align 8 \n" \
+ " .quad 0b,7b \n" \
+ " .quad 1b,8b \n" \
+ ".previous"
+#endif /* __s390x__ */
+
+/*
+ * Standard code for setting the result of z990 crypto instructions.
+ * %0: the register which will receive the result
+ * [result]: the register containing the result (e.g. second operand length
+ * to compute number of processed bytes].
+ */
+#ifndef __s390x__
+#define __crypt_z990_set_result \
+ " lr %0,%[result] \n"
+#else /* __s390x__ */
+#define __crypt_z990_set_result \
+ " lgr %0,%[result] \n"
+#endif
+
+/*
+ * Executes the KM (CIPHER MESSAGE) operation of the z990 CPU.
+ * @param func: the function code passed to KM; see crypt_z990_km_func
+ * @param param: address of parameter block; see POP for details on each func
+ * @param dest: address of destination memory area
+ * @param src: address of source memory area
+ * @param src_len: length of src operand in bytes
+ * @returns < zero for failure, 0 for the query func, number of processed bytes
+ * for encryption/decryption funcs
+ */
+static inline int
+crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len)
+{
+ register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register void* __param asm("1") = param;
+ register u8* __dest asm("4") = dest;
+ register const u8* __src asm("2") = src;
+ register long __src_len asm("3") = src_len;
+ int ret;
+
+ ret = 0;
+ __asm__ __volatile__ (
+ "0: .insn rre,0xB92E0000,%1,%2 \n" //KM opcode
+ "1: brc 1,0b \n" //handle partial completion
+ __crypt_z990_set_result
+ "6: \n"
+ __crypt_z990_fixup
+ : "+d" (ret), "+a" (__dest), "+a" (__src),
+ [result] "+d" (__src_len)
+ : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
+ "a" (__param)
+ : "cc", "memory"
+ );
+ if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ ret = src_len - ret;
+ }
+ return ret;
+}
+
+/*
+ * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the z990 CPU.
+ * @param func: the function code passed to KM; see crypt_z990_kmc_func
+ * @param param: address of parameter block; see POP for details on each func
+ * @param dest: address of destination memory area
+ * @param src: address of source memory area
+ * @param src_len: length of src operand in bytes
+ * @returns < zero for failure, 0 for the query func, number of processed bytes
+ * for encryption/decryption funcs
+ */
+static inline int
+crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
+{
+ register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register void* __param asm("1") = param;
+ register u8* __dest asm("4") = dest;
+ register const u8* __src asm("2") = src;
+ register long __src_len asm("3") = src_len;
+ int ret;
+
+ ret = 0;
+ __asm__ __volatile__ (
+ "0: .insn rre,0xB92F0000,%1,%2 \n" //KMC opcode
+ "1: brc 1,0b \n" //handle partial completion
+ __crypt_z990_set_result
+ "6: \n"
+ __crypt_z990_fixup
+ : "+d" (ret), "+a" (__dest), "+a" (__src),
+ [result] "+d" (__src_len)
+ : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
+ "a" (__param)
+ : "cc", "memory"
+ );
+ if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ ret = src_len - ret;
+ }
+ return ret;
+}
+
+/*
+ * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
+ * of the z990 CPU.
+ * @param func: the function code passed to KM; see crypt_z990_kimd_func
+ * @param param: address of parameter block; see POP for details on each func
+ * @param src: address of source memory area
+ * @param src_len: length of src operand in bytes
+ * @returns < zero for failure, 0 for the query func, number of processed bytes
+ * for digest funcs
+ */
+static inline int
+crypt_z990_kimd(long func, void* param, const u8* src, long src_len)
+{
+ register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register void* __param asm("1") = param;
+ register const u8* __src asm("2") = src;
+ register long __src_len asm("3") = src_len;
+ int ret;
+
+ ret = 0;
+ __asm__ __volatile__ (
+ "0: .insn rre,0xB93E0000,%1,%1 \n" //KIMD opcode
+ "1: brc 1,0b \n" /*handle partical completion of kimd*/
+ __crypt_z990_set_result
+ "6: \n"
+ __crypt_z990_fixup
+ : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
+ : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
+ "a" (__param)
+ : "cc", "memory"
+ );
+ if (ret >= 0 && (func & CRYPT_Z990_FUNC_MASK)){
+ ret = src_len - ret;
+ }
+ return ret;
+}
+
+/*
+ * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the z990 CPU.
+ * @param func: the function code passed to KM; see crypt_z990_klmd_func
+ * @param param: address of parameter block; see POP for details on each func
+ * @param src: address of source memory area
+ * @param src_len: length of src operand in bytes
+ * @returns < zero for failure, 0 for the query func, number of processed bytes
+ * for digest funcs
+ */
+static inline int
+crypt_z990_klmd(long func, void* param, const u8* src, long src_len)
+{
+ register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register void* __param asm("1") = param;
+ register const u8* __src asm("2") = src;
+ register long __src_len asm("3") = src_len;
+ int ret;
+
+ ret = 0;
+ __asm__ __volatile__ (
+ "0: .insn rre,0xB93F0000,%1,%1 \n" //KLMD opcode
+ "1: brc 1,0b \n" /*handle partical completion of klmd*/
+ __crypt_z990_set_result
+ "6: \n"
+ __crypt_z990_fixup
+ : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
+ : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
+ "a" (__param)
+ : "cc", "memory"
+ );
+ if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ ret = src_len - ret;
+ }
+ return ret;
+}
+
+/*
+ * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
+ * of the z990 CPU.
+ * @param func: the function code passed to KM; see crypt_z990_klmd_func
+ * @param param: address of parameter block; see POP for details on each func
+ * @param src: address of source memory area
+ * @param src_len: length of src operand in bytes
+ * @returns < zero for failure, 0 for the query func, number of processed bytes
+ * for digest funcs
+ */
+static inline int
+crypt_z990_kmac(long func, void* param, const u8* src, long src_len)
+{
+ register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register void* __param asm("1") = param;
+ register const u8* __src asm("2") = src;
+ register long __src_len asm("3") = src_len;
+ int ret;
+
+ ret = 0;
+ __asm__ __volatile__ (
+ "0: .insn rre,0xB91E0000,%5,%5 \n" //KMAC opcode
+ "1: brc 1,0b \n" /*handle partical completion of klmd*/
+ __crypt_z990_set_result
+ "6: \n"
+ __crypt_z990_fixup
+ : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
+ : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
+ "a" (__param)
+ : "cc", "memory"
+ );
+ if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ ret = src_len - ret;
+ }
+ return ret;
+}
+
+/**
+ * Tests if a specific z990 crypto function is implemented on the machine.
+ * @param func: the function code of the specific function; 0 if op in general
+ * @return 1 if func available; 0 if func or op in general not available
+ */
+static inline int
+crypt_z990_func_available(int func)
+{
+ int ret;
+
+ struct crypt_z990_query_status status = {
+ .high = 0,
+ .low = 0
+ };
+ switch (func & CRYPT_Z990_OP_MASK){
+ case CRYPT_Z990_KM:
+ ret = crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0);
+ break;
+ case CRYPT_Z990_KMC:
+ ret = crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+ break;
+ case CRYPT_Z990_KIMD:
+ ret = crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0);
+ break;
+ case CRYPT_Z990_KLMD:
+ ret = crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0);
+ break;
+ case CRYPT_Z990_KMAC:
+ ret = crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0);
+ break;
+ default:
+ ret = 0;
+ return ret;
+ }
+ if (ret >= 0){
+ func &= CRYPT_Z990_FUNC_MASK;
+ func &= 0x7f; //mask modifier bit
+ if (func < 64){
+ ret = (status.high >> (64 - func - 1)) & 0x1;
+ } else {
+ ret = (status.low >> (128 - func - 1)) & 0x1;
+ }
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+
+#endif // _CRYPTO_ARCH_S390_CRYPT_Z990_H
diff --git a/arch/s390/crypto/crypt_z990_query.c b/arch/s390/crypto/crypt_z990_query.c
new file mode 100644
index 000000000000..7133983d1384
--- /dev/null
+++ b/arch/s390/crypto/crypt_z990_query.c
@@ -0,0 +1,111 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for z990 cryptographic instructions.
+ * Testing module for querying processor crypto capabilities.
+ *
+ * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/errno.h>
+#include "crypt_z990.h"
+
+static void
+query_available_functions(void)
+{
+ printk(KERN_INFO "#####################\n");
+ //query available KM functions
+ printk(KERN_INFO "KM_QUERY: %d\n",
+ crypt_z990_func_available(KM_QUERY));
+ printk(KERN_INFO "KM_DEA: %d\n",
+ crypt_z990_func_available(KM_DEA_ENCRYPT));
+ printk(KERN_INFO "KM_TDEA_128: %d\n",
+ crypt_z990_func_available(KM_TDEA_128_ENCRYPT));
+ printk(KERN_INFO "KM_TDEA_192: %d\n",
+ crypt_z990_func_available(KM_TDEA_192_ENCRYPT));
+ //query available KMC functions
+ printk(KERN_INFO "KMC_QUERY: %d\n",
+ crypt_z990_func_available(KMC_QUERY));
+ printk(KERN_INFO "KMC_DEA: %d\n",
+ crypt_z990_func_available(KMC_DEA_ENCRYPT));
+ printk(KERN_INFO "KMC_TDEA_128: %d\n",
+ crypt_z990_func_available(KMC_TDEA_128_ENCRYPT));
+ printk(KERN_INFO "KMC_TDEA_192: %d\n",
+ crypt_z990_func_available(KMC_TDEA_192_ENCRYPT));
+ //query available KIMD fucntions
+ printk(KERN_INFO "KIMD_QUERY: %d\n",
+ crypt_z990_func_available(KIMD_QUERY));
+ printk(KERN_INFO "KIMD_SHA_1: %d\n",
+ crypt_z990_func_available(KIMD_SHA_1));
+ //query available KLMD functions
+ printk(KERN_INFO "KLMD_QUERY: %d\n",
+ crypt_z990_func_available(KLMD_QUERY));
+ printk(KERN_INFO "KLMD_SHA_1: %d\n",
+ crypt_z990_func_available(KLMD_SHA_1));
+ //query available KMAC functions
+ printk(KERN_INFO "KMAC_QUERY: %d\n",
+ crypt_z990_func_available(KMAC_QUERY));
+ printk(KERN_INFO "KMAC_DEA: %d\n",
+ crypt_z990_func_available(KMAC_DEA));
+ printk(KERN_INFO "KMAC_TDEA_128: %d\n",
+ crypt_z990_func_available(KMAC_TDEA_128));
+ printk(KERN_INFO "KMAC_TDEA_192: %d\n",
+ crypt_z990_func_available(KMAC_TDEA_192));
+}
+
+static int
+init(void)
+{
+ struct crypt_z990_query_status status = {
+ .high = 0,
+ .low = 0
+ };
+
+ printk(KERN_INFO "crypt_z990: querying available crypto functions\n");
+ crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0);
+ printk(KERN_INFO "KM: %016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+ printk(KERN_INFO "KMC: %016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KIMD: %016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KLMD: %016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KMAC: %016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+
+ query_available_functions();
+ return -1;
+}
+
+static void __exit
+cleanup(void)
+{
+}
+
+module_init(init);
+module_exit(cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/s390/crypto/crypto_des.h b/arch/s390/crypto/crypto_des.h
new file mode 100644
index 000000000000..c964b64111dd
--- /dev/null
+++ b/arch/s390/crypto/crypto_des.h
@@ -0,0 +1,18 @@
+/*
+ * Cryptographic API.
+ *
+ * Function for checking keys for the DES and Tripple DES Encryption
+ * algorithms.
+ *
+ * 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.
+ *
+ */
+#ifndef __CRYPTO_DES_H__
+#define __CRYPTO_DES_H__
+
+extern int crypto_des_check_key(const u8*, unsigned int, u32*);
+
+#endif //__CRYPTO_DES_H__
diff --git a/arch/s390/crypto/des_check_key.c b/arch/s390/crypto/des_check_key.c
new file mode 100644
index 000000000000..e3f5c5f238fe
--- /dev/null
+++ b/arch/s390/crypto/des_check_key.c
@@ -0,0 +1,130 @@
+/*
+ * Cryptographic API.
+ *
+ * Function for checking keys for the DES and Tripple DES Encryption
+ * algorithms.
+ *
+ * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
+ * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
+ * Derived from Cryptoapi and Nettle implementations, adapted for in-place
+ * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL.
+ *
+ * s390 Version:
+ * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *
+ * Derived from "crypto/des.c"
+ * Copyright (c) 1992 Dana L. How.
+ * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
+ * Copyright (c) Gisle Sflensminde <gisle@ii.uib.no>
+ * Copyright (C) 2001 Niels Mvller.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/crypto.h>
+
+#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o))
+
+static const u8 parity[] = {
+ 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8,
+};
+
+/*
+ * RFC2451: Weak key checks SHOULD be performed.
+ */
+int
+crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
+{
+ u32 n, w;
+
+ n = parity[key[0]]; n <<= 4;
+ n |= parity[key[1]]; n <<= 4;
+ n |= parity[key[2]]; n <<= 4;
+ n |= parity[key[3]]; n <<= 4;
+ n |= parity[key[4]]; n <<= 4;
+ n |= parity[key[5]]; n <<= 4;
+ n |= parity[key[6]]; n <<= 4;
+ n |= parity[key[7]];
+ w = 0x88888888L;
+
+ if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
+ && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */
+ if (n < 0x41415151) {
+ if (n < 0x31312121) {
+ if (n < 0x14141515) {
+ /* 01 01 01 01 01 01 01 01 */
+ if (n == 0x11111111) goto weak;
+ /* 01 1F 01 1F 01 0E 01 0E */
+ if (n == 0x13131212) goto weak;
+ } else {
+ /* 01 E0 01 E0 01 F1 01 F1 */
+ if (n == 0x14141515) goto weak;
+ /* 01 FE 01 FE 01 FE 01 FE */
+ if (n == 0x16161616) goto weak;
+ }
+ } else {
+ if (n < 0x34342525) {
+ /* 1F 01 1F 01 0E 01 0E 01 */
+ if (n == 0x31312121) goto weak;
+ /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
+ if (n == 0x33332222) goto weak;
+ } else {
+ /* 1F E0 1F E0 0E F1 0E F1 */
+ if (n == 0x34342525) goto weak;
+ /* 1F FE 1F FE 0E FE 0E FE */
+ if (n == 0x36362626) goto weak;
+ }
+ }
+ } else {
+ if (n < 0x61616161) {
+ if (n < 0x44445555) {
+ /* E0 01 E0 01 F1 01 F1 01 */
+ if (n == 0x41415151) goto weak;
+ /* E0 1F E0 1F F1 0E F1 0E */
+ if (n == 0x43435252) goto weak;
+ } else {
+ /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
+ if (n == 0x44445555) goto weak;
+ /* E0 FE E0 FE F1 FE F1 FE */
+ if (n == 0x46465656) goto weak;
+ }
+ } else {
+ if (n < 0x64646565) {
+ /* FE 01 FE 01 FE 01 FE 01 */
+ if (n == 0x61616161) goto weak;
+ /* FE 1F FE 1F FE 0E FE 0E */
+ if (n == 0x63636262) goto weak;
+ } else {
+ /* FE E0 FE E0 FE F1 FE F1 */
+ if (n == 0x64646565) goto weak;
+ /* FE FE FE FE FE FE FE FE */
+ if (n == 0x66666666) goto weak;
+ }
+ }
+ }
+ }
+ return 0;
+weak:
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(crypto_des_check_key);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Key Check function for DES & DES3 Cipher Algorithms");
diff --git a/arch/s390/crypto/des_z990.c b/arch/s390/crypto/des_z990.c
new file mode 100644
index 000000000000..813cf37b1177
--- /dev/null
+++ b/arch/s390/crypto/des_z990.c
@@ -0,0 +1,284 @@
+/*
+ * Cryptographic API.
+ *
+ * z990 implementation of the DES Cipher Algorithm.
+ *
+ * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+#include "crypt_z990.h"
+#include "crypto_des.h"
+
+#define DES_BLOCK_SIZE 8
+#define DES_KEY_SIZE 8
+
+#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE)
+#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE
+
+#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE)
+#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE
+
+struct crypt_z990_des_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES_KEY_SIZE];
+};
+
+struct crypt_z990_des3_128_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES3_128_KEY_SIZE];
+};
+
+struct crypt_z990_des3_192_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES3_192_KEY_SIZE];
+};
+
+static int
+des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+{
+ struct crypt_z990_des_ctx *dctx;
+ int ret;
+
+ dctx = ctx;
+ //test if key is valid (not a weak key)
+ ret = crypto_des_check_key(key, keylen, flags);
+ if (ret == 0){
+ memcpy(dctx->key, key, keylen);
+ }
+ return ret;
+}
+
+
+static void
+des_encrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE);
+}
+
+static void
+des_decrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE);
+}
+
+static struct crypto_alg des_alg = {
+ .cra_name = "des",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_z990_des_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = DES_KEY_SIZE,
+ .cia_max_keysize = DES_KEY_SIZE,
+ .cia_setkey = des_setkey,
+ .cia_encrypt = des_encrypt,
+ .cia_decrypt = des_decrypt } }
+};
+
+/*
+ * RFC2451:
+ *
+ * For DES-EDE3, there is no known need to reject weak or
+ * complementation keys. Any weakness is obviated by the use of
+ * multiple keys.
+ *
+ * However, if the two independent 64-bit keys are equal,
+ * then the DES3 operation is simply the same as DES.
+ * Implementers MUST reject keys that exhibit this property.
+ *
+ */
+static int
+des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+{
+ int i, ret;
+ struct crypt_z990_des3_128_ctx *dctx;
+ const u8* temp_key = key;
+
+ dctx = ctx;
+ if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
+
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
+ return -EINVAL;
+ }
+ for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) {
+ ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
+ if (ret < 0)
+ return ret;
+ }
+ memcpy(dctx->key, key, keylen);
+ return 0;
+}
+
+static void
+des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des3_128_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src,
+ DES3_128_BLOCK_SIZE);
+}
+
+static void
+des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des3_128_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src,
+ DES3_128_BLOCK_SIZE);
+}
+
+static struct crypto_alg des3_128_alg = {
+ .cra_name = "des3_ede128",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_128_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_z990_des3_128_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = DES3_128_KEY_SIZE,
+ .cia_max_keysize = DES3_128_KEY_SIZE,
+ .cia_setkey = des3_128_setkey,
+ .cia_encrypt = des3_128_encrypt,
+ .cia_decrypt = des3_128_decrypt } }
+};
+
+/*
+ * RFC2451:
+ *
+ * For DES-EDE3, there is no known need to reject weak or
+ * complementation keys. Any weakness is obviated by the use of
+ * multiple keys.
+ *
+ * However, if the first two or last two independent 64-bit keys are
+ * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
+ * same as DES. Implementers MUST reject keys that exhibit this
+ * property.
+ *
+ */
+static int
+des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+{
+ int i, ret;
+ struct crypt_z990_des3_192_ctx *dctx;
+ const u8* temp_key;
+
+ dctx = ctx;
+ temp_key = key;
+ if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
+ memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
+ DES_KEY_SIZE))) {
+
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
+ return -EINVAL;
+ }
+ for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
+ ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
+ if (ret < 0){
+ return ret;
+ }
+ }
+ memcpy(dctx->key, key, keylen);
+ return 0;
+}
+
+static void
+des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des3_192_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
+ DES3_192_BLOCK_SIZE);
+}
+
+static void
+des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_z990_des3_192_ctx *dctx;
+
+ dctx = ctx;
+ crypt_z990_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
+ DES3_192_BLOCK_SIZE);
+}
+
+static struct crypto_alg des3_192_alg = {
+ .cra_name = "des3_ede",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_z990_des3_192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = DES3_192_KEY_SIZE,
+ .cia_max_keysize = DES3_192_KEY_SIZE,
+ .cia_setkey = des3_192_setkey,
+ .cia_encrypt = des3_192_encrypt,
+ .cia_decrypt = des3_192_decrypt } }
+};
+
+
+
+static int
+init(void)
+{
+ int ret;
+
+ if (!crypt_z990_func_available(KM_DEA_ENCRYPT) ||
+ !crypt_z990_func_available(KM_TDEA_128_ENCRYPT) ||
+ !crypt_z990_func_available(KM_TDEA_192_ENCRYPT)){
+ return -ENOSYS;
+ }
+
+ ret = 0;
+ ret |= (crypto_register_alg(&des_alg) == 0)? 0:1;
+ ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2;
+ ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4;
+ if (ret){
+ crypto_unregister_alg(&des3_192_alg);
+ crypto_unregister_alg(&des3_128_alg);
+ crypto_unregister_alg(&des_alg);
+ return -EEXIST;
+ }
+
+ printk(KERN_INFO "crypt_z990: des_z990 loaded.\n");
+ return 0;
+}
+
+static void __exit
+fini(void)
+{
+ crypto_unregister_alg(&des3_192_alg);
+ crypto_unregister_alg(&des3_128_alg);
+ crypto_unregister_alg(&des_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_ALIAS("des");
+MODULE_ALIAS("des3_ede");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
diff --git a/arch/s390/crypto/sha1_z990.c b/arch/s390/crypto/sha1_z990.c
new file mode 100644
index 000000000000..298174ddf5b1
--- /dev/null
+++ b/arch/s390/crypto/sha1_z990.c
@@ -0,0 +1,167 @@
+/*
+ * Cryptographic API.
+ *
+ * z990 implementation of the SHA1 Secure Hash Algorithm.
+ *
+ * Derived from cryptoapi implementation, adapted for in-place
+ * scatterlist interface. Originally based on the public domain
+ * implementation written by Steve Reid.
+ *
+ * s390 Version:
+ * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *
+ * Derived from "crypto/sha1.c"
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+#include <asm/byteorder.h>
+#include "crypt_z990.h"
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA1_BLOCK_SIZE 64
+
+struct crypt_z990_sha1_ctx {
+ u64 count;
+ u32 state[5];
+ u32 buf_len;
+ u8 buffer[2 * SHA1_BLOCK_SIZE];
+};
+
+static void
+sha1_init(void *ctx)
+{
+ static const struct crypt_z990_sha1_ctx initstate = {
+ .state = {
+ 0x67452301,
+ 0xEFCDAB89,
+ 0x98BADCFE,
+ 0x10325476,
+ 0xC3D2E1F0
+ },
+ };
+ memcpy(ctx, &initstate, sizeof(initstate));
+}
+
+static void
+sha1_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct crypt_z990_sha1_ctx *sctx;
+ long imd_len;
+
+ sctx = ctx;
+ sctx->count += len * 8; //message bit length
+
+ //anything in buffer yet? -> must be completed
+ if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) {
+ //complete full block and hash
+ memcpy(sctx->buffer + sctx->buf_len, data,
+ SHA1_BLOCK_SIZE - sctx->buf_len);
+ crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
+ SHA1_BLOCK_SIZE);
+ data += SHA1_BLOCK_SIZE - sctx->buf_len;
+ len -= SHA1_BLOCK_SIZE - sctx->buf_len;
+ sctx->buf_len = 0;
+ }
+
+ //rest of data contains full blocks?
+ imd_len = len & ~0x3ful;
+ if (imd_len){
+ crypt_z990_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
+ data += imd_len;
+ len -= imd_len;
+ }
+ //anything left? store in buffer
+ if (len){
+ memcpy(sctx->buffer + sctx->buf_len , data, len);
+ sctx->buf_len += len;
+ }
+}
+
+
+static void
+pad_message(struct crypt_z990_sha1_ctx* sctx)
+{
+ int index;
+
+ index = sctx->buf_len;
+ sctx->buf_len = (sctx->buf_len < 56)?
+ SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
+ //start pad with 1
+ sctx->buffer[index] = 0x80;
+ //pad with zeros
+ index++;
+ memset(sctx->buffer + index, 0x00, sctx->buf_len - index);
+ //append length
+ memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count,
+ sizeof sctx->count);
+}
+
+/* Add padding and return the message digest. */
+static void
+sha1_final(void* ctx, u8 *out)
+{
+ struct crypt_z990_sha1_ctx *sctx = ctx;
+
+ //must perform manual padding
+ pad_message(sctx);
+ crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
+ //copy digest to out
+ memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
+ /* Wipe context */
+ memset(sctx, 0, sizeof *sctx);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "sha1",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_z990_sha1_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA1_DIGEST_SIZE,
+ .dia_init = sha1_init,
+ .dia_update = sha1_update,
+ .dia_final = sha1_final } }
+};
+
+static int
+init(void)
+{
+ int ret = -ENOSYS;
+
+ if (crypt_z990_func_available(KIMD_SHA_1)){
+ ret = crypto_register_alg(&alg);
+ if (ret == 0){
+ printk(KERN_INFO "crypt_z990: sha1_z990 loaded.\n");
+ }
+ }
+ return ret;
+}
+
+static void __exit
+fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_ALIAS("sha1");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 574c1b2a9d06..8e95f1a00b11 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -18,8 +18,10 @@ CONFIG_STANDALONE=y
#
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
CONFIG_IKCONFIG=y
@@ -31,6 +33,7 @@ CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
#
@@ -231,8 +234,6 @@ CONFIG_IPV6=y
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
@@ -242,7 +243,9 @@ CONFIG_XFRM=y
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -286,6 +289,11 @@ CONFIG_NET_CLS_POLICE=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
CONFIG_BONDING=m
@@ -305,20 +313,16 @@ CONFIG_NET_ETHERNET=y
#
# Ethernet (10000 Mbit)
#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Token Ring devices
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
#
-# Token Ring devices
+# Wireless LAN (non-hamradio)
#
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
+# CONFIG_NET_RADIO is not set
#
# Wan interfaces
@@ -341,23 +345,10 @@ CONFIG_QETH=y
# CONFIG_QETH_IPV6 is not set
# CONFIG_QETH_PERF_STATS is not set
CONFIG_CCWGROUP=y
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# File systems
@@ -397,6 +388,7 @@ CONFIG_FS_MBCACHE=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
@@ -493,9 +485,11 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA1_Z990 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_DES_Z990 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index 0cc8e5be48ba..b68ace7e2e4f 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -33,6 +33,8 @@
#define NUM_ACRS 16
#define TASK31_SIZE (0x80000000UL)
+#undef TASK_SIZE
+#define TASK_SIZE TASK31_SIZE
/* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 566277b9409c..df06185d54c2 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -297,64 +297,46 @@ static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
*/
asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
{
- if(call >> 16) /* hack for backward compatibility */
+ if (call >> 16) /* hack for backward compatibility */
return -EINVAL;
call &= 0xffff;
- if (call <= SEMTIMEDOP)
- switch (call) {
- case SEMTIMEDOP:
- if (third)
- return compat_sys_semtimedop(first,
- compat_ptr(ptr), second,
- compat_ptr(third));
- /* else fall through for normal semop() */
- case SEMOP:
- /* struct sembuf is the same on 32 and 64bit :)) */
- return sys_semtimedop (first, compat_ptr(ptr),
- second, NULL);
- case SEMGET:
- return sys_semget (first, second, third);
- case SEMCTL:
- return compat_sys_semctl (first, second, third,
- compat_ptr(ptr));
- default:
- return -EINVAL;
- };
- if (call <= MSGCTL)
- switch (call) {
- case MSGSND:
- return compat_sys_msgsnd (first, second, third,
- compat_ptr(ptr));
- case MSGRCV:
- return compat_sys_msgrcv (first, second, 0, third,
- 0, compat_ptr(ptr));
- case MSGGET:
- return sys_msgget ((key_t) first, second);
- case MSGCTL:
- return compat_sys_msgctl (first, second,
- compat_ptr(ptr));
- default:
- return -EINVAL;
- }
- if (call <= SHMCTL)
- switch (call) {
- case SHMAT:
- return compat_sys_shmat (first, second, third,
- 0, compat_ptr(ptr));
- case SHMDT:
- return sys_shmdt(compat_ptr(ptr));
- case SHMGET:
- return sys_shmget(first, second, third);
- case SHMCTL:
- return compat_sys_shmctl(first, second,
- compat_ptr(ptr));
- default:
- return -EINVAL;
- }
+ switch (call) {
+ case SEMTIMEDOP:
+ return compat_sys_semtimedop(first, compat_ptr(ptr),
+ second, compat_ptr(third));
+ case SEMOP:
+ /* struct sembuf is the same on 32 and 64bit :)) */
+ return sys_semtimedop(first, compat_ptr(ptr),
+ second, NULL);
+ case SEMGET:
+ return sys_semget(first, second, third);
+ case SEMCTL:
+ return compat_sys_semctl(first, second, third,
+ compat_ptr(ptr));
+ case MSGSND:
+ return compat_sys_msgsnd(first, second, third,
+ compat_ptr(ptr));
+ case MSGRCV:
+ return compat_sys_msgrcv(first, second, 0, third,
+ 0, compat_ptr(ptr));
+ case MSGGET:
+ return sys_msgget((key_t) first, second);
+ case MSGCTL:
+ return compat_sys_msgctl(first, second, compat_ptr(ptr));
+ case SHMAT:
+ return compat_sys_shmat(first, second, third,
+ 0, compat_ptr(ptr));
+ case SHMDT:
+ return sys_shmdt(compat_ptr(ptr));
+ case SHMGET:
+ return sys_shmget(first, second, third);
+ case SHMCTL:
+ return compat_sys_shmctl(first, second, compat_ptr(ptr));
+ }
- return -EINVAL;
+ return -ENOSYS;
}
asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low)
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 043c25b7b8f9..66861b95da68 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1361,7 +1361,7 @@ compat_sys_mq_open_wrapper:
llgtr %r5,%r5 # struct compat_mq_attr *
jg compat_sys_mq_open
- .globl sys_mq_unlink_wrapper
+ .globl sys32_mq_unlink_wrapper
sys32_mq_unlink_wrapper:
llgtr %r2,%r2 # const char *
jg sys_mq_unlink
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 37520c7e71be..d5a9e1cdac09 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -198,7 +198,8 @@ __switch_to_noper:
*/
.global do_call_softirq
do_call_softirq:
- stm %r12,%r15,24(%r15)
+ stnsm 24(%r15),0xfc
+ stm %r12,%r15,28(%r15)
lr %r12,%r15
basr %r13,0
do_call_base:
@@ -211,7 +212,8 @@ do_call_base:
st %r12,0(%r15) # store backchain
l %r1,.Ldo_softirq-do_call_base(%r13)
basr %r14,%r1
- lm %r12,%r15,24(%r12)
+ lm %r12,%r15,28(%r12)
+ ssm 24(%r15)
br %r14
__critical_start:
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 89c52f6b35fe..e94e694d512c 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -186,7 +186,8 @@ __switch_to_noper:
*/
.global do_call_softirq
do_call_softirq:
- stmg %r12,%r15,48(%r15)
+ stnsm 48(%r15),0xfc
+ stmg %r12,%r15,56(%r15)
lgr %r12,%r15
lg %r0,__LC_ASYNC_STACK
slgr %r0,%r15
@@ -196,7 +197,8 @@ do_call_softirq:
0: aghi %r15,-STACK_FRAME_OVERHEAD
stg %r12,0(%r15) # store back chain
brasl %r14,do_softirq
- lmg %r12,%r15,48(%r12)
+ lmg %r12,%r15,56(%r12)
+ ssm 48(%r15)
br %r14
__critical_start:
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 7f0e45e001f0..7ca8a8706cca 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -254,13 +254,13 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
/*
* Reboot, halt and power_off routines for non SMP.
*/
-extern void do_reipl(unsigned long devno);
+extern void reipl(unsigned long devno);
static void do_machine_restart_nonsmp(char * __unused)
{
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0);
else
- do_reipl (0x10000 | S390_lowcore.ipl_device);
+ reipl (0x10000 | S390_lowcore.ipl_device);
}
static void do_machine_halt_nonsmp(void)
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 2ee07a475716..de99f63ec951 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(cpu_online_map);
extern char vmhalt_cmd[];
extern char vmpoff_cmd[];
-extern void do_reipl(unsigned long devno);
+extern void reipl(unsigned long devno);
static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig);
@@ -278,7 +278,7 @@ static void do_machine_restart(void * __unused)
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0);
else
- do_reipl (0x10000 | S390_lowcore.ipl_device);
+ reipl (0x10000 | S390_lowcore.ipl_device);
}
signal_processor(smp_processor_id(), sigp_stop);
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index d778f98a2c7c..016eb6cd48c9 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -105,17 +105,6 @@ void show_trace(struct task_struct *task, unsigned long * stack)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- /*
- * We can't print the backtrace of a running process. It is
- * unreliable at best and can cause kernel oopses.
- */
- if (tsk->state == TASK_RUNNING)
- return;
- show_trace(tsk, (unsigned long *) tsk->thread.ksp);
-}
-
void show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long *stack;
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 5211a375afa8..3e63d8a70ed3 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -705,14 +705,8 @@ void show_task(unsigned long *sp)
show_stack(NULL, sp);
}
-void show_trace_task(struct task_struct *tsk)
-{
- show_task((unsigned long *)tsk->thread.sp);
-}
-
void dump_stack(void)
{
show_stack(NULL, NULL);
}
-
EXPORT_SYMBOL(dump_stack);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 3cf8af39ac95..47d685193ade 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1760,13 +1760,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
#endif
}
-void show_trace_task(struct task_struct *tsk)
-{
- if (tsk)
- show_stack(tsk,
- (unsigned long *) tsk->thread_info->ksp);
-}
-
void dump_stack(void)
{
unsigned long *ksp;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 078dc11132d3..ce108f7d6971 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -42,19 +42,8 @@ void dump_stack(void)
show_trace(&stack);
}
-
EXPORT_SYMBOL(dump_stack);
-void show_trace_task(struct task_struct *tsk)
-{
- unsigned long esp = PT_REGS_SP(&tsk->thread.regs);
-
- /* User space on another CPU? */
- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
- return;
- show_trace((unsigned long *)esp);
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
index 977d75772d81..2fccb4cc7b82 100644
--- a/arch/v850/kernel/process.c
+++ b/arch/v850/kernel/process.c
@@ -234,10 +234,3 @@ unsigned long get_wchan (struct task_struct *p)
return 0;
}
-
-void show_trace_task (struct task_struct *t)
-{
- /* blarg XXX */
- printk ("show_trace_task: KSP = 0x%lx, USP = 0x%lx, UPC = 0x%lx\n",
- t->thread.ksp, KSTK_ESP (t), KSTK_EIP (t));
-}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 5afe235c0474..2efdbaa1ecfa 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -197,16 +197,6 @@ void show_trace(unsigned long *stack)
printk("\n");
}
-void show_trace_task(struct task_struct *tsk)
-{
- unsigned long rsp = tsk->thread.rsp;
-
- /* User space on another CPU? */
- if ((rsp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1))
- return;
- show_trace((unsigned long *)rsp);
-}
-
void show_stack(struct task_struct *tsk, unsigned long * rsp)
{
unsigned long *stack;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 4b0925ea142b..d7c9d552fd8b 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -40,6 +40,12 @@ config CRYPTO_SHA1
help
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+config CRYPTO_SHA1_Z990
+ tristate "SHA1 digest algorithm for IBM zSeries z990"
+ depends on CRYPTO && ARCH_S390
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+
config CRYPTO_SHA256
tristate "SHA256 digest algorithm"
depends on CRYPTO
@@ -67,6 +73,12 @@ config CRYPTO_DES
help
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+config CRYPTO_DES_Z990
+ tristate "DES and Triple DES cipher algorithms for IBM zSeries z990"
+ depends on CRYPTO && ARCH_S390
+ help
+ DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+
config CRYPTO_BLOWFISH
tristate "Blowfish cipher algorithm"
depends on CRYPTO
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f9c506d93c69..37afd96d7009 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -656,7 +656,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
* If we can't read - sorry. If we only can't write - well,
* it's going to be read-only.
*/
- if (!lo_file->f_op->sendfile)
+ if (!file->f_op->sendfile)
goto out_putf;
if (!aops->prepare_write || !aops->commit_write)
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index b1d5dfa351ff..9d2759d8aa92 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -39,6 +39,8 @@
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/completion.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/bug.h>
@@ -132,7 +134,12 @@ struct cdrom_info {
char type[4];
char model[3];
};
-static struct cdrom_info viocd_unitinfo[VIOCD_MAX_CD];
+/*
+ * This needs to be allocated since it is passed to the
+ * Hypervisor and we may be a module.
+ */
+static struct cdrom_info *viocd_unitinfo;
+static dma_addr_t unitinfo_dmaaddr;
struct disk_info {
struct gendisk *viocd_disk;
@@ -141,13 +148,39 @@ struct disk_info {
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
#define DEVICE_NR(di) ((di) - &viocd_diskinfo[0])
-#define VIOCDI viocd_diskinfo[deviceno].viocd_info
static request_queue_t *viocd_queue;
static spinlock_t viocd_reqlock;
#define MAX_CD_REQ 1
+/* procfs support */
+static int proc_viocd_show(struct seq_file *m, void *v)
+{
+ int i;
+
+ for (i = 0; i < viocd_numdev; i++) {
+ seq_printf(m, "viocd device %d is iSeries resource %10.10s"
+ "type %4.4s, model %3.3s\n",
+ i, viocd_unitinfo[i].rsrcname,
+ viocd_unitinfo[i].type,
+ viocd_unitinfo[i].model);
+ }
+ return 0;
+}
+
+static int proc_viocd_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_viocd_show, NULL);
+}
+
+static struct file_operations proc_viocd_operations = {
+ .open = proc_viocd_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int viocd_blk_open(struct inode *inode, struct file *file)
{
struct disk_info *di = inode->i_bdev->bd_disk->private_data;
@@ -184,18 +217,20 @@ struct block_device_operations viocd_fops = {
/* Get info on CD devices from OS/400 */
static void __init get_viocd_info(void)
{
- dma_addr_t dmaaddr;
HvLpEvent_Rc hvrc;
int i;
struct viocd_waitevent we;
- dmaaddr = dma_map_single(iSeries_vio_dev, viocd_unitinfo,
- sizeof(viocd_unitinfo), DMA_FROM_DEVICE);
- if (dmaaddr == (dma_addr_t)-1) {
- printk(VIOCD_KERN_WARNING "error allocating tce\n");
+ viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (viocd_unitinfo == NULL) {
+ printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
return;
}
+ memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
+
init_completion(&we.com);
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -204,29 +239,34 @@ static void __init get_viocd_info(void)
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
viopath_sourceinst(viopath_hostLp),
viopath_targetinst(viopath_hostLp),
- (u64)&we, VIOVERSION << 16, dmaaddr, 0,
- sizeof(viocd_unitinfo), 0);
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
if (hvrc != HvLpEvent_Rc_Good) {
printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
(int)hvrc);
- return;
+ goto error_ret;
}
wait_for_completion(&we.com);
- dma_unmap_single(iSeries_vio_dev, dmaaddr, sizeof(viocd_unitinfo),
- DMA_FROM_DEVICE);
-
if (we.rc) {
const struct vio_error_entry *err =
vio_lookup_rc(viocd_err_table, we.sub_result);
printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
we.rc, we.sub_result, err->msg);
- return;
+ goto error_ret;
}
for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
viocd_numdev++;
+
+ return;
+
+error_ret:
+ dma_free_coherent(iSeries_vio_dev,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ viocd_unitinfo, unitinfo_dmaaddr);
+ viocd_unitinfo = NULL;
}
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
@@ -307,10 +347,6 @@ static int send_request(struct request *req)
}
dmaaddr = sg_dma_address(&sg);
len = sg_dma_len(&sg);
- if (dmaaddr == (dma_addr_t)-1) {
- printk(VIOCD_KERN_WARNING "error allocating tce\n");
- return -1;
- }
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
@@ -534,6 +570,7 @@ static int __init viocd_init(void)
struct gendisk *gendisk;
int deviceno;
int ret = 0;
+ struct proc_dir_entry *e;
if (viopath_hostLp == HvLpIndexInvalid) {
vio_set_hostlp();
@@ -604,7 +641,7 @@ static int __init viocd_init(void)
printk(VIOCD_KERN_WARNING
"Cannot create gendisk for %s!\n",
c->name);
- unregister_cdrom(&VIOCDI);
+ unregister_cdrom(c);
continue;
}
gendisk->major = VIOCD_MAJOR;
@@ -622,6 +659,12 @@ static int __init viocd_init(void)
add_disk(gendisk);
}
+ e = create_proc_entry("iSeries/viocd", S_IFREG|S_IRUGO, NULL);
+ if (e) {
+ e->owner = THIS_MODULE;
+ e->proc_fops = &proc_viocd_operations;
+ }
+
return 0;
out_undo_vio:
@@ -636,6 +679,7 @@ static void __exit viocd_exit(void)
{
int deviceno;
+ remove_proc_entry("iSeries/viocd", NULL);
for (deviceno = 0; deviceno < viocd_numdev; deviceno++) {
struct disk_info *d = &viocd_diskinfo[deviceno];
if (unregister_cdrom(&d->viocd_info) != 0)
@@ -646,7 +690,10 @@ static void __exit viocd_exit(void)
put_disk(d->viocd_disk);
}
blk_cleanup_queue(viocd_queue);
-
+ if (viocd_unitinfo != NULL)
+ dma_free_coherent(iSeries_vio_dev,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ viocd_unitinfo, unitinfo_dmaaddr);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
vio_clearHandler(viomajorsubtype_cdio);
unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index ea48f71926b3..e1ebc70335df 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -1275,6 +1275,9 @@ int i810_dma_mc(struct inode *inode, struct file *filp,
return -EINVAL;
}
+ if (mc.idx >= dma->buf_count || mc.idx < 0)
+ return -EINVAL;
+
i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
mc.last_render );
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 3f2b43fe4ac6..a5915c1e764b 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -47,6 +47,8 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/major.h>
#include <linux/completion.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -56,7 +58,7 @@
#include <asm/iSeries/HvCallEvent.h>
#include <asm/iSeries/HvLpConfig.h>
-#define VIOTAPE_VERSION "1.1"
+#define VIOTAPE_VERSION "1.2"
#define VIOTAPE_MAXREQ 1
#define VIOTAPE_KERN_WARN KERN_WARNING "viotape: "
@@ -269,6 +271,34 @@ static struct op_struct *op_struct_list;
/* forward declaration to resolve interdependence */
static int chg_state(int index, unsigned char new_state, struct file *file);
+/* procfs support */
+static int proc_viotape_show(struct seq_file *m, void *v)
+{
+ int i;
+
+ seq_printf(m, "viotape driver version " VIOTAPE_VERSION "\n");
+ for (i = 0; i < viotape_numdev; i++) {
+ seq_printf(m, "viotape device %d is iSeries resource %10.10s"
+ "type %4.4s, model %3.3s\n",
+ i, viotape_unitinfo[i].rsrcname,
+ viotape_unitinfo[i].type,
+ viotape_unitinfo[i].model);
+ }
+ return 0;
+}
+
+static int proc_viotape_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_viotape_show, NULL);
+}
+
+static struct file_operations proc_viotape_operations = {
+ .open = proc_viotape_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
/* Decode the device minor number into its parts */
void get_dev_info(struct inode *ino, struct viot_devinfo_struct *devi)
{
@@ -912,6 +942,7 @@ int __init viotap_init(void)
int ret;
char tapename[32];
int i;
+ struct proc_dir_entry *e;
op_struct_list = NULL;
if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) {
@@ -988,6 +1019,12 @@ int __init viotap_init(void)
viotape_unitinfo[i].model);
}
+ e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL);
+ if (e) {
+ e->owner = THIS_MODULE;
+ e->proc_fops = &proc_viotape_operations;
+ }
+
return 0;
unreg_class:
@@ -1029,6 +1066,8 @@ static void __exit viotap_exit(void)
{
int i, ret;
+ remove_proc_entry("iSeries/viotape", NULL);
+
for (i = 0; i < viotape_numdev; ++i) {
devfs_remove("iseries/nvt%d", i);
devfs_remove("iseries/vt%d", i);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 5564eb107fdf..7cd60dc50d81 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -143,19 +143,6 @@ config ALIM7101_WDT
Most people will say N.
-config AMD7XX_TCO
- tristate "AMD 766/768 TCO Timer/Watchdog"
- depends on WATCHDOG && X86 && PCI
- help
- This is the driver for the hardware watchdog built in to the
- AMD 766/768 chipsets.
- This watchdog simply watches your kernel to make sure it doesn't
- freeze, and if it does, it reboots your computer after a certain
- amount of time.
-
- You can compile this driver directly into the kernel, or use
- it as a module. The module will be called amd7xx_tco.
-
config SC520_WDT
tristate "AMD Elan SC520 processor Watchdog"
depends on WATCHDOG && X86
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 7ca0de685497..6eb9a783d5a8 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
-obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
diff --git a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c
deleted file mode 100644
index d29b4f2bb18c..000000000000
--- a/drivers/char/watchdog/amd7xx_tco.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * AMD 766/768 TCO Timer Driver
- * (c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
- * All Rights Reserved.
- *
- * Parts from;
- * Hardware driver for the AMD 768 Random Number Generator (RNG)
- * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * The author(s) of this software shall not be held liable for damages
- * of any nature resulting due to the use of this software. This
- * software is provided AS-IS with no warranties.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#define AMDTCO_MODULE_VER "build 20021116"
-#define AMDTCO_MODULE_NAME "amd7xx_tco"
-#define PFX AMDTCO_MODULE_NAME ": "
-
-#define MAX_TIMEOUT 38 /* max of 38 seconds, although the system will only
- * reset itself after the second timeout */
-
-/* pmbase registers */
-#define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */
-#define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */
-#define TCO_TIMEOUT_MASK 0x3f
-#define TCO_STATUS1_REG 0x44
-#define TCO_STATUS2_REG 0x46
-#define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */
-#define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */
-#define TCO_CTRL1_REG 0x48
-#define TCO_HALT (1 << 11)
-#define NO_REBOOT (1 << 10) /* in DevB:3x48 */
-
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
-static int timeout = MAX_TIMEOUT;
-static u32 pmbase; /* PMxx I/O base */
-static struct pci_dev *dev;
-static struct semaphore open_sem;
-static spinlock_t amdtco_lock; /* only for device access */
-static char expect_close;
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int nowayout = 1;
-#else
-static int nowayout = 0;
-#endif
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
-
-static inline u8 seconds_to_ticks(int seconds)
-{
- /* the internal timer is stored as ticks which decrement
- * every 0.6 seconds */
- return (seconds * 10) / 6;
-}
-
-static inline int ticks_to_seconds(u8 ticks)
-{
- return (ticks * 6) / 10;
-}
-
-static inline int amdtco_status(void)
-{
- u16 reg;
- int status = 0;
-
- reg = inb(pmbase+TCO_CTRL1_REG);
- if ((reg & TCO_HALT) == 0)
- status |= WDIOF_KEEPALIVEPING;
-
- reg = inb(pmbase+TCO_STATUS2_REG);
- if (reg & BOOT_STS)
- status |= WDIOF_CARDRESET;
-
- return status;
-}
-
-static inline void amdtco_ping(void)
-{
- outb(1, pmbase+TCO_RELOAD_REG);
-}
-
-static inline int amdtco_gettimeout(void)
-{
- u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
- return ticks_to_seconds(reg);
-}
-
-static inline void amdtco_settimeout(unsigned int timeout)
-{
- u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
- outb(reg, pmbase+TCO_INITVAL_REG);
-}
-
-static inline void amdtco_global_enable(void)
-{
- u16 reg;
-
- spin_lock(&amdtco_lock);
-
- /* clear NO_REBOOT on DevB:3x48 p97 */
- pci_read_config_word(dev, 0x48, &reg);
- reg &= ~NO_REBOOT;
- pci_write_config_word(dev, 0x48, reg);
-
- spin_unlock(&amdtco_lock);
-}
-
-static inline void amdtco_enable(void)
-{
- u16 reg;
-
- spin_lock(&amdtco_lock);
- reg = inw(pmbase+TCO_CTRL1_REG);
- reg &= ~TCO_HALT;
- outw(reg, pmbase+TCO_CTRL1_REG);
- spin_unlock(&amdtco_lock);
-}
-
-static inline void amdtco_disable(void)
-{
- u16 reg;
-
- spin_lock(&amdtco_lock);
- reg = inw(pmbase+TCO_CTRL1_REG);
- reg |= TCO_HALT;
- outw(reg, pmbase+TCO_CTRL1_REG);
- spin_unlock(&amdtco_lock);
-}
-
-static int amdtco_fop_open(struct inode *inode, struct file *file)
-{
- if (down_trylock(&open_sem))
- return -EBUSY;
-
- if (timeout > MAX_TIMEOUT)
- timeout = MAX_TIMEOUT;
-
- amdtco_disable();
- amdtco_settimeout(timeout);
- amdtco_global_enable();
- amdtco_enable();
- amdtco_ping();
- printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
- amdtco_gettimeout(), timeout);
-
- return 0;
-}
-
-
-static int amdtco_fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- int new_timeout;
- int tmp;
-
- static struct watchdog_info ident = {
- .options = WDIOF_SETTIMEOUT | WDIOF_CARDRESET,
- .identity = "AMD 766/768",
- };
-
- switch (cmd) {
- default:
- return -ENOIOCTLCMD;
-
- case WDIOC_GETSUPPORT:
- if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident))
- return -EFAULT;
- return 0;
-
- case WDIOC_GETSTATUS:
- return put_user(amdtco_status(), (int *)arg);
-
- case WDIOC_KEEPALIVE:
- amdtco_ping();
- return 0;
-
- case WDIOC_SETTIMEOUT:
- if (get_user(new_timeout, (int *)arg))
- return -EFAULT;
-
- if (new_timeout < 0)
- return -EINVAL;
-
- if (new_timeout > MAX_TIMEOUT)
- new_timeout = MAX_TIMEOUT;
-
- timeout = new_timeout;
- amdtco_settimeout(timeout);
- /* fall through and return the new timeout */
-
- case WDIOC_GETTIMEOUT:
- return put_user(amdtco_gettimeout(), (int *)arg);
-
- case WDIOC_SETOPTIONS:
- if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
- return -EFAULT;
-
- if (tmp & WDIOS_DISABLECARD)
- amdtco_disable();
-
- if (tmp & WDIOS_ENABLECARD)
- amdtco_enable();
-
- return 0;
- }
-}
-
-
-static int amdtco_fop_release(struct inode *inode, struct file *file)
-{
- if (expect_close == 42) {
- amdtco_disable();
- printk(KERN_INFO PFX "Watchdog disabled\n");
- } else {
- amdtco_ping();
- printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
- }
-
- expect_close = 0;
- up(&open_sem);
- return 0;
-}
-
-
-static ssize_t amdtco_fop_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
- if (len) {
- if (!nowayout) {
- size_t i;
- char c;
- expect_close = 0;
-
- for (i = 0; i != len; i++) {
- if (get_user(c, data + i))
- return -EFAULT;
-
- if (c == 'V')
- expect_close = 42;
- }
- }
- amdtco_ping();
- }
-
- return len;
-}
-
-
-static int amdtco_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
- if (code == SYS_DOWN || code == SYS_HALT)
- amdtco_disable();
-
- return NOTIFY_DONE;
-}
-
-
-static struct notifier_block amdtco_notifier =
-{
- .notifier_call = amdtco_notify_sys,
-};
-
-static struct file_operations amdtco_fops =
-{
- .owner = THIS_MODULE,
- .write = amdtco_fop_write,
- .ioctl = amdtco_fop_ioctl,
- .open = amdtco_fop_open,
- .release = amdtco_fop_release,
-};
-
-static struct miscdevice amdtco_miscdev =
-{
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &amdtco_fops,
-};
-
-static struct pci_device_id amdtco_pci_tbl[] = {
- /* AMD 766 PCI_IDs here */
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443, PCI_ANY_ID, PCI_ANY_ID, },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE (pci, amdtco_pci_tbl);
-
-static int __init amdtco_init(void)
-{
- int ret;
-
- sema_init(&open_sem, 1);
- spin_lock_init(&amdtco_lock);
-
- dev = NULL;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if (pci_match_device (amdtco_pci_tbl, dev) != NULL)
- goto found_one;
- }
-
- return -ENODEV;
-
-found_one:
-
- if ((ret = register_reboot_notifier(&amdtco_notifier))) {
- printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret);
- goto out_clean;
- }
-
- if ((ret = misc_register(&amdtco_miscdev))) {
- printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
- goto out_unreg_reboot;
- }
-
- pci_read_config_dword(dev, 0x58, &pmbase);
- pmbase &= 0x0000FF00;
-
- if (pmbase == 0) {
- printk (KERN_ERR PFX "power management base not set\n");
- ret = -EIO;
- goto out_unreg_misc;
- }
-
- /* ret = 0; */
- printk(banner);
- goto out_clean;
-
-out_unreg_misc:
- misc_deregister(&amdtco_miscdev);
-out_unreg_reboot:
- unregister_reboot_notifier(&amdtco_notifier);
-out_clean:
- return ret;
-}
-
-static void __exit amdtco_exit(void)
-{
- misc_deregister(&amdtco_miscdev);
- unregister_reboot_notifier(&amdtco_notifier);
-}
-
-module_init(amdtco_init);
-module_exit(amdtco_exit);
-
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
-MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d5a18851ae73..2c5afb66639a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -360,8 +360,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
return -EINVAL;
policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
- if (!policy)
- return -ENOMEM;
+ if (!policy) {
+ ret = -ENOMEM;
+ goto nomem_out;
+ }
memset(policy, 0, sizeof(struct cpufreq_policy));
policy->cpu = cpu;
@@ -410,7 +412,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
return 0;
- err_out_unregister:
+err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -418,8 +420,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
kobject_unregister(&policy->kobj);
wait_for_completion(&policy->kobj_unregister);
- err_out:
+err_out:
kfree(policy);
+
+nomem_out:
module_put(cpufreq_driver->owner);
return ret;
}
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 709dddc0d369..99ac1419dc79 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -167,8 +167,8 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
void __user *buffer, size_t *lenp)
{
char buf[16], *p;
- int cpu = (int) ctl->extra1;
- int len, left = *lenp;
+ int cpu = (long) ctl->extra1;
+ unsigned int len, left = *lenp;
if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) {
*lenp = 0;
@@ -205,7 +205,7 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context)
{
- int cpu = (int) table->extra1;
+ int cpu = (long) table->extra1;
if (!cpu_online(cpu))
return -EINVAL;
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 79c9cb80fd0a..ac2246dd7646 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -86,7 +86,7 @@ static struct edd_device *edd_devices[EDDMAXNR];
#define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
struct edd_attribute edd_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.test = _test, \
};
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index a316abaf7400..b3d7a002afba 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1695,6 +1695,7 @@ static int idedisk_cleanup (ide_drive_t *drive)
if (ide_unregister_subdriver(drive))
return 1;
del_gendisk(g);
+ drive->devfs_name[0] = '\0';
g->fops = ide_fops;
return 0;
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 78da95051201..4257350fa4b0 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -48,7 +48,6 @@
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/spinlock.h>
-#include <linux/pci.h>
#include <linux/kmod.h>
#include <linux/pci.h>
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index d2aa9b09ab02..fb7ae0006249 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -362,7 +362,6 @@ void ide_config(dev_link_t *link)
goto failed;
}
- MOD_INC_USE_COUNT;
info->ndev = 1;
sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2));
info->node.major = ide_major[hd];
@@ -408,7 +407,6 @@ void ide_release(dev_link_t *link)
if (link->io.NumPorts2)
request_region(link->io.BasePort2, link->io.NumPorts2,
info->node.dev_name);
- MOD_DEC_USE_COUNT;
}
info->ndev = 0;
link->dev = NULL;
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 234990c08a35..8dc51e2966e4 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -11,8 +11,8 @@
* and VAXstations, but can also be used on any standard RS232 with an
* adaptor).
*
- * DISCLAUNER: This works for _me_. If you break anything by using the
- * information given below, I will _not_ be lieable!
+ * DISCLAIMER: This works for _me_. If you break anything by using the
+ * information given below, I will _not_ be liable!
*
* RJ11 pinout: To DB9: Or DB25:
* 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
@@ -34,23 +34,32 @@
* Additionally, you have to get +12V from somewhere.
* Most easily, you'll get that from a floppy or HDD power connector.
* It's the yellow cable there (black is ground and red is +5V).
+ *
+ * The keyboard and all the commands it understands are documented in
+ * "VCB02 Video Subsystem - Technical Manual", EK-104AA-TM-001. This
+ * document is LK201 specific, but LK401 is mostly compatible. It comes
+ * up in LK201 mode and doesn't report any of the additional keys it
+ * has. These need to be switched on with the LK_CMD_ENABLE_LK401
+ * command. You'll find this document (scanned .pdf file) on MANX,
+ * a search engine specific to DEC documentation. Try
+ * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
*/
/*
* 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
+ * 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
- *
+ *
* Should you need to contact me, the author, you can do so either by
* email or by paper mail:
* Jan-Benedict Glaw, Lilienstraße 16, 33790 Hörste (near Halle/Westf.),
@@ -67,8 +76,7 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
-
-MODULE_AUTHOR ("Jan-Benedict Glaw <jblaw@lug-owl.de>");
+MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION ("LK keyboard driver");
MODULE_LICENSE ("GPL");
@@ -92,6 +100,11 @@ static int ctrlclick_volume = 100; /* % */
module_param (ctrlclick_volume, int, 0);
MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
+static int lk201_compose_is_alt = 0;
+module_param (lk201_compose_is_alt, int, 0);
+MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
+ "will act as an Alt key");
+
#undef LKKBD_DEBUG
@@ -126,8 +139,11 @@ MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
#define LK_CMD_SET_DEFAULTS 0xd3
#define LK_CMD_POWERCYCLE_RESET 0xfd
#define LK_CMD_ENABLE_LK401 0xe9
+#define LK_CMD_REQUEST_ID 0xab
/* Misc responses from keyboard */
+#define LK_STUCK_KEY 0x3d
+#define LK_SELFTEST_FAILED 0x3e
#define LK_ALL_KEYS_UP 0xb3
#define LK_METRONOME 0xb4
#define LK_OUTPUT_ERROR 0xb5
@@ -139,6 +155,7 @@ MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
#define LK_RESPONSE_RESERVED 0xbb
#define LK_NUM_KEYCODES 256
+#define LK_NUM_IGNORE_BYTES 6
typedef u_int16_t lk_keycode_t;
@@ -267,6 +284,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
struct lkkbd {
lk_keycode_t keycode[LK_NUM_KEYCODES];
int ignore_bytes;
+ unsigned char id[LK_NUM_IGNORE_BYTES];
struct input_dev dev;
struct serio *serio;
struct work_struct tq;
@@ -313,6 +331,82 @@ volume_to_hw (int volume_percent)
return ret;
}
+static void
+lkkbd_detection_done (struct lkkbd *lk)
+{
+ int i;
+
+ /*
+ * Reset setting for Compose key. Let Compose be KEY_COMPOSE.
+ */
+ lk->keycode[0xb1] = KEY_COMPOSE;
+
+ /*
+ * Print keyboard name and modify Compose=Alt on user's request.
+ */
+ switch (lk->id[4]) {
+ case 1:
+ sprintf (lk->name, "DEC LK201 keyboard");
+
+ if (lk201_compose_is_alt)
+ lk->keycode[0xb1] = KEY_LEFTALT;
+ break;
+
+ case 2:
+ sprintf (lk->name, "DEC LK401 keyboard");
+ break;
+
+ default:
+ sprintf (lk->name, "Unknown DEC keyboard");
+ printk (KERN_ERR "lkkbd: keyboard on %s is unknown, "
+ "please report to Jan-Benedict Glaw "
+ "<jbglaw@lug-owl.de>\n", lk->phys);
+ printk (KERN_ERR "lkkbd: keyboard ID'ed as:");
+ for (i = 0; i < LK_NUM_IGNORE_BYTES; i++)
+ printk (" 0x%02x", lk->id[i]);
+ printk ("\n");
+ break;
+ }
+ printk (KERN_INFO "lkkbd: keyboard on %s identified as: %s\n",
+ lk->phys, lk->name);
+
+ /*
+ * Report errors during keyboard boot-up.
+ */
+ switch (lk->id[2]) {
+ case 0x00:
+ /* All okay */
+ break;
+
+ case LK_STUCK_KEY:
+ printk (KERN_ERR "lkkbd: Stuck key on keyboard at "
+ "%s\n", lk->phys);
+ break;
+
+ case LK_SELFTEST_FAILED:
+ printk (KERN_ERR "lkkbd: Selftest failed on keyboard "
+ "at %s, keyboard may not work "
+ "properly\n", lk->phys);
+ break;
+
+ default:
+ printk (KERN_ERR "lkkbd: Unknown error %02x on "
+ "keyboard at %s\n", lk->id[2],
+ lk->phys);
+ break;
+ }
+
+ /*
+ * Try to hint user if there's a stuck key.
+ */
+ if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0)
+ printk (KERN_ERR "Scancode of stuck key is 0x%02x, keycode "
+ "is 0x%04x\n", lk->id[3],
+ lk->keycode[lk->id[3]]);
+
+ return;
+}
+
/*
* lkkbd_interrupt() is called by the low level driver when a character
* is received.
@@ -329,7 +423,11 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
if (lk->ignore_bytes > 0) {
DBG (KERN_INFO "Ignoring a byte on %s\n",
lk->name);
- lk->ignore_bytes--;
+ lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
+
+ if (lk->ignore_bytes == 0)
+ lkkbd_detection_done (lk);
+
return IRQ_HANDLED;
}
@@ -375,7 +473,8 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
break;
case 0x01:
DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n");
- lk->ignore_bytes = 3;
+ lk->ignore_bytes = LK_NUM_IGNORE_BYTES;
+ lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
schedule_work (&lk->tq);
break;
@@ -389,7 +488,7 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
input_sync (&lk->dev);
} else
printk (KERN_WARNING "%s: Unknown key with "
- "scancode %02x on %s.\n",
+ "scancode 0x%02x on %s.\n",
__FILE__, data, lk->name);
}
@@ -467,6 +566,9 @@ lkkbd_reinit (void *data)
unsigned char leds_on = 0;
unsigned char leds_off = 0;
+ /* Ask for ID */
+ lk->serio->write (lk->serio, LK_CMD_REQUEST_ID);
+
/* Reset parameters */
lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS);
@@ -527,9 +629,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
- if (!(serio->type & SERIO_PROTO))
- return;
- if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_LKKBD)
+ if ((serio->type & SERIO_PROTO) != SERIO_LKKBD)
return;
if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
@@ -537,10 +637,16 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
memset (lk, 0, sizeof (struct lkkbd));
init_input_dev (&lk->dev);
-
- lk->dev.evbit[0] = BIT (EV_KEY) | BIT (EV_LED) | BIT (EV_SND) | BIT (EV_REP);
- lk->dev.ledbit[0] = BIT (LED_CAPSL) | BIT (LED_COMPOSE) | BIT (LED_SCROLLL) | BIT (LED_SLEEP);
- lk->dev.sndbit[0] = BIT (SND_CLICK) | BIT (SND_BELL);
+ set_bit (EV_KEY, lk->dev.evbit);
+ set_bit (EV_LED, lk->dev.evbit);
+ set_bit (EV_SND, lk->dev.evbit);
+ set_bit (EV_REP, lk->dev.evbit);
+ set_bit (LED_CAPSL, lk->dev.ledbit);
+ set_bit (LED_SLEEP, lk->dev.ledbit);
+ set_bit (LED_COMPOSE, lk->dev.ledbit);
+ set_bit (LED_SCROLLL, lk->dev.ledbit);
+ set_bit (SND_BELL, lk->dev.sndbit);
+ set_bit (SND_CLICK, lk->dev.sndbit);
lk->serio = serio;
@@ -564,14 +670,13 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
return;
}
- sprintf (lk->name, "LK keyboard");
+ sprintf (lk->name, "DEC LK keyboard");
+ sprintf (lk->phys, "%s/input0", serio->phys);
memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
for (i = 0; i < LK_NUM_KEYCODES; i++)
set_bit (lk->keycode[i], lk->dev.keybit);
- sprintf (lk->name, "%s/input0", serio->phys);
-
lk->dev.name = lk->name;
lk->dev.phys = lk->phys;
lk->dev.id.bustype = BUS_RS232;
@@ -599,9 +704,9 @@ lkkbd_disconnect (struct serio *serio)
}
static struct serio_dev lkkbd_dev = {
- .interrupt = lkkbd_interrupt,
.connect = lkkbd_connect,
.disconnect = lkkbd_disconnect,
+ .interrupt = lkkbd_interrupt,
};
/*
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 13086cec9f49..17db090dc6f6 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -119,7 +119,7 @@ config MOUSE_RISCPC
module will be called rpcmouse.
config MOUSE_VSXXXAA
- tristate "DEC VSXXX-AA/GA mouse and tablet"
+ tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet"
depends on INPUT && INPUT_MOUSE
select SERIO
help
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index bcc0d3ae219f..c26d907e8bb9 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -11,14 +11,14 @@
/*
* 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
+ * 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
@@ -45,32 +45,32 @@
*
* DEC socket DB9 DB25 Note
* 1 (GND) 5 7 -
- * 2 (RxD) 3 3 -
- * 3 (TxD) 2 2 -
+ * 2 (RxD) 2 3 -
+ * 3 (TxD) 3 2 -
* 4 (-12V) - - Somewhere from the PSU. At ATX, it's
- * the blue wire at pin 12 of the ATX
- * power connector. Please note that the
- * docs say this should be +12V! However,
- * I measured -12V...
- * 5 (+5V) - - PSU (red wire of ATX power connector
+ * the thin blue wire at pin 12 of the
+ * ATX power connector. Only required for
+ * VSXXX-AA/-GA mice.
+ * 5 (+5V) - - PSU (red wires of ATX power connector
* on pin 4, 6, 19 or 20) or HDD power
- * connector (also red wire)
- * 6 (not conn.) - - -
+ * connector (also red wire).
+ * 6 (+12V) - - HDD power connector, yellow wire. Only
+ * required for VSXXX-AB digitizer.
* 7 (dev. avail.) - - The mouse shorts this one to pin 1.
* This way, the host computer can detect
* the mouse. To use it with the adaptor,
* simply don't connect this pin.
*
* So to get a working adaptor, you need to connect the mouse with three
- * wires to a RS232 port and two additional wires for +5V and -12V to the
- * PSU.
+ * wires to a RS232 port and two or three additional wires for +5V, +12V and
+ * -12V to the PSU.
*
* Flow specification for the link is 4800, 8o1.
- */
-
-/*
- * TODO list:
- * - Automatically attach to a given serial port (no need for inputattach).
+ *
+ * The mice and tablet are described in "VCB02 Video Subsystem - Technical
+ * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine
+ * specific for DEC documentation. Try
+ * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
*/
#include <linux/delay.h>
@@ -115,6 +115,7 @@ struct vsxxxaa {
unsigned char version;
unsigned char country;
unsigned char type;
+ char name[64];
char phys[32];
};
@@ -134,27 +135,34 @@ vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte)
{
if (mouse->count == BUFLEN) {
printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
- mouse->dev.name, mouse->dev.phys);
+ mouse->name, mouse->phys);
vsxxxaa_drop_bytes (mouse, 1);
}
+ DBG (KERN_INFO "Queueing byte 0x%02x\n", byte);
mouse->buf[mouse->count++] = byte;
}
static void
-vsxxxaa_report_mouse (struct vsxxxaa *mouse)
+vsxxxaa_detection_done (struct vsxxxaa *mouse)
{
- char *devtype;
-
switch (mouse->type) {
- case 0x02: devtype = "DEC mouse"; break;
- case 0x04: devtype = "DEC tablet"; break;
- default: devtype = "unknown DEC device"; break;
+ case 0x02:
+ sprintf (mouse->name, "DEC VSXXX-AA/GA mouse");
+ break;
+
+ case 0x04:
+ sprintf (mouse->name, "DEC VSXXX-AB digitizer");
+ break;
+
+ default:
+ sprintf (mouse->name, "unknown DEC pointer device");
+ break;
}
- printk (KERN_INFO "Found %s version 0x%x from country 0x%x "
- "on port %s\n", devtype, mouse->version,
- mouse->country, mouse->dev.phys);
+ printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x "
+ "on port %s\n", mouse->name, mouse->version,
+ mouse->country, mouse->phys);
}
/*
@@ -216,7 +224,7 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
* 0, bit 4 of byte 0 is direction.
*/
dx = buf[1] & 0x7f;
- dx *= ((buf[0] >> 4) & 0x01)? -1: 1;
+ dx *= ((buf[0] >> 4) & 0x01)? 1: -1;
/*
* Low 7 bit of byte 2 are abs(dy), bit 7 is
@@ -236,7 +244,7 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
vsxxxaa_drop_bytes (mouse, 3);
DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
- mouse->dev.name, mouse->dev.phys, dx, dy,
+ mouse->name, mouse->phys, dx, dy,
left? "L": "l", middle? "M": "m", right? "R": "r");
/*
@@ -246,6 +254,7 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
input_report_key (dev, BTN_LEFT, left);
input_report_key (dev, BTN_MIDDLE, middle);
input_report_key (dev, BTN_RIGHT, right);
+ input_report_key (dev, BTN_TOUCH, 0);
input_report_rel (dev, REL_X, dx);
input_report_rel (dev, REL_Y, dy);
input_sync (dev);
@@ -256,7 +265,7 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
struct input_dev *dev = &mouse->dev;
unsigned char *buf = mouse->buf;
- int left, middle, right, extra;
+ int left, middle, right, touch;
int x, y;
/*
@@ -270,10 +279,12 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
*/
/*
- * Get X/Y position
+ * Get X/Y position. Y axis needs to be inverted since VSXXX-AB
+ * counts down->top while monitor counts top->bottom.
*/
x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
+ y = 1023 - y;
/*
* Get button state. It's bits <4..1> of byte 0.
@@ -281,14 +292,14 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
left = (buf[0] & 0x02)? 1: 0;
middle = (buf[0] & 0x04)? 1: 0;
right = (buf[0] & 0x08)? 1: 0;
- extra = (buf[0] & 0x10)? 1: 0;
+ touch = (buf[0] & 0x10)? 1: 0;
vsxxxaa_drop_bytes (mouse, 5);
DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
- mouse->dev.name, mouse->dev.phys, x, y,
+ mouse->name, mouse->phys, x, y,
left? "L": "l", middle? "M": "m",
- right? "R": "r", extra? "E": "e");
+ right? "R": "r", touch? "T": "t");
/*
* Report what we've found so far...
@@ -297,7 +308,7 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
input_report_key (dev, BTN_LEFT, left);
input_report_key (dev, BTN_MIDDLE, middle);
input_report_key (dev, BTN_RIGHT, right);
- input_report_key (dev, BTN_EXTRA, extra);
+ input_report_key (dev, BTN_TOUCH, touch);
input_report_abs (dev, ABS_X, x);
input_report_abs (dev, ABS_Y, y);
input_sync (dev);
@@ -334,7 +345,7 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
mouse->version = buf[0] & 0x0f;
mouse->country = (buf[1] >> 4) & 0x07;
- mouse->type = buf[1] & 0x07;
+ mouse->type = buf[1] & 0x0f;
error = buf[2] & 0x7f;
/*
@@ -347,7 +358,7 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
right = (buf[0] & 0x01)? 1: 0;
vsxxxaa_drop_bytes (mouse, 4);
- vsxxxaa_report_mouse (mouse);
+ vsxxxaa_detection_done (mouse);
if (error <= 0x1f) {
/* No error. Report buttons */
@@ -355,20 +366,22 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
input_report_key (dev, BTN_LEFT, left);
input_report_key (dev, BTN_MIDDLE, middle);
input_report_key (dev, BTN_RIGHT, right);
+ input_report_key (dev, BTN_TOUCH, 0);
input_sync (dev);
} else {
printk (KERN_ERR "Your %s on %s reports an undefined error, "
- "please check it...\n", mouse->dev.name,
- mouse->dev.phys);
+ "please check it...\n", mouse->name,
+ mouse->phys);
}
/*
- * If the mouse was hot-plugged, we need to
- * force differential mode now...
+ * If the mouse was hot-plugged, we need to force differential mode
+ * now... However, give it a second to recover from it's reset.
*/
printk (KERN_NOTICE "%s on %s: Forceing standard packet format and "
- "streaming mode\n", mouse->dev.name, mouse->dev.phys);
+ "streaming mode\n", mouse->name, mouse->phys);
mouse->serio->write (mouse->serio, 'S');
+ mdelay (50);
mouse->serio->write (mouse->serio, 'R');
}
@@ -392,7 +405,7 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
printk (KERN_ERR "%s on %s: Dropping a byte to regain "
"sync with mouse data stream...\n",
- mouse->dev.name, mouse->dev.phys);
+ mouse->name, mouse->phys);
vsxxxaa_drop_bytes (mouse, 1);
}
@@ -475,7 +488,6 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
-
if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
return;
@@ -486,14 +498,15 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
init_input_dev (&mouse->dev);
set_bit (EV_KEY, mouse->dev.evbit); /* We have buttons */
- set_bit (EV_REL, mouse->dev.evbit); /* We can move */
+ set_bit (EV_REL, mouse->dev.evbit);
+ set_bit (EV_ABS, mouse->dev.evbit);
set_bit (BTN_LEFT, mouse->dev.keybit); /* We have 3 buttons */
set_bit (BTN_MIDDLE, mouse->dev.keybit);
set_bit (BTN_RIGHT, mouse->dev.keybit);
- set_bit (BTN_EXTRA, mouse->dev.keybit); /* ...and Tablet */
- set_bit (REL_X, mouse->dev.relbit); /* We can move in */
- set_bit (REL_Y, mouse->dev.relbit); /* two dimensions */
- set_bit (ABS_X, mouse->dev.absbit); /* DEC tablet support */
+ set_bit (BTN_TOUCH, mouse->dev.keybit); /* ...and Tablet */
+ set_bit (REL_X, mouse->dev.relbit);
+ set_bit (REL_Y, mouse->dev.relbit);
+ set_bit (ABS_X, mouse->dev.absbit);
set_bit (ABS_Y, mouse->dev.absbit);
mouse->dev.absmin[ABS_X] = 0;
@@ -504,9 +517,10 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
mouse->dev.private = mouse;
serio->private = mouse;
+ sprintf (mouse->name, "DEC VSXXX-AA/GA mouse or VSXXX-AB digitizer");
sprintf (mouse->phys, "%s/input0", serio->phys);
+ mouse->dev.name = mouse->name;
mouse->dev.phys = mouse->phys;
- mouse->dev.name = "DEC VSXXX-AA/GA mouse or DEC tablet";
mouse->dev.id.bustype = BUS_RS232;
mouse->serio = serio;
@@ -516,20 +530,20 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
}
/*
- * Request selftest and differential stream mode.
+ * Request selftest. Standard packet format and differential
+ * mode will be requested after the device ID'ed successfully.
*/
mouse->serio->write (mouse->serio, 'T'); /* Test */
- mouse->serio->write (mouse->serio, 'R'); /* Differential stream */
input_register_device (&mouse->dev);
- printk (KERN_INFO "input: %s on %s\n", mouse->dev.name, serio->phys);
+ printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
}
static struct serio_dev vsxxxaa_dev = {
- .interrupt = vsxxxaa_interrupt,
- .connect = vsxxxaa_connect,
- .disconnect = vsxxxaa_disconnect
+ .connect = vsxxxaa_connect,
+ .interrupt = vsxxxaa_interrupt,
+ .disconnect = vsxxxaa_disconnect,
};
int __init
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 10a54ddd2540..cacd1f20ea5f 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -130,3 +130,13 @@ config SERIO_PCIPS2
To compile this driver as a module, choose M here: the
module will be called pcips2.
+
+config SERIO_MACEPS2
+ tristate "SGI O2 MACE PS/2 controller"
+ depends on SGI_IP32 && SERIO
+ help
+ Say Y here if you have SGI O2 workstation and want to use its
+ PS/2 ports.
+
+ To compile this driver as a module, choose M here: the
+ module will be called maceps2.
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 2eb86eba6ed9..a47dec2556e8 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
+obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 6b434f8b62f1..9b36485fc605 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -69,7 +69,7 @@ static inline int i8042_platform_init(void)
* On ix86 platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on ix86 boxes.
*/
-#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__)
+#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
return -1;
#endif
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
new file mode 100644
index 000000000000..863b9c95fbb8
--- /dev/null
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -0,0 +1,76 @@
+#ifndef _I8042_IP22_H
+#define _I8042_IP22_H
+
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/ip22.h>
+
+/*
+ * 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.
+ */
+
+/*
+ * Names.
+ */
+
+#define I8042_KBD_PHYS_DESC "hpc3ps2/serio0"
+#define I8042_AUX_PHYS_DESC "hpc3ps2/serio1"
+#define I8042_MUX_PHYS_DESC "hpc3ps2/serio%d"
+
+/*
+ * IRQs.
+ */
+
+#define I8042_KBD_IRQ SGI_KEYBD_IRQ
+#define I8042_AUX_IRQ SGI_KEYBD_IRQ
+
+/*
+ * Register numbers.
+ */
+
+#define I8042_COMMAND_REG ((unsigned long)&sgioc->kbdmouse.command)
+#define I8042_STATUS_REG ((unsigned long)&sgioc->kbdmouse.command)
+#define I8042_DATA_REG ((unsigned long)&sgioc->kbdmouse.data)
+
+static inline int i8042_read_data(void)
+{
+ return sgioc->kbdmouse.data;
+}
+
+static inline int i8042_read_status(void)
+{
+ return sgioc->kbdmouse.command;
+}
+
+static inline void i8042_write_data(int val)
+{
+ sgioc->kbdmouse.data = val;
+}
+
+static inline void i8042_write_command(int val)
+{
+ sgioc->kbdmouse.command = val;
+}
+
+static inline int i8042_platform_init(void)
+{
+#if 0
+ /* XXX sgi_kh is a virtual address */
+ if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
+ return 1;
+#endif
+
+ i8042_reset = 1;
+
+ return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+#if 0
+ release_mem_region(JAZZ_KEYBOARD_ADDRESS, sizeof(struct hpc_keyb));
+#endif
+}
+
+#endif /* _I8042_IP22_H */
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
new file mode 100644
index 000000000000..5c20ab131488
--- /dev/null
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -0,0 +1,69 @@
+#ifndef _I8042_JAZZ_H
+#define _I8042_JAZZ_H
+
+#include <asm/jazz.h>
+
+/*
+ * 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.
+ */
+
+/*
+ * Names.
+ */
+
+#define I8042_KBD_PHYS_DESC "R4030/serio0"
+#define I8042_AUX_PHYS_DESC "R4030/serio1"
+#define I8042_MUX_PHYS_DESC "R4030/serio%d"
+
+/*
+ * IRQs.
+ */
+
+#define I8042_KBD_IRQ JAZZ_KEYBOARD_IRQ
+#define I8042_AUX_IRQ JAZZ_MOUSE_IRQ
+
+#define I8042_COMMAND_REG ((unsigned long)&jazz_kh->command)
+#define I8042_STATUS_REG ((unsigned long)&jazz_kh->command)
+#define I8042_DATA_REG ((unsigned long)&jazz_kh->data)
+
+static inline int i8042_read_data(void)
+{
+ return jazz_kh->data;
+}
+
+static inline int i8042_read_status(void)
+{
+ return jazz_kh->command;
+}
+
+static inline void i8042_write_data(int val)
+{
+ jazz_kh->data = val;
+}
+
+static inline void i8042_write_command(int val)
+{
+ jazz_kh->command = val;
+}
+
+static inline int i8042_platform_init(void)
+{
+#if 0
+ /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
+ if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
+ return 1;
+#endif
+
+ return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+#if 0
+ release_mem_region(JAZZ_KEYBOARD_ADDRESS, 2);
+#endif
+}
+
+#endif /* _I8042_JAZZ_H */
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index 3d59eb2e05a7..f0f637483233 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -1,6 +1,8 @@
#ifndef _I8042_H
#define _I8042_H
+#include <linux/config.h>
+
/*
* Copyright (c) 1999-2002 Vojtech Pavlik
*
@@ -13,7 +15,11 @@
* Arch-dependent inline functions and defines.
*/
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_MIPS_JAZZ)
+#include "i8042-jazzio.h"
+#elif defined(CONFIG_SGI_IP22)
+#include "i8042-ip22io.h"
+#elif defined(CONFIG_PPC)
#include "i8042-ppcio.h"
#elif defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
#include "i8042-sparcio.h"
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
new file mode 100644
index 000000000000..c7db1de49cfc
--- /dev/null
+++ b/drivers/input/serio/maceps2.c
@@ -0,0 +1,160 @@
+/*
+ * SGI O2 MACE PS2 controller driver for linux
+ *
+ * Copyright (C) 2002 Vivien Chappelier
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org");
+MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver");
+MODULE_LICENSE("GPL");
+
+#define MACE_PS2_TIMEOUT 10000 /* in 50us unit */
+
+#define PS2_STATUS_CLOCK_SIGNAL BIT(0) /* external clock signal */
+#define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */
+#define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */
+#define PS2_STATUS_TX_EMPTY BIT(3) /* empty transmit buffer */
+#define PS2_STATUS_RX_FULL BIT(4) /* full receive buffer */
+#define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */
+#define PS2_STATUS_ERROR_PARITY BIT(6) /* parity error */
+#define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */
+
+#define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */
+#define PS2_CONTROL_TX_ENABLE BIT(1) /* transmit enable */
+#define PS2_CONTROL_TX_INT_ENABLE BIT(2) /* enable transmit interrupt */
+#define PS2_CONTROL_RX_INT_ENABLE BIT(3) /* enable receive interrupt */
+#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */
+#define PS2_CONTROL_RESET BIT(5) /* reset */
+
+
+struct maceps2_data {
+ struct mace_ps2port *port;
+ int irq;
+};
+
+static int maceps2_write(struct serio *dev, unsigned char val)
+{
+ struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+ unsigned int timeout = MACE_PS2_TIMEOUT;
+
+ do {
+ if (mace_read(port->status) & PS2_STATUS_TX_EMPTY) {
+ mace_write(val, port->tx);
+ return 0;
+ }
+ udelay(50);
+ } while (timeout--);
+
+ return -1;
+}
+
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct serio *dev = dev_id;
+ struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+ unsigned int byte;
+
+ if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
+ byte = mace_read(port->rx);
+ serio_interrupt(dev, byte & 0xff, 0, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int maceps2_open(struct serio *dev)
+{
+ struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+
+ if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
+ printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
+ return -EBUSY;
+ }
+
+ /* Reset port */
+ mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
+ data->port->control);
+ udelay(100);
+
+ /* Enable interrupts */
+ mace_write(PS2_CONTROL_RX_CLOCK_ENABLE | PS2_CONTROL_TX_ENABLE |
+ PS2_CONTROL_RX_INT_ENABLE, data->port->control);
+
+ return 0;
+}
+
+static void maceps2_close(struct serio *dev)
+{
+ struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+
+ mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
+ data->port->control);
+ udelay(100);
+ free_irq(data->irq, dev);
+}
+
+static struct maceps2_data port0_data, port1_data;
+
+static struct serio maceps2_port0 =
+{
+ .type = SERIO_8042,
+ .open = maceps2_open,
+ .close = maceps2_close,
+ .write = maceps2_write,
+ .name = "MACE PS/2 port0",
+ .phys = "mace/serio0",
+ .driver = &port0_data,
+};
+
+static struct serio maceps2_port1 =
+{
+ .type = SERIO_8042,
+ .open = maceps2_open,
+ .close = maceps2_close,
+ .write = maceps2_write,
+ .name = "MACE PS/2 port1",
+ .phys = "mace/serio1",
+ .driver = &port1_data,
+};
+
+static int __init maceps2_init(void)
+{
+ port0_data.port = &mace->perif.ps2.keyb;
+ port0_data.irq = MACEISA_KEYB_IRQ;
+ port1_data.port = &mace->perif.ps2.mouse;
+ port1_data.irq = MACEISA_MOUSE_IRQ;
+ serio_register_port(&maceps2_port0);
+ serio_register_port(&maceps2_port1);
+
+ return 0;
+}
+
+static void __exit maceps2_exit(void)
+{
+ serio_unregister_port(&maceps2_port0);
+ serio_unregister_port(&maceps2_port1);
+}
+
+module_init(maceps2_init);
+module_exit(maceps2_exit);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 0270a5659727..bdfcbe09d4d5 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -12,6 +12,7 @@
#include <linux/moduleparam.h>
#include <linux/blkpg.h>
#include <linux/bio.h>
+#include <linux/buffer_head.h>
#include <linux/mempool.h>
#include <linux/slab.h>
@@ -46,6 +47,7 @@ struct target_io {
*/
#define DMF_BLOCK_IO 0
#define DMF_SUSPENDED 1
+#define DMF_FS_LOCKED 2
struct mapped_device {
struct rw_semaphore lock;
@@ -80,6 +82,11 @@ struct mapped_device {
*/
uint32_t event_nr;
wait_queue_head_t eventq;
+
+ /*
+ * freeze/thaw support require holding onto a super block
+ */
+ struct super_block *frozen_sb;
};
#define MIN_IOS 256
@@ -885,6 +892,52 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table)
}
/*
+ * Functions to lock and unlock any filesystem running on the
+ * device.
+ */
+static int __lock_fs(struct mapped_device *md)
+{
+ struct block_device *bdev;
+
+ if (test_and_set_bit(DMF_FS_LOCKED, &md->flags))
+ return 0;
+
+ bdev = bdget_disk(md->disk, 0);
+ if (!bdev) {
+ DMWARN("bdget failed in __lock_fs");
+ return -ENOMEM;
+ }
+
+ WARN_ON(md->frozen_sb);
+ md->frozen_sb = freeze_bdev(bdev);
+ /* don't bdput right now, we don't want the bdev
+ * to go away while it is locked. We'll bdput
+ * in __unlock_fs
+ */
+ return 0;
+}
+
+static int __unlock_fs(struct mapped_device *md)
+{
+ struct block_device *bdev;
+
+ if (!test_and_clear_bit(DMF_FS_LOCKED, &md->flags))
+ return 0;
+
+ bdev = bdget_disk(md->disk, 0);
+ if (!bdev) {
+ DMWARN("bdget failed in __unlock_fs");
+ return -ENOMEM;
+ }
+
+ thaw_bdev(bdev, md->frozen_sb);
+ md->frozen_sb = NULL;
+ bdput(bdev);
+ bdput(bdev);
+ return 0;
+}
+
+/*
* We need to be able to change a mapping table under a mounted
* filesystem. For example we might want to move some data in
* the background. Before the table can be swapped with
@@ -896,13 +949,27 @@ int dm_suspend(struct mapped_device *md)
struct dm_table *map;
DECLARE_WAITQUEUE(wait, current);
- down_write(&md->lock);
+ /* Flush I/O to the device. */
+ down_read(&md->lock);
+ if (test_bit(DMF_BLOCK_IO, &md->flags)) {
+ up_read(&md->lock);
+ return -EINVAL;
+ }
+
+ __lock_fs(md);
+ up_read(&md->lock);
/*
* First we set the BLOCK_IO flag so no more ios will be
* mapped.
*/
+ down_write(&md->lock);
if (test_bit(DMF_BLOCK_IO, &md->flags)) {
+ /*
+ * If we get here we know another thread is
+ * trying to suspend as well, so we leave the fs
+ * locked for this thread.
+ */
up_write(&md->lock);
return -EINVAL;
}
@@ -937,6 +1004,7 @@ int dm_suspend(struct mapped_device *md)
/* were we interrupted ? */
if (atomic_read(&md->pending)) {
+ __unlock_fs(md);
clear_bit(DMF_BLOCK_IO, &md->flags);
up_write(&md->lock);
return -EINTR;
@@ -974,6 +1042,7 @@ int dm_resume(struct mapped_device *md)
def = bio_list_get(&md->deferred);
__flush_deferred_io(md, def);
up_write(&md->lock);
+ __unlock_fs(md);
dm_table_unplug_all(map);
dm_table_put(map);
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 4850af52dcec..97fd269a90ee 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -61,7 +61,6 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -78,10 +77,11 @@
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iommu.h>
+#include <asm/vio.h>
#include "iseries_veth.h"
-extern struct pci_dev *iSeries_veth_dev;
+extern struct vio_dev *iSeries_veth_dev;
MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>");
MODULE_DESCRIPTION("iSeries Virtual ethernet driver");
@@ -895,10 +895,10 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
}
dma_length = skb->len;
- dma_address = pci_map_single(iSeries_veth_dev, skb->data,
- dma_length, PCI_DMA_TODEVICE);
+ dma_address = vio_map_single(iSeries_veth_dev, skb->data,
+ dma_length, DMA_TO_DEVICE);
- if (pci_dma_mapping_error(dma_address))
+ if (dma_mapping_error(dma_address))
goto recycle_and_drop;
/* Is it really necessary to check the length and address
@@ -1016,8 +1016,8 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx,
dma_address = msg->data.addr[0];
dma_length = msg->data.len[0];
- pci_unmap_single(iSeries_veth_dev, dma_address, dma_length,
- PCI_DMA_TODEVICE);
+ vio_unmap_single(iSeries_veth_dev, dma_address, dma_length,
+ DMA_TO_DEVICE);
if (msg->skb) {
dev_kfree_skb_any(msg->skb);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 87fa182a06b3..260b12b34779 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -24,8 +24,7 @@ obj-$(CONFIG_PARISC) += setup-bus.o
obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_PPC64) += setup-bus.o
-obj-$(CONFIG_SGI_IP27) += setup-irq.o
-obj-$(CONFIG_SGI_IP32) += setup-irq.o
+obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_PCI_USE_VECTOR) += msi.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d0ab034fa0c1..ab9f28443436 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.136 $
+ * $Revision: 1.139 $
*/
#include <linux/config.h>
@@ -74,6 +74,8 @@ dasd_alloc_device(void)
if (device == NULL)
return ERR_PTR(-ENOMEM);
memset(device, 0, sizeof (struct dasd_device));
+ /* open_count = 0 means device online but not in use */
+ atomic_set(&device->open_count, -1);
/* Get two pages for normal block device operations. */
device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1);
@@ -549,6 +551,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize,
}
strncpy((char *) &cqr->magic, magic, 4);
ASCEBC((char *) &cqr->magic, 4);
+ set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
dasd_get_device(device);
return cqr;
}
@@ -597,6 +600,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
}
strncpy((char *) &cqr->magic, magic, 4);
ASCEBC((char *) &cqr->magic, 4);
+ set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
dasd_get_device(device);
return cqr;
}
@@ -688,9 +692,10 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
rc = ccw_device_clear(device->cdev, (long) cqr);
switch (rc) {
case 0: /* termination successful */
- if (cqr->retries > 0)
+ if (cqr->retries > 0) {
+ cqr->retries--;
cqr->status = DASD_CQR_QUEUED;
- else
+ } else
cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock();
break;
@@ -982,6 +987,8 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
irb->scsw.cstat == 0 &&
!irb->esw.esw0.erw.cons)
era = dasd_era_none;
+ else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags))
+ era = dasd_era_fatal; /* don't recover this request */
else if (irb->esw.esw0.erw.cons)
era = device->discipline->examine_error(cqr, irb);
else
@@ -1875,7 +1882,7 @@ dasd_generic_set_offline (struct ccw_device *cdev)
* the blkdev_get in dasd_scan_partitions. We are only interested
* in the other openers.
*/
- max_count = device->bdev ? 1 : 0;
+ max_count = device->bdev ? 0 : -1;
if (atomic_read(&device->open_count) > max_count) {
printk (KERN_WARNING "Can't offline dasd device with open"
" count = %i.\n",
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c6b26e729aaa..e90c1c93e19a 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -5,7 +5,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
*
- * $Revision: 1.28 $
+ * $Revision: 1.30 $
*/
#include <linux/timer.h>
@@ -1763,6 +1763,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
erp->magic = default_erp->magic;
erp->expires = 0;
erp->retries = 256;
+ cqr->buildclk = get_clock();
erp->status = DASD_CQR_FILLED;
/* remove the default erp */
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 1490f1e4a4ec..e7afb426b539 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.53 $
+ * $Revision: 1.54 $
*/
#include <linux/config.h>
@@ -1130,6 +1130,7 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
cqr->cpaddr->count = 32;
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1173,6 +1174,7 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
cqr->cpaddr->count = 32;
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1215,6 +1217,7 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
cqr->cpaddr->count = 32;
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 70ccb1110d07..9967c082c0ad 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.56 $
+ * $Revision: 1.57 $
*/
#ifndef DASD_INT_H
@@ -159,6 +159,7 @@ struct dasd_ccw_req {
struct ccw1 *cpaddr; /* address of channel program */
char status; /* status of this request */
short retries; /* A retry counter */
+ unsigned long flags; /* flags of this request */
/* ... and how */
unsigned long starttime; /* jiffies time of request start */
@@ -192,6 +193,9 @@ struct dasd_ccw_req {
#define DASD_CQR_ERROR 0x04 /* request is completed with error */
#define DASD_CQR_FAILED 0x05 /* request is finally failed */
+/* per dasd_ccw_req flags */
+#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
+
/* Signature for error recovery functions. */
typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index ef0f996fa798..ecba07756cbb 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -381,6 +381,8 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
return; /* Sucessfully restarted. */
break;
case RAW3270_IO_STOP:
+ if (!rq)
+ break;
raw3270_halt_io_nolock(rp, rq);
rq->rc = -EIO;
break;
@@ -881,7 +883,7 @@ raw3270_activate_view(struct raw3270_view *view)
if (rc) {
/* Didn't work. Try to reactivate the old view. */
rp->view = oldview;
- if (oldview->fn->activate(oldview) != 0) {
+ if (!oldview || oldview->fn->activate(oldview) != 0) {
/* Didn't work as well. Try any other view. */
list_for_each_entry(nv, &rp->view_list, list)
if (nv != view && nv != oldview) {
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cffeda66520e..ccdf053b3dfd 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.117 $
+ * $Revision: 1.121 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -783,3 +783,68 @@ cio_get_console_subchannel(void)
}
#endif
+static inline int
+__disable_subchannel_easy(unsigned int schid, struct schib *schib)
+{
+ int retry, cc;
+
+ cc = 0;
+ for (retry=0;retry<3;retry++) {
+ schib->pmcw.ena = 0;
+ cc = msch(schid, schib);
+ if (cc)
+ return (cc==3?-ENODEV:-EBUSY);
+ stsch(schid, schib);
+ if (!schib->pmcw.ena)
+ return 0;
+ }
+ return -EBUSY; /* uhm... */
+}
+
+static inline int
+__clear_subchannel_easy(unsigned int schid)
+{
+ int retry;
+
+ if (csch(schid))
+ return -ENODEV;
+ for (retry=0;retry<20;retry++) {
+ struct tpi_info ti;
+
+ if (tpi(&ti)) {
+ tsch(schid, (struct irb *)__LC_IRB);
+ return 0;
+ }
+ udelay(100);
+ }
+ return -EBUSY;
+}
+
+extern void do_reipl(unsigned long devno);
+/* Make sure all subchannels are quiet before we re-ipl an lpar. */
+void
+reipl(unsigned long devno)
+{
+ unsigned int schid;
+
+ local_irq_disable();
+ for (schid=0;schid<=highest_subchannel;schid++) {
+ struct schib schib;
+ if (stsch(schid, &schib))
+ goto out;
+ if (!schib.pmcw.ena)
+ continue;
+ switch(__disable_subchannel_easy(schid, &schib)) {
+ case 0:
+ case -ENODEV:
+ break;
+ default: /* -EBUSY */
+ if (__clear_subchannel_easy(schid))
+ break; /* give up... */
+ stsch(schid, &schib);
+ __disable_subchannel_easy(schid, &schib);
+ }
+ }
+out:
+ do_reipl(devno);
+}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index eac048a1991c..763056eede77 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -440,12 +440,14 @@ ccw_device_nopath_notify(void *data)
if (!ret) {
if (get_device(&sch->dev)) {
/* Driver doesn't want to keep device. */
+ cio_disable_subchannel(sch);
device_unregister(&sch->dev);
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
put_device(&sch->dev);
}
} else {
+ cio_disable_subchannel(sch);
ccw_device_set_timeout(cdev, 0);
cdev->private->state = DEV_STATE_DISCONNECTED;
wake_up(&cdev->private->wait_q);
@@ -787,6 +789,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
+ ccw_device_set_timeout(cdev, 0);
/* OK, i/o is dead now. Call interrupt handler. */
cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler)
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 3188cde89326..f4c9779d2d4a 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.79 $"
+#define VERSION_QDIO_C "$Revision: 1.80 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -461,12 +461,12 @@ check_next:
switch(slsb[f_mod_no]) {
- /* the hydra has not fetched the output yet */
+ /* the adapter has not fetched the output yet */
case SLSB_CU_OUTPUT_PRIMED:
QDIO_DBF_TEXT5(0,trace,"outpprim");
break;
- /* the hydra got it */
+ /* the adapter got it */
case SLSB_P_OUTPUT_EMPTY:
atomic_dec(&q->number_of_buffers_used);
f++;
@@ -919,7 +919,7 @@ qdio_is_inbound_q_done(struct qdio_q *q)
no_used=atomic_read(&q->number_of_buffers_used);
/*
- * we need that one for synchronization with Hydra, as Hydra
+ * we need that one for synchronization with the adapter, as it
* does a kind of PCI avoidance
*/
SYNC_MEMORY;
@@ -1069,7 +1069,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
}
/*
* maybe we have to do work on our outbound queues... at least
- * we have to check Hydra outbound-int-capable thinint-capable
+ * we have to check the outbound-int-capable thinint-capable
* queues
*/
if (q->hydra_gives_outbound_pcis) {
@@ -2027,7 +2027,7 @@ tiqdio_check_chsc_availability(void)
goto exit;
}
- /* Check for hydra thin interrupts (bit 67). */
+ /* Check for OSA/FCP thin interrupts (bit 67). */
hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
== 0x10000000);
sprintf(dbf_text,"hydrati%1x", hydra_thinints);
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 601453f1a6b9..5771fb36360f 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: iucv.c,v 1.27 2004/03/22 07:43:43 braunu Exp $
+ * $Id: iucv.c,v 1.28 2004/04/15 06:34:58 braunu Exp $
*
* IUCV network driver
*
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.27 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.28 $
*
*/
@@ -351,7 +351,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.27 $";
+ char vbuf[] = "$Revision: 1.28 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
@@ -800,6 +800,7 @@ iucv_register_program (__u8 pgmname[16],
if (iucv_pathid_table == NULL) {
printk(KERN_WARNING "%s: iucv_pathid_table storage "
"allocation failed\n", __FUNCTION__);
+ kfree(new_handler);
return NULL;
}
memset (iucv_pathid_table, 0, max_connections * sizeof(handler *));
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index fb30461252ab..a65ef7677beb 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: netiucv.c,v 1.48 2004/04/01 13:42:09 braunu Exp $
+ * $Id: netiucv.c,v 1.49 2004/04/15 06:37:54 braunu Exp $
*
* IUCV network driver
*
@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.48 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.49 $
*
*/
@@ -601,11 +601,12 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
if ((skb = skb_dequeue(&conn->commit_queue))) {
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
- }
- if (privptr) {
- privptr->stats.tx_packets++;
- privptr->stats.tx_bytes +=
- (skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN);
+ if (privptr) {
+ privptr->stats.tx_packets++;
+ privptr->stats.tx_bytes +=
+ (skb->len - NETIUCV_HDRLEN
+ - NETIUCV_HDRLEN);
+ }
}
}
conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head;
@@ -1078,6 +1079,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
"%s: Could not allocate tx_skb\n",
conn->netdev->name);
rc = -ENOMEM;
+ return rc;
} else {
skb_reserve(nskb, NETIUCV_HDRLEN);
memcpy(skb_put(nskb, skb->len),
@@ -1880,7 +1882,7 @@ static struct device_driver netiucv_driver = {
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.48 $";
+ char vbuf[] = "$Revision: 1.49 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 1175c1e8deac..74b167b0f29a 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -23,7 +23,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.98 $"
+#define VERSION_QETH_H "$Revision: 1.100 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -423,14 +423,12 @@ struct qeth_qdio_out_q {
struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
int queue_no;
struct qeth_card *card;
- struct tasklet_struct tasklet;
spinlock_t lock;
volatile int do_pack;
/*
* index of buffer to be filled by driver; state EMPTY or PACKING
*/
volatile int next_buf_to_fill;
- volatile int next_buf_to_flush;
/*
* number of buffers that are currently filled (PRIMED)
* -> these buffers are hardware-owned
@@ -447,7 +445,6 @@ struct qeth_qdio_info {
struct qeth_qdio_buffer_pool in_buf_pool;
struct qeth_qdio_buffer_pool init_pool;
int in_buf_size;
- struct tasklet_struct in_tasklet;
/* output */
int no_out_queues;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 414d9c3de0d5..4ee0592f21d0 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.77 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.82 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.77 $ $Date: 2004/04/06 14:38:19 $
+ * $Revision: 1.82 $ $Date: 2004/04/21 08:27:21 $
*
* 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
@@ -78,7 +78,7 @@ qeth_eyecatcher(void)
#include "qeth_mpc.h"
#include "qeth_fs.h"
-#define VERSION_QETH_C "$Revision: 1.77 $"
+#define VERSION_QETH_C "$Revision: 1.82 $"
static const char *version = "qeth S/390 OSA-Express driver ("
VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
@@ -486,6 +486,7 @@ qeth_remove_device(struct ccwgroup_device *cgdev)
list_del(&card->list);
write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
unregister_netdev(card->dev);
+ qeth_remove_device_attributes(&cgdev->dev);
qeth_free_card(card);
cgdev->dev.driver_data = NULL;
put_device(&cgdev->dev);
@@ -822,7 +823,7 @@ qeth_register_mc_addresses(void *ptr)
struct qeth_card *card;
card = (struct qeth_card *) ptr;
- daemonize("getmcaddr");
+ daemonize("qeth_reg_mcaddrs");
QETH_DBF_TEXT(trace,4,"regmcth1");
if (!qeth_do_run_thread(card, QETH_SET_MC_THREAD))
return 0;
@@ -843,7 +844,7 @@ qeth_register_ip_address(void *ptr)
struct qeth_card *card;
card = (struct qeth_card *) ptr;
- daemonize("regip");
+ daemonize("qeth_reg_ip");
QETH_DBF_TEXT(trace,4,"regipth1");
if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))
return 0;
@@ -860,7 +861,7 @@ qeth_recover(void *ptr)
int rc = 0;
card = (struct qeth_card *) ptr;
- daemonize("recover");
+ daemonize("qeth_recover");
QETH_DBF_TEXT(trace,2,"recover1");
QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
@@ -1969,45 +1970,6 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
return rc;
}
-static void
-qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
- unsigned int qdio_err, unsigned int siga_err,
- unsigned int queue, int first_element, int count,
- unsigned long card_ptr)
-{
- struct net_device *net_dev;
- struct qeth_card *card;
- struct qeth_qdio_buffer *buffer;
- int i;
-
- QETH_DBF_TEXT(trace, 6, "qdinput");
- card = (struct qeth_card *) card_ptr;
- net_dev = card->dev;
-#ifdef CONFIG_QETH_PERF_STATS
- card->perf_stats.inbound_start_time = qeth_get_micros();
-#endif
- if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
- QETH_DBF_TEXT(trace, 1,"qdinchk");
- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
- QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
- QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
- qeth_schedule_recovery(card);
- return;
- }
- }
- for (i = first_element; i < (first_element + count); ++i) {
- buffer = &card->qdio.in_q->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
- if ((status == QDIO_STATUS_LOOK_FOR_ERROR) &&
- qeth_check_for_inbound_error(buffer, qdio_err, siga_err))
- buffer->state = QETH_QDIO_BUF_ERROR;
- else
- buffer->state = QETH_QDIO_BUF_PRIMED;
- }
-
- tasklet_schedule(&card->qdio.in_tasklet);
-}
-
static inline struct sk_buff *
qeth_get_skb(unsigned int length)
{
@@ -2127,7 +2089,6 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
return htons(ETH_P_802_2);
}
-
static inline void
qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
@@ -2193,7 +2154,6 @@ qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
#endif /* CONFIG_QETH_VLAN */
}
-
static inline void
qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
@@ -2241,6 +2201,38 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
qeth_rebuild_skb_vlan(card, skb, hdr);
}
+static inline void
+qeth_process_inbound_buffer(struct qeth_card *card,
+ struct qeth_qdio_buffer *buf, int index)
+{
+ struct qdio_buffer_element *element;
+ int offset;
+ struct sk_buff *skb;
+ struct qeth_hdr *hdr;
+ int rxrc;
+
+ /* get first element of current buffer */
+ element = (struct qdio_buffer_element *)&buf->buffer->element[0];
+ offset = 0;
+#ifdef CONFIG_QETH_PERF_STATS
+ card->perf_stats.bufs_rec++;
+#endif
+ while((skb = qeth_get_next_skb(card, buf->buffer, &element,
+ &offset, &hdr))){
+ qeth_rebuild_skb(card, skb, hdr);
+
+#ifdef CONFIG_QETH_PERF_STATS
+ card->perf_stats.inbound_time += qeth_get_micros() -
+ card->perf_stats.inbound_start_time;
+ card->perf_stats.inbound_cnt++;
+#endif
+ skb->dev = card->dev;
+ rxrc = netif_rx(skb);
+ card->dev->last_rx = jiffies;
+ card->stats.rx_packets++;
+ card->stats.rx_bytes += skb->len;
+ }
+}
static inline struct qeth_buffer_pool_entry *
qeth_get_buffer_pool_entry(struct qeth_card *card)
@@ -2284,7 +2276,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
buf->state = QETH_QDIO_BUF_EMPTY;
}
-static void
+static inline void
qeth_clear_output_buffer(struct qeth_card *card,
struct qeth_qdio_out_buffer *buf)
{
@@ -2355,61 +2347,43 @@ qeth_put_buffer_pool_entry(struct qeth_card *card,
}
static void
-qeth_qdio_input_tasklet(unsigned long data)
+qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
+ unsigned int qdio_err, unsigned int siga_err,
+ unsigned int queue, int first_element, int count,
+ unsigned long card_ptr)
{
- struct qeth_card *card = (struct qeth_card *) data;
- int current_buf = card->qdio.in_q->next_buf_to_process;
- struct qeth_qdio_buffer *buf;
- struct qdio_buffer_element *element;
- int offset;
- struct sk_buff *skb;
- struct qeth_hdr *hdr;
- int rxrc;
-
- QETH_DBF_TEXT(trace,6,"qdintlet");
- buf = &card->qdio.in_q->bufs[current_buf];
- while((buf->state == QETH_QDIO_BUF_PRIMED) ||
- (buf->state == QETH_QDIO_BUF_ERROR)){
- if (buf->state == QETH_QDIO_BUF_ERROR)
- goto clear_buffer;
- if (netif_queue_stopped(card->dev))
- goto clear_buffer;
- /* get first element of current buffer */
- element = (struct qdio_buffer_element *)
- &buf->buffer->element[0];
- offset = 0;
-#ifdef CONFIG_QETH_PERF_STATS
- card->perf_stats.bufs_rec++;
-#endif
- while((skb = qeth_get_next_skb(card, buf->buffer, &element,
- &offset, &hdr))){
+ struct net_device *net_dev;
+ struct qeth_card *card;
+ struct qeth_qdio_buffer *buffer;
+ int index;
+ int i;
- qeth_rebuild_skb(card, skb, hdr);
+ QETH_DBF_TEXT(trace, 6, "qdinput");
+ card = (struct qeth_card *) card_ptr;
+ net_dev = card->dev;
#ifdef CONFIG_QETH_PERF_STATS
- card->perf_stats.inbound_time += qeth_get_micros() -
- card->perf_stats.inbound_start_time;
- card->perf_stats.inbound_cnt++;
+ card->perf_stats.inbound_start_time = qeth_get_micros();
#endif
- skb->dev = card->dev;
- if (netif_queue_stopped(card->dev)) {
- dev_kfree_skb_irq(skb);
- card->stats.rx_dropped++;
- } else {
- rxrc = netif_rx(skb);
- card->dev->last_rx = jiffies;
- card->stats.rx_packets++;
- card->stats.rx_bytes += skb->len;
- }
+ if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+ if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+ QETH_DBF_TEXT(trace, 1,"qdinchk");
+ QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+ QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
+ QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
+ qeth_schedule_recovery(card);
+ return;
}
-clear_buffer:
- qeth_put_buffer_pool_entry(card, buf->pool_entry);
- /* give buffer back to hardware */
- qeth_queue_input_buffer(card, current_buf);
- current_buf = (current_buf + 1) % QDIO_MAX_BUFFERS_PER_Q;
- buf = &card->qdio.in_q->bufs[current_buf];
}
- /* set index for next time the tasklet is scheduled */
- card->qdio.in_q->next_buf_to_process = current_buf;
+ for (i = first_element; i < (first_element + count); ++i) {
+ index = i % QDIO_MAX_BUFFERS_PER_Q;
+ buffer = &card->qdio.in_q->bufs[index];
+ if (!((status == QDIO_STATUS_LOOK_FOR_ERROR) &&
+ qeth_check_for_inbound_error(buffer, qdio_err, siga_err)))
+ qeth_process_inbound_buffer(card, buffer, index);
+ /* clear buffer and give back to hardware */
+ qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+ qeth_queue_input_buffer(card, index);
+ }
}
static inline int
@@ -2524,10 +2498,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
* switches between PACKING and non-PACKING state if needed.
* has to be called holding queue->lock
*/
-static inline void
+static inline int
qeth_switch_packing_state(struct qeth_qdio_out_q *queue)
{
struct qeth_qdio_out_buffer *buffer;
+ int flush_count = 0;
QETH_DBF_TEXT(trace, 6, "swipack");
if (!queue->do_pack) {
@@ -2554,6 +2529,7 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue)
BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
if (buffer->next_element_to_fill > 0) {
buffer->state = QETH_QDIO_BUF_PRIMED;
+ flush_count++;
atomic_inc(&queue->used_buffers);
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
@@ -2561,6 +2537,25 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue)
}
}
}
+ return flush_count;
+}
+
+static inline void
+qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue, int under_int)
+{
+ struct qeth_qdio_out_buffer *buffer;
+
+ buffer = &queue->bufs[queue->next_buf_to_fill];
+ BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
+ if (buffer->next_element_to_fill > 0){
+ /* it's a packing buffer */
+ buffer->state = QETH_QDIO_BUF_PRIMED;
+ atomic_inc(&queue->used_buffers);
+ qeth_flush_buffers(queue, under_int, queue->next_buf_to_fill,
+ 1);
+ queue->next_buf_to_fill =
+ (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+ }
}
static void
@@ -2603,58 +2598,12 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
atomic_dec(&queue->set_pci_flags_count);
qeth_clear_output_buffer(card, buffer);
+ atomic_dec(&queue->used_buffers);
}
- atomic_sub(count, &queue->used_buffers);
-
- //if (!atomic_read(&queue->set_pci_flags_count))
- tasklet_schedule(&queue->tasklet);
netif_wake_queue(card->dev);
}
-static void
-qeth_qdio_output_tasklet(unsigned long data)
-{
- struct qeth_qdio_out_q *queue = (struct qeth_qdio_out_q *) data;
- struct qeth_qdio_out_buffer *buffer;
- int index;
- int count;
-
- QETH_DBF_TEXT(trace, 6, "outtlet");
-
- /* flush all PRIMED buffers */
- index = queue->next_buf_to_flush;
- count = 0;
- while (queue->bufs[index].state == QETH_QDIO_BUF_PRIMED) {
- count++;
- index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
- }
- qeth_flush_buffers(queue, 0, queue->next_buf_to_flush, count);
- queue->next_buf_to_flush = index;
-
- /* flush a buffer with data, if no more PCIs are
- * outstanding */
- if (!atomic_read(&queue->set_pci_flags_count)){
- spin_lock(&queue->lock);
- buffer = &queue->bufs[index];
- if (buffer->state == QETH_QDIO_BUF_PRIMED){
- qeth_flush_buffers(queue, 0, index, 1);
- index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
- queue->next_buf_to_flush = index;
- } else if (buffer->next_element_to_fill > 0){
- /* it's a packing buffer */
- BUG_ON(index != queue->next_buf_to_fill);
- buffer->state = QETH_QDIO_BUF_PRIMED;
- atomic_inc(&queue->used_buffers);
- qeth_flush_buffers(queue, 0, index, 1);
- index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
- queue->next_buf_to_flush = index;
- queue->next_buf_to_fill = index;
- }
- spin_unlock(&queue->lock);
- }
-}
-
static char*
qeth_create_qib_param_field(struct qeth_card *card)
{
@@ -2858,8 +2807,6 @@ qeth_init_qdio_info(struct qeth_card *card)
card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
- card->qdio.in_tasklet.data = (unsigned long) card;
- card->qdio.in_tasklet.func = qeth_qdio_input_tasklet;
/* outbound */
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
@@ -2903,13 +2850,9 @@ qeth_init_qdio_queues(struct qeth_card *card)
}
card->qdio.out_qs[i]->card = card;
card->qdio.out_qs[i]->next_buf_to_fill = 0;
- card->qdio.out_qs[i]->next_buf_to_flush = 0;
card->qdio.out_qs[i]->do_pack = 0;
atomic_set(&card->qdio.out_qs[i]->used_buffers,0);
atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
- card->qdio.out_qs[i]->tasklet.data =
- (unsigned long) card->qdio.out_qs[i];
- card->qdio.out_qs[i]->tasklet.func = qeth_qdio_output_tasklet;
spin_lock_init(&card->qdio.out_qs[i]->lock);
}
return 0;
@@ -3653,6 +3596,8 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr;
struct qeth_qdio_out_buffer *buffer;
int elements_needed;
+ int start_index;
+ int flush_count = 0;
int rc;
QETH_DBF_TEXT(trace, 6, "dosndpkt");
@@ -3671,9 +3616,7 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
}
spin_lock(&queue->lock);
- /* check if we need to switch packing state of this queue */
- if (card->info.type != QETH_CARD_TYPE_IQD)
- qeth_switch_packing_state(queue);
+ start_index = queue->next_buf_to_fill;
buffer = &queue->bufs[queue->next_buf_to_fill];
BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
if (queue->do_pack){
@@ -3682,6 +3625,7 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
< elements_needed){
/* ... no -> set state PRIMED */
buffer->state = QETH_QDIO_BUF_PRIMED;
+ flush_count++;
atomic_inc(&queue->used_buffers);
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
@@ -3695,18 +3639,24 @@ qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
PRINT_WARN("qeth_do_send_packet: error during "
"qeth_fill_buffer.");
card->stats.tx_dropped++;
- spin_unlock(&queue->lock);
- return rc;
- }
- if (buffer->state == QETH_QDIO_BUF_PRIMED){
+ } else if (buffer->state == QETH_QDIO_BUF_PRIMED){
/* next time fill the next buffer */
+ flush_count++;
atomic_inc(&queue->used_buffers);
queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
QDIO_MAX_BUFFERS_PER_Q;
}
- spin_unlock(&queue->lock);
+ /* check if we need to switch packing state of this queue */
+ if (card->info.type != QETH_CARD_TYPE_IQD)
+ flush_count += qeth_switch_packing_state(queue);
+
+ if (flush_count)
+ qeth_flush_buffers(queue, 0, start_index, flush_count);
- tasklet_schedule(&queue->tasklet);
+ if (!atomic_read(&queue->set_pci_flags_count))
+ qeth_flush_buffers_on_no_pci(queue, 0);
+
+ spin_unlock(&queue->lock);
return rc;
}
@@ -4424,6 +4374,10 @@ qeth_delete_mc_addresses(struct qeth_card *card)
if (!ipm->is_multicast)
continue;
iptodo = qeth_get_addr_buffer(ipm->proto);
+ if (!iptodo) {
+ QETH_DBF_TEXT(trace, 2, "dmcnomem");
+ continue;
+ }
memcpy(iptodo, ipm, sizeof(struct qeth_ipaddr));
iptodo->users = iptodo->users * -1;
if (!__qeth_insert_ip_todo(card, iptodo, 0))
@@ -4694,14 +4648,14 @@ qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
if (addr->proto == QETH_PROT_IPV4) {
QETH_DBF_TEXT(trace, 2,"setaddr4");
- QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, sizeof(int));
+ QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
} else if (addr->proto == QETH_PROT_IPV6) {
QETH_DBF_TEXT(trace, 2, "setaddr6");
- QETH_DBF_HEX(trace,4,&addr->u.a6.addr,4);
- QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+4,4);
+ QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+ QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
} else {
QETH_DBF_TEXT(trace, 2, "setaddr?");
- QETH_DBF_HEX(trace, 4, addr, sizeof(struct qeth_ipaddr));
+ QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
}
do {
if (addr->is_multicast)
@@ -4732,14 +4686,14 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
if (addr->proto == QETH_PROT_IPV4) {
QETH_DBF_TEXT(trace, 2,"deladdr4");
- QETH_DBF_HEX(trace, 2, &addr->u.a4.addr, sizeof(int));
+ QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
} else if (addr->proto == QETH_PROT_IPV6) {
QETH_DBF_TEXT(trace, 2, "deladdr6");
- QETH_DBF_HEX(trace, 2, &addr->u.a6.addr,
- sizeof(struct in6_addr));
+ QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+ QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
} else {
QETH_DBF_TEXT(trace, 2, "deladdr?");
- QETH_DBF_HEX(trace, 2, addr, sizeof(struct qeth_ipaddr));
+ QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
}
if (addr->is_multicast)
rc = qeth_send_setdelmc(card, addr, IPA_CMD_DELIPM);
@@ -6515,26 +6469,24 @@ qeth_ip_event(struct notifier_block *this,
addr->u.a4.addr = ifa->ifa_address;
addr->u.a4.mask = ifa->ifa_mask;
addr->type = QETH_IP_TYPE_NORMAL;
- }
+ } else
+ goto out;
+
switch(event) {
case NETDEV_UP:
- if (addr) {
- if (!qeth_add_ip(card, addr))
- kfree(addr);
- }
+ if (!qeth_add_ip(card, addr))
+ kfree(addr);
break;
case NETDEV_DOWN:
- if (addr) {
- if (!qeth_delete_ip(card, addr))
- kfree(addr);
- }
+ if (!qeth_delete_ip(card, addr))
+ kfree(addr);
break;
default:
break;
}
qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD);
schedule_work(&card->kernel_thread_starter);
-
+out:
return NOTIFY_DONE;
}
@@ -6570,26 +6522,24 @@ qeth_ip6_event(struct notifier_block *this,
memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
addr->u.a6.pfxlen = ifa->prefix_len;
addr->type = QETH_IP_TYPE_NORMAL;
- }
+ } else
+ goto out;
+
switch(event) {
case NETDEV_UP:
- if (addr){
- if (!qeth_add_ip(card, addr))
- kfree(addr);
- }
+ if (!qeth_add_ip(card, addr))
+ kfree(addr);
break;
case NETDEV_DOWN:
- if (addr){
- if (!qeth_delete_ip(card, addr))
- kfree(addr);
- }
+ if (!qeth_delete_ip(card, addr))
+ kfree(addr);
break;
default:
break;
}
qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD);
schedule_work(&card->kernel_thread_starter);
-
+out:
return NOTIFY_DONE;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 31eb79a84c58..a6f1156440bf 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -29,7 +29,7 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.105 $"
+#define ZFCP_AUX_REVISION "$Revision: 1.107 $"
#include "zfcp_ext.h"
@@ -1078,17 +1078,6 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
{
char dbf_name[20];
- /* debug feature area which records fsf request sequence numbers */
- sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s",
- zfcp_get_busid_by_adapter(adapter));
- adapter->req_dbf = debug_register(dbf_name,
- ZFCP_REQ_DBF_INDEX,
- ZFCP_REQ_DBF_AREAS,
- ZFCP_REQ_DBF_LENGTH);
- debug_register_view(adapter->req_dbf, &debug_hex_ascii_view);
- debug_set_level(adapter->req_dbf, ZFCP_REQ_DBF_LEVEL);
- debug_text_event(adapter->req_dbf, 1, "zzz");
-
/* debug feature area which records SCSI command failures (hostbyte) */
rwlock_init(&adapter->cmd_dbf_lock);
sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
@@ -1131,7 +1120,7 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
- if (adapter->req_dbf && adapter->cmd_dbf && adapter->abort_dbf &&
+ if (adapter->cmd_dbf && adapter->abort_dbf &&
adapter->in_els_dbf && adapter->erp_dbf)
return 0;
@@ -1147,7 +1136,6 @@ void
zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
{
debug_unregister(adapter->erp_dbf);
- debug_unregister(adapter->req_dbf);
debug_unregister(adapter->cmd_dbf);
debug_unregister(adapter->abort_dbf);
debug_unregister(adapter->in_els_dbf);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 00de5d6f0733..e4bc663cea4a 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -33,7 +33,7 @@
#define ZFCP_DEF_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_DEF_REVISION "$Revision: 1.71 $"
+#define ZFCP_DEF_REVISION "$Revision: 1.72 $"
/*************************** INCLUDES *****************************************/
@@ -450,19 +450,12 @@ struct zfcp_ls_rnid_acc {
#define ZFCP_ERP_DBF_LEVEL 3
#define ZFCP_ERP_DBF_NAME "zfcperp"
-#define ZFCP_REQ_DBF_INDEX 1
-#define ZFCP_REQ_DBF_AREAS 1
-#define ZFCP_REQ_DBF_LENGTH 8
-#define ZFCP_REQ_DBF_LEVEL 1
-#define ZFCP_REQ_DBF_NAME "zfcpreq"
-
#define ZFCP_CMD_DBF_INDEX 2
#define ZFCP_CMD_DBF_AREAS 1
#define ZFCP_CMD_DBF_LENGTH 8
#define ZFCP_CMD_DBF_LEVEL 3
#define ZFCP_CMD_DBF_NAME "zfcpcmd"
-
#define ZFCP_ABORT_DBF_INDEX 2
#define ZFCP_ABORT_DBF_AREAS 1
#define ZFCP_ABORT_DBF_LENGTH 8
@@ -475,11 +468,6 @@ struct zfcp_ls_rnid_acc {
#define ZFCP_IN_ELS_DBF_LEVEL 6
#define ZFCP_IN_ELS_DBF_NAME "zfcpels"
-#define ZFCP_ADAPTER_REQ_DBF_INDEX 4
-#define ZFCP_ADAPTER_REQ_DBF_AREAS 1
-#define ZFCP_ADAPTER_REQ_DBF_LENGTH 8
-#define ZFCP_ADAPTER_REQ_DBF_LEVEL 6
-
/******************** LOGGING MACROS AND DEFINES *****************************/
/*
@@ -986,7 +974,6 @@ struct zfcp_adapter {
struct zfcp_port *nameserver_port; /* adapter's nameserver */
debug_info_t *erp_dbf; /* S/390 debug features */
debug_info_t *abort_dbf;
- debug_info_t *req_dbf;
debug_info_t *in_els_dbf;
debug_info_t *cmd_dbf;
rwlock_t cmd_dbf_lock;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index ccac73ed538f..045d04ba8497 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_ERP_REVISION "$Revision: 1.49 $"
+#define ZFCP_ERP_REVISION "$Revision: 1.51 $"
#include "zfcp_ext.h"
@@ -1865,6 +1865,7 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
case ZFCP_ERP_FAILED :
atomic_inc(&port->erp_counter);
if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+ zfcp_erp_port_failed(port);
break;
case ZFCP_ERP_EXIT :
/* nothing */
@@ -1874,7 +1875,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) {
zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */
result = ZFCP_ERP_EXIT;
- zfcp_erp_port_failed(port);
}
return result;
@@ -2397,8 +2397,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
ZFCP_LOG_NORMAL("bug: shutdown of QDIO queues failed "
"(retval=%d)\n", retval_cleanup);
}
- else
- debug_text_event(adapter->req_dbf, 1, "q_clean");
failed_qdio_establish:
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
@@ -2468,10 +2466,8 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
ZFCP_LOG_NORMAL("bug: shutdown of QDIO queues failed on "
"adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
- } else {
+ } else
ZFCP_LOG_DEBUG("queues cleaned up\n");
- debug_text_event(adapter->req_dbf, 1, "q_clean");
- }
/*
* First we had to stop QDIO operation.
@@ -2834,9 +2830,10 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
/* nameserver port may live again */
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
&adapter->nameserver_port->status);
- zfcp_erp_port_reopen(adapter->nameserver_port, 0);
- erp_action->step = ZFCP_ERP_STEP_NAMESERVER_OPEN;
- retval = ZFCP_ERP_CONTINUES;
+ if (zfcp_erp_port_reopen(adapter->nameserver_port, 0) >= 0) {
+ erp_action->step = ZFCP_ERP_STEP_NAMESERVER_OPEN;
+ retval = ZFCP_ERP_CONTINUES;
+ } else retval = ZFCP_ERP_FAILED;
break;
}
/* else nameserver port is already open, fall through */
@@ -2972,6 +2969,10 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w");
debug_event(adapter->erp_dbf, 3,
&erp_action->port->wwpn, sizeof (wwn_t));
+ if (atomic_test_mask(
+ ZFCP_STATUS_COMMON_ERP_FAILED,
+ &adapter->nameserver_port->status))
+ zfcp_erp_port_failed(erp_action->port);
zfcp_erp_action_ready(erp_action);
}
}
@@ -3357,7 +3358,7 @@ zfcp_erp_action_enqueue(int action,
struct zfcp_adapter *adapter,
struct zfcp_port *port, struct zfcp_unit *unit)
{
- int retval = -1;
+ int retval = 1;
struct zfcp_erp_action *erp_action = NULL;
int stronger_action = 0;
u32 status = 0;
@@ -3376,7 +3377,7 @@ zfcp_erp_action_enqueue(int action,
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
&adapter->status))
- goto out;
+ return -EIO;
debug_event(adapter->erp_dbf, 4, &action, sizeof (int));
/* check whether we really need this */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index c4faf9ec2b89..79bb0bab483f 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -29,7 +29,7 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_FSF_C_REVISION "$Revision: 1.43 $"
+#define ZFCP_FSF_C_REVISION "$Revision: 1.45 $"
#include "zfcp_ext.h"
@@ -379,13 +379,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
zfcp_get_busid_by_adapter(adapter),
fsf_req->qtcb->prefix.prot_status_qual.
sequence_error.exp_req_seq_no);
- debug_text_event(adapter->req_dbf, 1, "exp_seq!");
- debug_event(adapter->req_dbf, 1,
- &fsf_req->qtcb->prefix.prot_status_qual.
- sequence_error.exp_req_seq_no, 4);
- debug_text_event(adapter->req_dbf, 1, "qtcb_seq!");
- debug_exception(adapter->req_dbf, 1,
- &fsf_req->qtcb->prefix.req_seq_no, 4);
debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err");
/* restart operation on this adapter */
zfcp_erp_adapter_reopen(adapter, 0);
@@ -891,7 +884,6 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
ZFCP_LOG_TRACE("Status Read request initiated (adapter%s)\n",
zfcp_get_busid_by_adapter(adapter));
- debug_text_event(adapter->req_dbf, 1, "unso");
goto out;
failed_req_send:
@@ -1277,10 +1269,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
case FSF_FCP_COMMAND_DOES_NOT_EXIST:
ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n");
retval = 0;
- debug_text_event(new_fsf_req->adapter->req_dbf, 3, "no_exist");
- debug_event(new_fsf_req->adapter->req_dbf, 3,
- &new_fsf_req->qtcb->bottom.support.req_handle,
- sizeof (unsigned long));
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_no_exist");
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
@@ -3373,10 +3361,6 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
* (need this for look up on normal command completion)
*/
fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd;
- debug_text_event(adapter->req_dbf, 3, "fsf/sc");
- debug_event(adapter->req_dbf, 3, &fsf_req, sizeof (unsigned long));
- debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long));
-
fsf_req->data.send_fcp_command_task.start_jiffies = jiffies;
fsf_req->data.send_fcp_command_task.unit = unit;
ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun);
@@ -3517,12 +3501,9 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
send_failed:
no_fit:
failed_scsi_cmnd:
- /* dequeue new FSF request previously enqueued */
- debug_text_event(adapter->req_dbf, 3, "fail_sc");
- debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long));
-
zfcp_fsf_req_free(fsf_req);
fsf_req = NULL;
+ scsi_cmnd->host_scribble = NULL;
success:
failed_req_create:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
@@ -4267,14 +4248,9 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
* the new eh
*/
/* always call back */
- debug_text_event(fsf_req->adapter->req_dbf, 2, "ok_done:");
- debug_event(fsf_req->adapter->req_dbf, 2, &scpnt,
- sizeof (unsigned long));
- debug_event(fsf_req->adapter->req_dbf, 2, &scpnt->scsi_done,
- sizeof (unsigned long));
- debug_event(fsf_req->adapter->req_dbf, 2, &fsf_req,
- sizeof (unsigned long));
+
(scpnt->scsi_done) (scpnt);
+
/*
* We must hold this lock until scsi_done has been called.
* Otherwise we may call scsi_done after abort regarding this
@@ -4954,15 +4930,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
"to request queue.\n");
} else {
req_queue->distance_from_int = new_distance_from_int;
- debug_text_event(adapter->req_dbf, 1, "o:a/seq");
- debug_event(adapter->req_dbf, 1, &fsf_req,
- sizeof (unsigned long));
- if (likely(inc_seq_no)) {
- debug_event(adapter->req_dbf, 1,
- &adapter->fsf_req_seq_no, sizeof (u32));
- } else {
- debug_text_event(adapter->req_dbf, 1, "nocb");
- }
/*
* increase FSF sequence counter -
* this must only be done for request successfully enqueued to
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 1e72bd18796b..ca238c054d5d 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.16 $"
+#define ZFCP_QDIO_C_REVISION "$Revision: 1.18 $"
#include "zfcp_ext.h"
@@ -485,10 +485,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
struct zfcp_fsf_req *fsf_req;
int retval = 0;
- /* Note: seq is entered later */
- debug_text_event(adapter->req_dbf, 1, "i:a/seq");
- debug_event(adapter->req_dbf, 1, &sbale_addr, sizeof (unsigned long));
-
/* invalid (per convention used in this driver) */
if (unlikely(!sbale_addr)) {
ZFCP_LOG_NORMAL("bug: invalid reqid\n");
@@ -506,11 +502,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
retval = -EINVAL;
goto out;
}
- /* debug feature stuff (test for QTCB: remember new unsol. status!) */
- if (likely(fsf_req->qtcb)) {
- debug_event(adapter->req_dbf, 1,
- &fsf_req->qtcb->prefix.req_seq_no, sizeof (u32));
- }
ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
if (likely(fsf_req->qtcb)) {
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 071007e0f181..ed9ebd166acc 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_SCSI_REVISION "$Revision: 1.59 $"
+#define ZFCP_SCSI_REVISION "$Revision: 1.60 $"
#include <linux/blkdev.h>
@@ -297,10 +297,6 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
if (unlikely(tmp < 0)) {
ZFCP_LOG_DEBUG("error: initiation of Send FCP Cmnd failed\n");
retval = SCSI_MLQUEUE_HOST_BUSY;
- } else {
- debug_text_event(adapter->req_dbf, 3, "q_scpnt");
- debug_event(adapter->req_dbf, 3, &scpnt,
- sizeof (unsigned long));
}
out:
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index bf653f99513d..23f452ad3f64 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -205,7 +205,7 @@ config SERIAL_AMBA_PL011
depends on ARM_AMBA
select SERIAL_CORE
help
- This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
+ This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
here.
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index daee75c13a46..482693db18a0 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -207,7 +207,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
/**
* fb_set_cmap - set the colormap
* @cmap: frame buffer colormap structure
- * @kspc: boolean, 0 copy local, 1 get_user() function
+ * @kspc: boolean, 1 copy local, 0 get_user() function
* @info: frame buffer info structure
*
* Sets the colormap @cmap for a screen of device @info.
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index bd6eb4940d3c..9875025aa650 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -44,7 +44,7 @@ config BINFMT_SHARED_FLAT
config BINFMT_AOUT
tristate "Kernel support for a.out and ECOFF binaries"
- depends on (X86 && !X86_64) || ALPHA || ARM || M68K || MIPS || SPARC32
+ depends on (X86 && !X86_64) || ALPHA || ARM || M68K || SPARC32
---help---
A.out (Assembler.OUTput) is a set of formats for libraries and
executables used in the earliest versions of UNIX. Linux used
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b0314046ec4b..1b43058d8dc0 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -251,6 +251,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
{
memset(bdev, 0, sizeof(*bdev));
sema_init(&bdev->bd_sem, 1);
+ sema_init(&bdev->bd_mount_sem, 1);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
inode_init_once(&ei->vfs_inode);
diff --git a/fs/buffer.c b/fs/buffer.c
index 21b8ae31e827..7fc4e91f0ce9 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -227,6 +227,77 @@ int fsync_bdev(struct block_device *bdev)
return sync_blockdev(bdev);
}
+/**
+ * freeze_bdev -- lock a filesystem and force it into a consistent state
+ * @bdev: blockdevice to lock
+ *
+ * This takes the block device bd_mount_sem to make sure no new mounts
+ * happen on bdev until thaw_bdev() is called.
+ * If a superblock is found on this device, we take the s_umount semaphore
+ * on it to make sure nobody unmounts until the snapshot creation is done.
+ */
+struct super_block *freeze_bdev(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ down(&bdev->bd_mount_sem);
+ sb = get_super(bdev);
+ if (sb && !(sb->s_flags & MS_RDONLY)) {
+ sb->s_frozen = SB_FREEZE_WRITE;
+ wmb();
+
+ sync_inodes_sb(sb, 0);
+ DQUOT_SYNC(sb);
+
+ lock_super(sb);
+ if (sb->s_dirt && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, 1);
+
+ sync_blockdev(sb->s_bdev);
+ sync_inodes_sb(sb, 1);
+
+ sb->s_frozen = SB_FREEZE_TRANS;
+ wmb();
+
+ sync_blockdev(sb->s_bdev);
+
+ if (sb->s_op->write_super_lockfs)
+ sb->s_op->write_super_lockfs(sb);
+ }
+
+ sync_blockdev(bdev);
+ return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
+}
+EXPORT_SYMBOL(freeze_bdev);
+
+/**
+ * thaw_bdev -- unlock filesystem
+ * @bdev: blockdevice to unlock
+ * @sb: associated superblock
+ *
+ * Unlocks the filesystem and marks it writeable again after freeze_bdev().
+ */
+void thaw_bdev(struct block_device *bdev, struct super_block *sb)
+{
+ if (sb) {
+ BUG_ON(sb->s_bdev != bdev);
+
+ if (sb->s_op->unlockfs)
+ sb->s_op->unlockfs(sb);
+ sb->s_frozen = SB_UNFROZEN;
+ wmb();
+ wake_up(&sb->s_wait_unfrozen);
+ drop_super(sb);
+ }
+
+ up(&bdev->bd_mount_sem);
+}
+EXPORT_SYMBOL(thaw_bdev);
+
/*
* sync everything. Start out by waking pdflush, because that writes back
* all queues in parallel.
diff --git a/fs/compat.c b/fs/compat.c
index 40023e684520..b628d2e315f1 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -235,7 +235,7 @@ out:
return error;
}
-/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64 */
+/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
#define IOCTL_HASHSIZE 256
struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index de45d833d0f4..56ef9138e9cc 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -70,8 +70,10 @@
#include <net/sock.h> /* siocdevprivate_ioctl */
#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/rfcomm.h>
#include <net/bluetooth/hci.h>
+#include <net/bluetooth/rfcomm.h>
+
+#include <linux/capi.h>
#include <scsi/scsi.h>
/* Ugly hack. */
diff --git a/fs/exec.c b/fs/exec.c
index c37b1478fdac..47285fe301ff 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -870,15 +870,6 @@ out:
EXPORT_SYMBOL(flush_old_exec);
-/*
- * We mustn't allow tracing of suid binaries, unless
- * the tracer has the capability to trace anything..
- */
-static inline int must_not_trace_exec(struct task_struct * p)
-{
- return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
-}
-
/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -945,27 +936,7 @@ EXPORT_SYMBOL(prepare_binprm);
void compute_creds(struct linux_binprm *bprm)
{
- task_lock(current);
- if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
- current->mm->dumpable = 0;
-
- if (must_not_trace_exec(current)
- || atomic_read(&current->fs->count) > 1
- || atomic_read(&current->files->count) > 1
- || atomic_read(&current->sighand->count) > 1) {
- if(!capable(CAP_SETUID)) {
- bprm->e_uid = current->uid;
- bprm->e_gid = current->gid;
- }
- }
- }
-
- current->suid = current->euid = current->fsuid = bprm->e_uid;
- current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
- task_unlock(current);
-
- security_bprm_compute_creds(bprm);
+ security_bprm_apply_creds(bprm);
}
EXPORT_SYMBOL(compute_creds);
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 12f71306153a..3c95df4bb817 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -599,6 +599,7 @@ struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
return NULL;
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+ memset(bh->b_data, 0, journal->j_blocksize);
bh->b_state |= (1 << BH_Dirty);
BUFFER_TRACE(bh, "return this buffer");
return journal_add_journal_head(bh);
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index fc425aa0d47c..864615916862 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -117,11 +117,16 @@ static int mount_port __initdata = 0; /* Mount daemon port number */
***************************************************************************/
enum {
+ /* Options that take integer arguments */
Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin,
- Opt_acregmax, Opt_acdirmin, Opt_acdirmax, Opt_soft, Opt_hard, Opt_intr,
+ Opt_acregmax, Opt_acdirmin, Opt_acdirmax,
+ /* Options that take no arguments */
+ Opt_soft, Opt_hard, Opt_intr,
Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
- Opt_broken_suid, Opt_err,
+ Opt_broken_suid,
+ /* Error token */
+ Opt_err
};
static match_table_t __initdata tokens = {
@@ -146,9 +151,13 @@ static match_table_t __initdata tokens = {
{Opt_noac, "noac"},
{Opt_lock, "lock"},
{Opt_nolock, "nolock"},
+ {Opt_v2, "nfsvers=2"},
{Opt_v2, "v2"},
+ {Opt_v3, "nfsvers=3"},
{Opt_v3, "v3"},
+ {Opt_udp, "proto=udp"},
{Opt_udp, "udp"},
+ {Opt_tcp, "proto=tcp"},
{Opt_tcp, "tcp"},
{Opt_broken_suid, "broken_suid"},
{Opt_err, NULL}
@@ -169,18 +178,19 @@ static int __init root_nfs_parse(char *name, char *buf)
if (!name)
return 1;
- if (name[0] && strcmp(name, "default")){
- strlcpy(buf, name, NFS_MAXPATHLEN);
- return 1;
- }
+ /* Set the NFS remote path */
+ p = strsep(&name, ",");
+ if (p[0] != '\0' && strcmp(p, "default") != 0)
+ strlcpy(buf, p, NFS_MAXPATHLEN);
+
while ((p = strsep (&name, ",")) != NULL) {
int token;
if (!*p)
continue;
token = match_token(p, tokens, args);
- /* %u tokens only */
- if (match_int(&args[0], &option))
+ /* %u tokens only. Beware if you add new tokens! */
+ if (token < Opt_soft && match_int(&args[0], &option))
return 0;
switch (token) {
case Opt_port:
@@ -265,6 +275,7 @@ static int __init root_nfs_parse(char *name, char *buf)
return 0;
}
}
+
return 1;
}
@@ -273,7 +284,7 @@ static int __init root_nfs_parse(char *name, char *buf)
*/
static int __init root_nfs_name(char *name)
{
- static char buf[NFS_MAXPATHLEN];
+ static char buf[NFS_MAXPATHLEN] __initdata;
char *cp;
/* Set some default values */
@@ -283,9 +294,6 @@ static int __init root_nfs_name(char *name)
nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */
nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
- nfs_data.bsize = 0;
- nfs_data.timeo = 7;
- nfs_data.retrans = 3;
nfs_data.acregmin = 3;
nfs_data.acregmax = 60;
nfs_data.acdirmin = 30;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f2233df104a6..1ab82924fba5 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -86,7 +86,7 @@ static void reiserfs_write_super_lockfs (struct super_block * s)
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
reiserfs_block_writes(&th) ;
- journal_end(&th, s, 1) ;
+ journal_end_sync(&th, s, 1) ;
}
s->s_dirt = 0;
reiserfs_write_unlock(s);
diff --git a/fs/super.c b/fs/super.c
index f20abf04f8a5..e62838940bc7 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -77,6 +77,7 @@ static struct super_block *alloc_super(void)
sema_init(&s->s_dquot.dqio_sem, 1);
sema_init(&s->s_dquot.dqonoff_sem, 1);
init_rwsem(&s->s_dquot.dqptr_sem);
+ init_waitqueue_head(&s->s_wait_unfrozen);
s->s_maxbytes = MAX_NON_LFS;
s->dq_op = sb_dquot_ops;
s->s_qcop = sb_quotactl_ops;
@@ -623,7 +624,14 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
if (IS_ERR(bdev))
return (struct super_block *)bdev;
+ /*
+ * once the super is inserted into the list by sget, s_umount
+ * will protect the lockfs code from trying to start a snapshot
+ * while we are mounting
+ */
+ down(&bdev->bd_mount_sem);
s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
+ up(&bdev->bd_mount_sem);
if (IS_ERR(s))
goto out;
diff --git a/fs/xfs/linux/xfs_ioctl.c b/fs/xfs/linux/xfs_ioctl.c
index fb317760a25e..c5059bbe5694 100644
--- a/fs/xfs/linux/xfs_ioctl.c
+++ b/fs/xfs/linux/xfs_ioctl.c
@@ -825,13 +825,14 @@ xfs_ioctl(
case XFS_IOC_FREEZE:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- xfs_fs_freeze(mp);
+
+ freeze_bdev(inode->i_sb->s_bdev);
return 0;
case XFS_IOC_THAW:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- xfs_fs_thaw(mp);
+ thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
return 0;
case XFS_IOC_GOINGDOWN: {
diff --git a/fs/xfs/linux/xfs_lrw.c b/fs/xfs/linux/xfs_lrw.c
index 2077d8536208..93bb959fef48 100644
--- a/fs/xfs/linux/xfs_lrw.c
+++ b/fs/xfs/linux/xfs_lrw.c
@@ -682,8 +682,6 @@ xfs_write(
io = &xip->i_iocore;
mp = io->io_mount;
- xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
-
if (XFS_FORCED_SHUTDOWN(mp)) {
return -EIO;
}
diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c
index 478e7caca902..5b7f46bc34b9 100644
--- a/fs/xfs/linux/xfs_super.c
+++ b/fs/xfs/linux/xfs_super.c
@@ -589,28 +589,7 @@ STATIC void
linvfs_freeze_fs(
struct super_block *sb)
{
- vfs_t *vfsp = LINVFS_GET_VFS(sb);
- vnode_t *vp;
- int error;
-
- if (sb->s_flags & MS_RDONLY)
- return;
- VFS_ROOT(vfsp, &vp, error);
- VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_FREEZE, 0, error);
- VN_RELE(vp);
-}
-
-STATIC void
-linvfs_unfreeze_fs(
- struct super_block *sb)
-{
- vfs_t *vfsp = LINVFS_GET_VFS(sb);
- vnode_t *vp;
- int error;
-
- VFS_ROOT(vfsp, &vp, error);
- VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_THAW, 0, error);
- VN_RELE(vp);
+ VFS_FREEZE(LINVFS_GET_VFS(sb));
}
STATIC struct dentry *
@@ -850,7 +829,6 @@ STATIC struct super_operations linvfs_sops = {
.write_super = linvfs_write_super,
.sync_fs = linvfs_sync_super,
.write_super_lockfs = linvfs_freeze_fs,
- .unlockfs = linvfs_unfreeze_fs,
.statfs = linvfs_statfs,
.remount_fs = linvfs_remount,
.show_options = linvfs_show_options,
diff --git a/fs/xfs/linux/xfs_vfs.c b/fs/xfs/linux/xfs_vfs.c
index 63adf1d5988e..2b75cccdfd60 100644
--- a/fs/xfs/linux/xfs_vfs.c
+++ b/fs/xfs/linux/xfs_vfs.c
@@ -230,6 +230,18 @@ vfs_force_shutdown(
((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line));
}
+void
+vfs_freeze(
+ struct bhv_desc *bdp)
+{
+ struct bhv_desc *next = bdp;
+
+ ASSERT(next);
+ while (! (bhvtovfsops(next))->vfs_freeze)
+ next = BHV_NEXT(next);
+ ((*bhvtovfsops(next)->vfs_freeze)(next));
+}
+
vfs_t *
vfs_allocate( void )
{
diff --git a/fs/xfs/linux/xfs_vfs.h b/fs/xfs/linux/xfs_vfs.h
index f94ce05153c3..dc1cd1973dda 100644
--- a/fs/xfs/linux/xfs_vfs.h
+++ b/fs/xfs/linux/xfs_vfs.h
@@ -112,6 +112,7 @@ typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
struct vnode *, bhv_desc_t *, int);
typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
+typedef void (*vfs_freeze_t)(bhv_desc_t *);
typedef struct vfsops {
bhv_position_t vf_position; /* behavior chain position */
@@ -128,6 +129,7 @@ typedef struct vfsops {
vfs_quotactl_t vfs_quotactl; /* disk quota */
vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
+ vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
} vfsops_t;
/*
@@ -147,6 +149,7 @@ typedef struct vfsops {
#define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p))
#define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) )
#define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) )
+#define VFS_FREEZE(v) ( vfs_freeze(VHEAD(v)) )
/*
* PVFS's. Operates on behavior descriptor pointers.
@@ -164,6 +167,7 @@ typedef struct vfsops {
#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p))
#define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) )
#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) )
+#define PVFS_FREEZE(b) ( vfs_freeze(b) )
extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
@@ -178,6 +182,7 @@ extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int);
extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
+extern void vfs_freeze(bhv_desc_t *);
typedef struct bhv_vfsops {
struct vfsops bhv_common;
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index d6a6d056c34e..37b28e59e8c1 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -582,63 +582,25 @@ xfs_fs_log_dummy(xfs_mount_t *mp)
}
int
-xfs_fs_freeze(
- xfs_mount_t *mp)
-{
- vfs_t *vfsp;
- /*REFERENCED*/
- int error;
-
- vfsp = XFS_MTOVFS(mp);
-
- /* Stop new writers */
- xfs_start_freeze(mp, XFS_FREEZE_WRITE);
-
- /* Flush the refcache */
- xfs_refcache_purge_mp(mp);
-
- /* Flush delalloc and delwri data */
- VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error);
-
- /* Pause transaction subsystem */
- xfs_start_freeze(mp, XFS_FREEZE_TRANS);
-
- /* Flush any remaining inodes into buffers */
- VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error);
-
- /* Push all buffers out to disk */
- xfs_binval(mp->m_ddev_targp);
- if (mp->m_rtdev_targp) {
- xfs_binval(mp->m_rtdev_targp);
- }
-
- /* Push the superblock and write an unmount record */
- xfs_log_unmount_write(mp);
- xfs_unmountfs_writesb(mp);
-
- return 0;
-}
-
-int
-xfs_fs_thaw(
- xfs_mount_t *mp)
-{
- xfs_finish_freeze(mp);
- return 0;
-}
-
-int
xfs_fs_goingdown(
xfs_mount_t *mp,
__uint32_t inflags)
{
- switch (inflags)
- {
- case XFS_FSOP_GOING_FLAGS_DEFAULT:
- xfs_fs_freeze(mp);
- xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
- xfs_fs_thaw(mp);
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ switch (inflags) {
+ case XFS_FSOP_GOING_FLAGS_DEFAULT: {
+ struct vfs *vfsp = XFS_MTOVFS(mp);
+ struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
+
+ if (sb) {
+ xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+ thaw_bdev(sb->s_bdev, sb);
+ }
+
break;
+ }
case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
break;
diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h
index 70b0f125767b..b61486173a61 100644
--- a/fs/xfs/xfs_fsops.h
+++ b/fs/xfs/xfs_fsops.h
@@ -60,14 +60,6 @@ xfs_reserve_blocks(
xfs_fsop_resblks_t *outval);
int
-xfs_fs_freeze(
- xfs_mount_t *mp);
-
-int
-xfs_fs_thaw(
- xfs_mount_t *mp);
-
-int
xfs_fs_goingdown(
xfs_mount_t *mp,
__uint32_t inflags);
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 9ff45c11d3c8..8505f1d35429 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -820,7 +820,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
xlog_t *log = mp->m_log;
vfs_t *vfsp = XFS_MTOVFS(mp);
- if (mp->m_frozen || XFS_FORCED_SHUTDOWN(mp) ||
+ if (vfsp->vfs_super->s_frozen || XFS_FORCED_SHUTDOWN(mp) ||
(vfsp->vfs_flag & VFS_RDONLY))
return 0;
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index e9039e8842b0..56d104d21e63 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -140,9 +140,6 @@ xfs_mount_init(void)
*/
xfs_trans_ail_init(mp);
- /* Init freeze sync structures */
- spinlock_init(&mp->m_freeze_lock, "xfs_freeze");
- init_sv(&mp->m_wait_unfreeze, SV_DEFAULT, "xfs_freeze", 0);
atomic_set(&mp->m_active_trans, 0);
return mp;
@@ -192,8 +189,6 @@ xfs_mount_free(
VFS_REMOVEBHV(vfsp, &mp->m_bhv);
}
- spinlock_destroy(&mp->m_freeze_lock);
- sv_destroy(&mp->m_wait_unfreeze);
kmem_free(mp, sizeof(xfs_mount_t));
}
@@ -1586,59 +1581,3 @@ xfs_mount_log_sbunit(
xfs_mod_sb(tp, fields);
xfs_trans_commit(tp, 0, NULL);
}
-
-/* Functions to lock access out of the filesystem for forced
- * shutdown or snapshot.
- */
-
-void
-xfs_start_freeze(
- xfs_mount_t *mp,
- int level)
-{
- unsigned long s = mutex_spinlock(&mp->m_freeze_lock);
-
- mp->m_frozen = level;
- mutex_spinunlock(&mp->m_freeze_lock, s);
-
- if (level == XFS_FREEZE_TRANS) {
- while (atomic_read(&mp->m_active_trans) > 0)
- delay(100);
- }
-}
-
-void
-xfs_finish_freeze(
- xfs_mount_t *mp)
-{
- unsigned long s = mutex_spinlock(&mp->m_freeze_lock);
-
- if (mp->m_frozen) {
- mp->m_frozen = 0;
- sv_broadcast(&mp->m_wait_unfreeze);
- }
-
- mutex_spinunlock(&mp->m_freeze_lock, s);
-}
-
-void
-xfs_check_frozen(
- xfs_mount_t *mp,
- bhv_desc_t *bdp,
- int level)
-{
- unsigned long s;
-
- if (mp->m_frozen) {
- s = mutex_spinlock(&mp->m_freeze_lock);
-
- if (mp->m_frozen < level) {
- mutex_spinunlock(&mp->m_freeze_lock, s);
- } else {
- sv_wait(&mp->m_wait_unfreeze, 0, &mp->m_freeze_lock, s);
- }
- }
-
- if (level == XFS_FREEZE_TRANS)
- atomic_inc(&mp->m_active_trans);
-}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index ea86fbaffd40..e338e32d346d 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -379,10 +379,6 @@ typedef struct xfs_mount {
struct xfs_dmops m_dm_ops; /* vector of DMI ops */
struct xfs_qmops m_qm_ops; /* vector of XQM ops */
struct xfs_ioops m_io_ops; /* vector of I/O ops */
- lock_t m_freeze_lock; /* Lock for m_frozen */
- uint m_frozen; /* FS frozen for shutdown or
- * snapshot */
- sv_t m_wait_unfreeze;/* waiting to unfreeze */
atomic_t m_active_trans; /* number trans frozen */
} xfs_mount_t;
@@ -558,16 +554,6 @@ extern void xfs_initialize_perag(xfs_mount_t *, int);
extern void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
__int64_t);
-/*
- * Flags for freeze operations.
- */
-#define XFS_FREEZE_WRITE 1
-#define XFS_FREEZE_TRANS 2
-
-extern void xfs_start_freeze(xfs_mount_t *, int);
-extern void xfs_finish_freeze(xfs_mount_t *);
-extern void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int);
-
extern struct vfsops xfs_vfsops;
extern struct vnodeops xfs_vnodeops;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index af07bd91b81e..aebea7a293d6 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -131,7 +131,9 @@ xfs_trans_alloc(
xfs_mount_t *mp,
uint type)
{
- xfs_check_frozen(mp, NULL, XFS_FREEZE_TRANS);
+ vfs_check_frozen(XFS_MTOVFS(mp)->vfs_super, SB_FREEZE_TRANS);
+ atomic_inc(&mp->m_active_trans);
+
return (_xfs_trans_alloc(mp, type));
}
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index e0bbdbef441a..3d6822de23eb 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1858,6 +1858,20 @@ xfs_showargs(
return 0;
}
+STATIC void
+xfs_freeze(
+ bhv_desc_t *bdp)
+{
+ xfs_mount_t *mp = XFS_BHVTOM(bdp);
+
+ while (atomic_read(&mp->m_active_trans) > 0)
+ delay(100);
+
+ /* Push the superblock and write an unmount record */
+ xfs_log_unmount_write(mp);
+ xfs_unmountfs_writesb(mp);
+}
+
vfsops_t xfs_vfsops = {
BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
@@ -1874,4 +1888,5 @@ vfsops_t xfs_vfsops = {
.vfs_quotactl = (vfs_quotactl_t)fs_nosys,
.vfs_init_vnode = xfs_initialize_vnode,
.vfs_force_shutdown = xfs_do_force_shutdown,
+ .vfs_freeze = xfs_freeze,
};
diff --git a/include/asm-arm/arch-versatile/dma.h b/include/asm-arm/arch-versatile/dma.h
new file mode 100644
index 000000000000..dcc8ac26eac0
--- /dev/null
+++ b/include/asm-arm/arch-versatile/dma.h
@@ -0,0 +1,27 @@
+/*
+ * linux/include/asm-arm/arch-versatile/dma.h
+ *
+ * Copyright (C) 2003 ARM Limited.
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS 0xffffffff
+#define MAX_DMA_CHANNELS 0
+
+#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h
new file mode 100644
index 000000000000..535b1f041b73
--- /dev/null
+++ b/include/asm-arm/arch-versatile/hardware.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/arch-versatile/hardware.h
+ *
+ * This file contains the hardware definitions of the Versatile PB board.
+ *
+ * Copyright (C) 2003 ARM Limited.
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include <asm/arch/platform.h>
+
+// FIXME = PCI settings need to be fixed!!!!!
+
+/*
+ * Similar to above, but for PCI addresses (memory, IO, Config and the
+ * V3 chip itself). WARNING: this has to mirror definitions in platform.h
+ */
+#define PCI_MEMORY_VADDR 0xe8000000
+#define PCI_CONFIG_VADDR 0xec000000
+#define PCI_V3_VADDR 0xed000000
+#define PCI_IO_VADDR 0xee000000
+
+#define PCIO_BASE PCI_IO_VADDR
+#define PCIMEM_BASE PCI_MEMORY_VADDR
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+
+#endif
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h
new file mode 100644
index 000000000000..542bc6b5d03c
--- /dev/null
+++ b/include/asm-arm/arch-versatile/io.h
@@ -0,0 +1,29 @@
+/*
+ * linux/include/asm-arm/arch-versatile/io.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffff
+
+#define __io(a) ((a))
+#define __mem_pci(a) ((unsigned long)(a))
+#define __mem_isa(a) ((unsigned long)(a))
+
+#endif
diff --git a/include/asm-arm/arch-versatile/irqs.h b/include/asm-arm/arch-versatile/irqs.h
new file mode 100644
index 000000000000..745aa841b31a
--- /dev/null
+++ b/include/asm-arm/arch-versatile/irqs.h
@@ -0,0 +1,211 @@
+/*
+ * linux/include/asm-arm/arch-versatile/irqs.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/arch/platform.h>
+
+/*
+ * IRQ interrupts definitions are the same the INT definitions
+ * held within platform.h
+ */
+#define IRQ_VIC_START 0
+#define IRQ_WDOGINT (IRQ_VIC_START + INT_WDOGINT)
+#define IRQ_SOFTINT (IRQ_VIC_START + INT_SOFTINT)
+#define IRQ_COMMRx (IRQ_VIC_START + INT_COMMRx)
+#define IRQ_COMMTx (IRQ_VIC_START + INT_COMMTx)
+#define IRQ_TIMERINT0_1 (IRQ_VIC_START + INT_TIMERINT0_1)
+#define IRQ_TIMERINT2_3 (IRQ_VIC_START + INT_TIMERINT2_3)
+#define IRQ_GPIOINT0 (IRQ_VIC_START + INT_GPIOINT0)
+#define IRQ_GPIOINT1 (IRQ_VIC_START + INT_GPIOINT1)
+#define IRQ_GPIOINT2 (IRQ_VIC_START + INT_GPIOINT2)
+#define IRQ_GPIOINT3 (IRQ_VIC_START + INT_GPIOINT3)
+#define IRQ_RTCINT (IRQ_VIC_START + INT_RTCINT)
+#define IRQ_SSPINT (IRQ_VIC_START + INT_SSPINT)
+#define IRQ_UARTINT0 (IRQ_VIC_START + INT_UARTINT0)
+#define IRQ_UARTINT1 (IRQ_VIC_START + INT_UARTINT1)
+#define IRQ_UARTINT2 (IRQ_VIC_START + INT_UARTINT2)
+#define IRQ_SCIINT (IRQ_VIC_START + INT_SCIINT)
+#define IRQ_CLCDINT (IRQ_VIC_START + INT_CLCDINT)
+#define IRQ_DMAINT (IRQ_VIC_START + INT_DMAINT)
+#define IRQ_PWRFAILINT (IRQ_VIC_START + INT_PWRFAILINT)
+#define IRQ_MBXINT (IRQ_VIC_START + INT_MBXINT)
+#define IRQ_GNDINT (IRQ_VIC_START + INT_GNDINT)
+#define IRQ_VICSOURCE21 (IRQ_VIC_START + INT_VICSOURCE21)
+#define IRQ_VICSOURCE22 (IRQ_VIC_START + INT_VICSOURCE22)
+#define IRQ_VICSOURCE23 (IRQ_VIC_START + INT_VICSOURCE23)
+#define IRQ_VICSOURCE24 (IRQ_VIC_START + INT_VICSOURCE24)
+#define IRQ_VICSOURCE25 (IRQ_VIC_START + INT_VICSOURCE25)
+#define IRQ_VICSOURCE26 (IRQ_VIC_START + INT_VICSOURCE26)
+#define IRQ_VICSOURCE27 (IRQ_VIC_START + INT_VICSOURCE27)
+#define IRQ_VICSOURCE28 (IRQ_VIC_START + INT_VICSOURCE28)
+#define IRQ_VICSOURCE29 (IRQ_VIC_START + INT_VICSOURCE29)
+#define IRQ_VICSOURCE30 (IRQ_VIC_START + INT_VICSOURCE30)
+#define IRQ_VICSOURCE31 (IRQ_VIC_START + INT_VICSOURCE31)
+#define IRQ_VIC_END (IRQ_VIC_START + 31)
+
+#define IRQMASK_WDOGINT INTMASK_WDOGINT
+#define IRQMASK_SOFTINT INTMASK_SOFTINT
+#define IRQMASK_COMMRx INTMASK_COMMRx
+#define IRQMASK_COMMTx INTMASK_COMMTx
+#define IRQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1
+#define IRQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3
+#define IRQMASK_GPIOINT0 INTMASK_GPIOINT0
+#define IRQMASK_GPIOINT1 INTMASK_GPIOINT1
+#define IRQMASK_GPIOINT2 INTMASK_GPIOINT2
+#define IRQMASK_GPIOINT3 INTMASK_GPIOINT3
+#define IRQMASK_RTCINT INTMASK_RTCINT
+#define IRQMASK_SSPINT INTMASK_SSPINT
+#define IRQMASK_UARTINT0 INTMASK_UARTINT0
+#define IRQMASK_UARTINT1 INTMASK_UARTINT1
+#define IRQMASK_UARTINT2 INTMASK_UARTINT2
+#define IRQMASK_SCIINT INTMASK_SCIINT
+#define IRQMASK_CLCDINT INTMASK_CLCDINT
+#define IRQMASK_DMAINT INTMASK_DMAINT
+#define IRQMASK_PWRFAILINT INTMASK_PWRFAILINT
+#define IRQMASK_MBXINT INTMASK_MBXINT
+#define IRQMASK_GNDINT INTMASK_GNDINT
+#define IRQMASK_VICSOURCE21 INTMASK_VICSOURCE21
+#define IRQMASK_VICSOURCE22 INTMASK_VICSOURCE22
+#define IRQMASK_VICSOURCE23 INTMASK_VICSOURCE23
+#define IRQMASK_VICSOURCE24 INTMASK_VICSOURCE24
+#define IRQMASK_VICSOURCE25 INTMASK_VICSOURCE25
+#define IRQMASK_VICSOURCE26 INTMASK_VICSOURCE26
+#define IRQMASK_VICSOURCE27 INTMASK_VICSOURCE27
+#define IRQMASK_VICSOURCE28 INTMASK_VICSOURCE28
+#define IRQMASK_VICSOURCE29 INTMASK_VICSOURCE29
+#define IRQMASK_VICSOURCE30 INTMASK_VICSOURCE30
+#define IRQMASK_VICSOURCE31 INTMASK_VICSOURCE31
+
+/*
+ * FIQ interrupts definitions are the same the INT definitions.
+ */
+#define FIQ_WDOGINT INT_WDOGINT
+#define FIQ_SOFTINT INT_SOFTINT
+#define FIQ_COMMRx INT_COMMRx
+#define FIQ_COMMTx INT_COMMTx
+#define FIQ_TIMERINT0_1 INT_TIMERINT0_1
+#define FIQ_TIMERINT2_3 INT_TIMERINT2_3
+#define FIQ_GPIOINT0 INT_GPIOINT0
+#define FIQ_GPIOINT1 INT_GPIOINT1
+#define FIQ_GPIOINT2 INT_GPIOINT2
+#define FIQ_GPIOINT3 INT_GPIOINT3
+#define FIQ_RTCINT INT_RTCINT
+#define FIQ_SSPINT INT_SSPINT
+#define FIQ_UARTINT0 INT_UARTINT0
+#define FIQ_UARTINT1 INT_UARTINT1
+#define FIQ_UARTINT2 INT_UARTINT2
+#define FIQ_SCIINT INT_SCIINT
+#define FIQ_CLCDINT INT_CLCDINT
+#define FIQ_DMAINT INT_DMAINT
+#define FIQ_PWRFAILINT INT_PWRFAILINT
+#define FIQ_MBXINT INT_MBXINT
+#define FIQ_GNDINT INT_GNDINT
+#define FIQ_VICSOURCE21 INT_VICSOURCE21
+#define FIQ_VICSOURCE22 INT_VICSOURCE22
+#define FIQ_VICSOURCE23 INT_VICSOURCE23
+#define FIQ_VICSOURCE24 INT_VICSOURCE24
+#define FIQ_VICSOURCE25 INT_VICSOURCE25
+#define FIQ_VICSOURCE26 INT_VICSOURCE26
+#define FIQ_VICSOURCE27 INT_VICSOURCE27
+#define FIQ_VICSOURCE28 INT_VICSOURCE28
+#define FIQ_VICSOURCE29 INT_VICSOURCE29
+#define FIQ_VICSOURCE30 INT_VICSOURCE30
+#define FIQ_VICSOURCE31 INT_VICSOURCE31
+
+
+#define FIQMASK_WDOGINT INTMASK_WDOGINT
+#define FIQMASK_SOFTINT INTMASK_SOFTINT
+#define FIQMASK_COMMRx INTMASK_COMMRx
+#define FIQMASK_COMMTx INTMASK_COMMTx
+#define FIQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1
+#define FIQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3
+#define FIQMASK_GPIOINT0 INTMASK_GPIOINT0
+#define FIQMASK_GPIOINT1 INTMASK_GPIOINT1
+#define FIQMASK_GPIOINT2 INTMASK_GPIOINT2
+#define FIQMASK_GPIOINT3 INTMASK_GPIOINT3
+#define FIQMASK_RTCINT INTMASK_RTCINT
+#define FIQMASK_SSPINT INTMASK_SSPINT
+#define FIQMASK_UARTINT0 INTMASK_UARTINT0
+#define FIQMASK_UARTINT1 INTMASK_UARTINT1
+#define FIQMASK_UARTINT2 INTMASK_UARTINT2
+#define FIQMASK_SCIINT INTMASK_SCIINT
+#define FIQMASK_CLCDINT INTMASK_CLCDINT
+#define FIQMASK_DMAINT INTMASK_DMAINT
+#define FIQMASK_PWRFAILINT INTMASK_PWRFAILINT
+#define FIQMASK_MBXINT INTMASK_MBXINT
+#define FIQMASK_GNDINT INTMASK_GNDINT
+#define FIQMASK_VICSOURCE21 INTMASK_VICSOURCE21
+#define FIQMASK_VICSOURCE22 INTMASK_VICSOURCE22
+#define FIQMASK_VICSOURCE23 INTMASK_VICSOURCE23
+#define FIQMASK_VICSOURCE24 INTMASK_VICSOURCE24
+#define FIQMASK_VICSOURCE25 INTMASK_VICSOURCE25
+#define FIQMASK_VICSOURCE26 INTMASK_VICSOURCE26
+#define FIQMASK_VICSOURCE27 INTMASK_VICSOURCE27
+#define FIQMASK_VICSOURCE28 INTMASK_VICSOURCE28
+#define FIQMASK_VICSOURCE29 INTMASK_VICSOURCE29
+#define FIQMASK_VICSOURCE30 INTMASK_VICSOURCE30
+#define FIQMASK_VICSOURCE31 INTMASK_VICSOURCE31
+
+/*
+ * Secondary interrupt controller
+ */
+#define IRQ_SIC_START 32
+#define IRQ_SIC_MMCI0B (IRQ_SIC_START + SIC_INT_MMCI0B)
+#define IRQ_SIC_MMCI1B (IRQ_SIC_START + SIC_INT_MMCI1B)
+#define IRQ_SIC_KMI0 (IRQ_SIC_START + SIC_INT_KMI0)
+#define IRQ_SIC_KMI1 (IRQ_SIC_START + SIC_INT_KMI1)
+#define IRQ_SIC_SCI3 (IRQ_SIC_START + SIC_INT_SCI3)
+#define IRQ_SIC_UART3 (IRQ_SIC_START + SIC_INT_UART3)
+#define IRQ_SIC_CLCD (IRQ_SIC_START + SIC_INT_CLCD)
+#define IRQ_SIC_TOUCH (IRQ_SIC_START + SIC_INT_TOUCH)
+#define IRQ_SIC_KEYPAD (IRQ_SIC_START + SIC_INT_KEYPAD)
+#define IRQ_SIC_DoC (IRQ_SIC_START + SIC_INT_DoC)
+#define IRQ_SIC_MMCI0A (IRQ_SIC_START + SIC_INT_MMCI0A)
+#define IRQ_SIC_MMCI1A (IRQ_SIC_START + SIC_INT_MMCI1A)
+#define IRQ_SIC_AACI (IRQ_SIC_START + SIC_INT_AACI)
+#define IRQ_SIC_ETH (IRQ_SIC_START + SIC_INT_ETH)
+#define IRQ_SIC_USB (IRQ_SIC_START + SIC_INT_USB)
+#define IRQ_SIC_PCI0 (IRQ_SIC_START + SIC_INT_PCI0)
+#define IRQ_SIC_PCI1 (IRQ_SIC_START + SIC_INT_PCI1)
+#define IRQ_SIC_PCI2 (IRQ_SIC_START + SIC_INT_PCI2)
+#define IRQ_SIC_PCI3 (IRQ_SIC_START + SIC_INT_PCI3)
+#define IRQ_SIC_END 63
+
+#define SIC_IRQMASK_MMCI0B SIC_INTMASK_MMCI0B
+#define SIC_IRQMASK_MMCI1B SIC_INTMASK_MMCI1B
+#define SIC_IRQMASK_KMI0 SIC_INTMASK_KMI0
+#define SIC_IRQMASK_KMI1 SIC_INTMASK_KMI1
+#define SIC_IRQMASK_SCI3 SIC_INTMASK_SCI3
+#define SIC_IRQMASK_UART3 SIC_INTMASK_UART3
+#define SIC_IRQMASK_CLCD SIC_INTMASK_CLCD
+#define SIC_IRQMASK_TOUCH SIC_INTMASK_TOUCH
+#define SIC_IRQMASK_KEYPAD SIC_INTMASK_KEYPAD
+#define SIC_IRQMASK_DoC SIC_INTMASK_DoC
+#define SIC_IRQMASK_MMCI0A SIC_INTMASK_MMCI0A
+#define SIC_IRQMASK_MMCI1A SIC_INTMASK_MMCI1A
+#define SIC_IRQMASK_AACI SIC_INTMASK_AACI
+#define SIC_IRQMASK_ETH SIC_INTMASK_ETH
+#define SIC_IRQMASK_USB SIC_INTMASK_USB
+#define SIC_IRQMASK_PCI0 SIC_INTMASK_PCI0
+#define SIC_IRQMASK_PCI1 SIC_INTMASK_PCI1
+#define SIC_IRQMASK_PCI2 SIC_INTMASK_PCI2
+#define SIC_IRQMASK_PCI3 SIC_INTMASK_PCI3
+
+#define NR_IRQS 64
diff --git a/include/asm-arm/arch-versatile/memory.h b/include/asm-arm/arch-versatile/memory.h
new file mode 100644
index 000000000000..4b7295b4a89a
--- /dev/null
+++ b/include/asm-arm/arch-versatile/memory.h
@@ -0,0 +1,61 @@
+/*
+ * linux/include/asm-arm/arch-versatile/memory.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xbf000000UL)
+#define TASK_SIZE_26 (0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (0x40000000)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+#define PHYS_OFFSET (0x00000000UL)
+
+/*
+ * On Versatile PB, the dram is contiguous
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
+
+#endif
diff --git a/include/asm-arm/arch-versatile/param.h b/include/asm-arm/arch-versatile/param.h
new file mode 100644
index 000000000000..34b897335f87
--- /dev/null
+++ b/include/asm-arm/arch-versatile/param.h
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-versatile/param.h
+ *
+ * Copyright (C) 2002 ARM Limited
+ *
+ * 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
+ */
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
new file mode 100644
index 000000000000..68be3f036600
--- /dev/null
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -0,0 +1,488 @@
+/*
+ * linux/include/asm-arm/arch-versatile/platform.h
+ *
+ * Copyright (c) ARM Limited 2003. All rights reserved.
+ *
+ * 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
+ */
+
+#ifndef __address_h
+#define __address_h 1
+
+/*
+ * Memory definitions
+ */
+#define VERSATILE_BOOT_ROM_LO 0x30000000 /* DoC Base (64Mb)...*/
+#define VERSATILE_BOOT_ROM_HI 0x30000000
+#define VERSATILE_BOOT_ROM_BASE VERSATILE_BOOT_ROM_HI /* Normal position */
+#define VERSATILE_BOOT_ROM_SIZE SZ_64M
+
+#define VERSATILE_SSRAM_BASE /* VERSATILE_SSMC_BASE ? */
+#define VERSATILE_SSRAM_SIZE SZ_2M
+
+#define VERSATILE_FLASH_BASE 0x34000000
+#define VERSATILE_FLASH_SIZE SZ_64M
+
+/*
+ * SDRAM
+ */
+#define VERSATILE_SDRAM_BASE 0x00000000
+
+/*
+ * Logic expansion modules
+ *
+ */
+
+
+/* ------------------------------------------------------------------------
+ * Versatile PB Registers
+ * ------------------------------------------------------------------------
+ *
+ */
+#define VERSATILE_SYS_ID_OFFSET 0x00
+#define VERSATILE_SYS_SW_OFFSET 0x04
+#define VERSATILE_SYS_LED_OFFSET 0x08
+#define VERSATILE_SYS_OSC0_OFFSET 0x0C
+#define VERSATILE_SYS_OSC1_OFFSET 0x10
+#define VERSATILE_SYS_OSC2_OFFSET 0x14
+#define VERSATILE_SYS_OSC3_OFFSET 0x18
+#define VERSATILE_SYS_OSC4_OFFSET 0x1C
+#define VERSATILE_SYS_LOCK_OFFSET 0x20
+#define VERSATILE_SYS_100HZ_OFFSET 0x24
+#define VERSATILE_SYS_CFGDATA1_OFFSET 0x28
+#define VERSATILE_SYS_CFGDATA2_OFFSET 0x2C
+#define VERSATILE_SYS_FLAGS_OFFSET 0x30
+#define VERSATILE_SYS_FLAGSSET_OFFSET 0x30
+#define VERSATILE_SYS_FLAGSCLR_OFFSET 0x34
+#define VERSATILE_SYS_NVFLAGS_OFFSET 0x38
+#define VERSATILE_SYS_NVFLAGSSET_OFFSET 0x38
+#define VERSATILE_SYS_NVFLAGSCLR_OFFSET 0x3C
+#define VERSATILE_SYS_RESETCTL_OFFSET 0x40
+#define VERSATILE_SYS_PICCTL_OFFSET 0x44
+#define VERSATILE_SYS_MCI_OFFSET 0x48
+#define VERSATILE_SYS_FLASH_OFFSET 0x4C
+#define VERSATILE_SYS_CLCD_OFFSET 0x50
+#define VERSATILE_SYS_CLCDSER_OFFSET 0x54
+#define VERSATILE_SYS_BOOTCS_OFFSET 0x58
+#define VERSATILE_SYS_24MHz_OFFSET 0x5C
+#define VERSATILE_SYS_MISC_OFFSET 0x60
+#define VERSATILE_SYS_TEST_OSC0_OFFSET 0x80
+#define VERSATILE_SYS_TEST_OSC1_OFFSET 0x84
+#define VERSATILE_SYS_TEST_OSC2_OFFSET 0x88
+#define VERSATILE_SYS_TEST_OSC3_OFFSET 0x8C
+#define VERSATILE_SYS_TEST_OSC4_OFFSET 0x90
+
+#define VERSATILE_SYS_BASE 0x10000000
+#define VERSATILE_SYS_ID (VERSATILE_SYS_BASE + VERSATILE_SYS_ID_OFFSET)
+#define VERSATILE_SYS_SW (VERSATILE_SYS_BASE + VERSATILE_SYS_SW_OFFSET)
+#define VERSATILE_SYS_LED (VERSATILE_SYS_BASE + VERSATILE_SYS_LED_OFFSET)
+#define VERSATILE_SYS_OSC0 (VERSATILE_SYS_BASE + VERSATILE_SYS_OSC0_OFFSET)
+#define VERSATILE_SYS_OSC1 (VERSATILE_SYS_BASE + VERSATILE_SYS_OSC1_OFFSET)
+#define VERSATILE_SYS_OSC2 (VERSATILE_SYS_BASE + VERSATILE_SYS_OSC2_OFFSET)
+#define VERSATILE_SYS_OSC3 (VERSATILE_SYS_BASE + VERSATILE_SYS_OSC3_OFFSET)
+#define VERSATILE_SYS_OSC4 (VERSATILE_SYS_BASE + VERSATILE_SYS_OSC4_OFFSET)
+#define VERSATILE_SYS_LOCK (VERSATILE_SYS_BASE + VERSATILE_SYS_LOCK_OFFSET)
+#define VERSATILE_SYS_100HZ (VERSATILE_SYS_BASE + VERSATILE_SYS_100HZ_OFFSET)
+#define VERSATILE_SYS_CFGDATA1 (VERSATILE_SYS_BASE + VERSATILE_SYS_CFGDATA1_OFFSET)
+#define VERSATILE_SYS_CFGDATA2 (VERSATILE_SYS_BASE + VERSATILE_SYS_CFGDATA2_OFFSET)
+#define VERSATILE_SYS_FLAGS (VERSATILE_SYS_BASE + VERSATILE_SYS_FLAGS_OFFSET)
+#define VERSATILE_SYS_FLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_FLAGSSET_OFFSET)
+#define VERSATILE_SYS_FLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_FLAGSCLR_OFFSET)
+#define VERSATILE_SYS_NVFLAGS (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGS_OFFSET)
+#define VERSATILE_SYS_NVFLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
+#define VERSATILE_SYS_NVFLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
+#define VERSATILE_SYS_RESETCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
+#define VERSATILE_SYS_PICCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
+#define VERSATILE_SYS_MCI (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
+#define VERSATILE_SYS_FLASH (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
+#define VERSATILE_SYS_CLCD (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
+#define VERSATILE_SYS_CLCDSER (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCDSER_OFFSET)
+#define VERSATILE_SYS_BOOTCS (VERSATILE_SYS_BASE + VERSATILE_SYS_BOOTCS_OFFSET)
+#define VERSATILE_SYS_24MHz (VERSATILE_SYS_BASE + VERSATILE_SYS_24MHz_OFFSET)
+#define VERSATILE_SYS_MISC (VERSATILE_SYS_BASE + VERSATILE_SYS_MISC_OFFSET)
+#define VERSATILE_SYS_TEST_OSC0 (VERSATILE_SYS_BASE + VERSATILE_SYS_TEST_OSC0_OFFSET)
+#define VERSATILE_SYS_TEST_OSC1 (VERSATILE_SYS_BASE + VERSATILE_SYS_TEST_OSC1_OFFSET)
+#define VERSATILE_SYS_TEST_OSC2 (VERSATILE_SYS_BASE + VERSATILE_SYS_TEST_OSC2_OFFSET)
+#define VERSATILE_SYS_TEST_OSC3 (VERSATILE_SYS_BASE + VERSATILE_SYS_TEST_OSC3_OFFSET)
+#define VERSATILE_SYS_TEST_OSC4 (VERSATILE_SYS_BASE + VERSATILE_SYS_TEST_OSC4_OFFSET)
+
+/*
+ * Values for VERSATILE_SYS_RESET_CTRL
+ */
+#define VERSATILE_SYS_CTRL_RESET_CONFIGCLR 0x01
+#define VERSATILE_SYS_CTRL_RESET_CONFIGINIT 0x02
+#define VERSATILE_SYS_CTRL_RESET_DLLRESET 0x03
+#define VERSATILE_SYS_CTRL_RESET_PLLRESET 0x04
+#define VERSATILE_SYS_CTRL_RESET_POR 0x05
+#define VERSATILE_SYS_CTRL_RESET_DoC 0x06
+
+#define VERSATILE_SYS_CTRL_LED (1 << 0)
+
+
+/* ------------------------------------------------------------------------
+ * Versatile PB control registers
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * VERSATILE_IDFIELD
+ *
+ * 31:24 = manufacturer (0x41 = ARM)
+ * 23:16 = architecture (0x08 = AHB system bus, ASB processor bus)
+ * 15:12 = FPGA (0x3 = XVC600 or XVC600E)
+ * 11:4 = build value
+ * 3:0 = revision number (0x1 = rev B (AHB))
+ */
+
+/*
+ * VERSATILE_SYS_LOCK
+ * control access to SYS_OSCx, SYS_CFGDATAx, SYS_RESETCTL,
+ * SYS_CLD, SYS_BOOTCS
+ */
+#define VERSATILE_SYS_LOCK_LOCKED (1 << 16)
+#define VERSATILE_SYS_LOCKVAL_MASK 0xFFFF /* write 0xA05F to enable write access */
+
+/*
+ * VERSATILE_SYS_FLASH
+ */
+#define VERSATILE_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */
+
+/*
+ * VERSATILE_INTREG
+ * - used to acknowledge and control MMCI and UART interrupts
+ */
+#define VERSATILE_INTREG_WPROT 0x00 /* MMC protection status (no interrupt generated) */
+#define VERSATILE_INTREG_RI0 0x01 /* Ring indicator UART0 is asserted, */
+#define VERSATILE_INTREG_CARDIN 0x08 /* MMCI card in detect */
+ /* write 1 to acknowledge and clear */
+#define VERSATILE_INTREG_RI1 0x02 /* Ring indicator UART1 is asserted, */
+#define VERSATILE_INTREG_CARDINSERT 0x03 /* Signal insertion of MMC card */
+
+/*
+ * VERSATILE peripheral addresses
+ */
+#define VERSATILE_PCI_CORE_BASE 0x10001000 /* PCI core control */
+#define VERSATILE_I2C_BASE 0x10002000 /* I2C control */
+#define VERSATILE_SIC_BASE 0x10003000 /* Secondary interrupt controller */
+#define VERSATILE_AACI_BASE 0x10004000 /* Audio */
+#define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
+#define VERSATILE_KMI0_BASE 0x10006000 /* KMI interface */
+#define VERSATILE_KMI1_BASE 0x10007000 /* KMI 2nd interface */
+#define VERSATILE_CHAR_LCD_BASE 0x10008000 /* Character LCD */
+#define VERSATILE_UART3_BASE 0x10009000 /* UART 3 */
+#define VERSATILE_SCI1_BASE 0x1000A000
+#define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
+ /* 0x1000C000 - 0x1000CFFF = reserved */
+#define VERSATILE_ETH_BASE 0x10010000 /* Ethernet */
+#define VERSATILE_USB_BASE 0x10020000 /* USB */
+ /* 0x10030000 - 0x100FFFFF = reserved */
+#define VERSATILE_SMC_BASE 0x10100000 /* SMC */
+#define VERSATILE_MPMC_BASE 0x10110000 /* MPMC */
+#define VERSATILE_CLCD_BASE 0x10120000 /* CLCD */
+#define VERSATILE_DMAC_BASE 0x10130000 /* DMA controller */
+#define VERSATILE_VIC_BASE 0x10140000 /* Vectored interrupt controller */
+#define VERSATILE_PERIPH_BASE 0x10150000 /* off-chip peripherals alias from */
+ /* 0x10000000 - 0x100FFFFF */
+#define VERSATILE_AHBM_BASE 0x101D0000 /* AHB monitor */
+#define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
+#define VERSATILE_WATCHDOG_BASE 0x101E1000 /* Watchdog */
+#define VERSATILE_TIMER0_1_BASE 0x101E2000 /* Timer 0 and 1 */
+#define VERSATILE_TIMER2_3_BASE 0x101E3000 /* Timer 2 and 3 */
+#define VERSATILE_GPIO0_BASE 0x101E4000 /* GPIO port 0 */
+#define VERSATILE_GPIO1_BASE 0x101E5000 /* GPIO port 1 */
+#define VERSATILE_GPIO2_BASE 0x101E6000 /* GPIO port 2 */
+#define VERSATILE_GPIO3_BASE 0x101E7000 /* GPIO port 3 */
+#define VERSATILE_RTC_BASE 0x101E8000 /* Real Time Clock */
+ /* 0x101E9000 - reserved */
+#define VERSATILE_SCI_BASE 0x101F0000 /* Smart card controller */
+#define VERSATILE_UART0_BASE 0x101F1000 /* Uart 0 */
+#define VERSATILE_UART1_BASE 0x101F2000 /* Uart 1 */
+#define VERSATILE_UART2_BASE 0x101F3000 /* Uart 2 */
+#define VERSATILE_SSP_BASE 0x101F4000 /* Synchronous Serial Port */
+
+#define VERSATILE_SSMC_BASE 0x20000000 /* SSMC */
+#define VERSATILE_MBX_BASE 0x40000000 /* MBX */
+#define VERSATILE_PCI_BASE 0x41000000 /* PCI Interface */
+#define VERSATILE_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */
+#define VERSATILE_LT_BASE 0x80000000 /* Logic Tile expansion */
+
+/*
+ * Disk on Chip
+ */
+#define VERSATILE_DOC_BASE 0x2C000000
+#define VERSATILE_DOC_SIZE (16 << 20)
+#define VERSATILE_DOC_PAGE_SIZE 512
+#define VERSATILE_DOC_TOTAL_PAGES (DOC_SIZE / PAGE_SIZE)
+
+#define ERASE_UNIT_PAGES 32
+#define START_PAGE 0x80
+
+/*
+ * LED settings, bits [7:0]
+ */
+#define VERSATILE_SYS_LED0 (1 << 0)
+#define VERSATILE_SYS_LED1 (1 << 1)
+#define VERSATILE_SYS_LED2 (1 << 2)
+#define VERSATILE_SYS_LED3 (1 << 3)
+#define VERSATILE_SYS_LED4 (1 << 4)
+#define VERSATILE_SYS_LED5 (1 << 5)
+#define VERSATILE_SYS_LED6 (1 << 6)
+#define VERSATILE_SYS_LED7 (1 << 7)
+
+#define ALL_LEDS 0xFF
+
+#define LED_BANK VERSATILE_SYS_LED
+
+/*
+ * Control registers
+ */
+#define VERSATILE_IDFIELD_OFFSET 0x0 /* Versatile build information */
+#define VERSATILE_FLASHPROG_OFFSET 0x4 /* Flash devices */
+#define VERSATILE_INTREG_OFFSET 0x8 /* Interrupt control */
+#define VERSATILE_DECODE_OFFSET 0xC /* Fitted logic modules */
+
+
+/* ------------------------------------------------------------------------
+ * Versatile PB Interrupt Controller - control registers
+ * ------------------------------------------------------------------------
+ *
+ * Offsets from interrupt controller base
+ *
+ * System Controller interrupt controller base is
+ *
+ * VERSATILE_IC_BASE
+ *
+ * Core Module interrupt controller base is
+ *
+ * VERSATILE_SYS_IC
+ *
+ */
+#define VIC_IRQ_STATUS 0
+#define VIC_FIQ_STATUS 0x04
+#define VIC_IRQ_RAW_STATUS 0x08
+#define VIC_INT_SELECT 0x0C /* 1 = FIQ, 0 = IRQ */
+#define VIC_IRQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
+#define VIC_IRQ_ENABLE_CLEAR 0x14
+#define VIC_IRQ_SOFT 0x18
+#define VIC_IRQ_SOFT_CLEAR 0x1C
+#define VIC_PROTECT 0x20
+#define VIC_VECT_ADDR 0x30
+#define VIC_DEF_VECT_ADDR 0x34
+#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */
+#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */
+#define VIC_ITCR 0x300 /* VIC test control register */
+
+#define VIC_FIQ_RAW_STATUS 0x08
+#define VIC_FIQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
+#define VIC_FIQ_ENABLE_CLEAR 0x14
+#define VIC_FIQ_SOFT 0x18
+#define VIC_FIQ_SOFT_CLEAR 0x1C
+
+#define SIC_IRQ_STATUS 0
+#define SIC_IRQ_RAW_STATUS 0x04
+#define SIC_IRQ_ENABLE 0x08
+#define SIC_IRQ_ENABLE_SET 0x08
+#define SIC_IRQ_ENABLE_CLEAR 0x0C
+#define SIC_INT_SOFT_SET 0x10
+#define SIC_INT_SOFT_CLEAR 0x14
+#define SIC_INT_PIC_ENABLE 0x20 /* read status of pass through mask */
+#define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */
+#define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */
+
+#define VICVectCntl_Enable (1 << 5)
+
+/* ------------------------------------------------------------------------
+ * Interrupts - bit assignment (primary)
+ * ------------------------------------------------------------------------
+ */
+
+#define INT_WDOGINT 0 /* Watchdog timer */
+#define INT_SOFTINT 1 /* Software interrupt */
+#define INT_COMMRx 2 /* Debug Comm Rx interrupt */
+#define INT_COMMTx 3 /* Debug Comm Tx interrupt */
+#define INT_TIMERINT0_1 4 /* Timer 0 and 1 */
+#define INT_TIMERINT2_3 5 /* Timer 2 and 3 */
+#define INT_GPIOINT0 6 /* GPIO 0 */
+#define INT_GPIOINT1 7 /* GPIO 1 */
+#define INT_GPIOINT2 8 /* GPIO 2 */
+#define INT_GPIOINT3 9 /* GPIO 3 */
+#define INT_RTCINT 10 /* Real Time Clock */
+#define INT_SSPINT 11 /* Synchronous Serial Port */
+#define INT_UARTINT0 12 /* UART 0 on development chip */
+#define INT_UARTINT1 13 /* UART 1 on development chip */
+#define INT_UARTINT2 14 /* UART 2 on development chip */
+#define INT_SCIINT 15 /* Smart Card Interface */
+#define INT_CLCDINT 16 /* CLCD controller */
+#define INT_DMAINT 17 /* DMA controller */
+#define INT_PWRFAILINT 18 /* Power failure */
+#define INT_MBXINT 19 /* Graphics processor */
+#define INT_GNDINT 20 /* Reserved */
+ /* External interrupt signals from logic tiles or secondary controller */
+#define INT_VICSOURCE21 21 /* Disk on Chip */
+#define INT_VICSOURCE22 22 /* MCI0A */
+#define INT_VICSOURCE23 23 /* MCI1A */
+#define INT_VICSOURCE24 24 /* AACI */
+#define INT_VICSOURCE25 25 /* Ethernet */
+#define INT_VICSOURCE26 26 /* USB */
+#define INT_VICSOURCE27 27 /* PCI 0 */
+#define INT_VICSOURCE28 28 /* PCI 1 */
+#define INT_VICSOURCE29 29 /* PCI 2 */
+#define INT_VICSOURCE30 30 /* PCI 3 */
+#define INT_VICSOURCE31 31 /* SIC source */
+
+/*
+ * Interrupt bit positions
+ *
+ */
+#define INTMASK_WDOGINT (1 << INT_WDOGINT)
+#define INTMASK_SOFTINT (1 << INT_SOFTINT)
+#define INTMASK_COMMRx (1 << INT_COMMRx)
+#define INTMASK_COMMTx (1 << INT_COMMTx)
+#define INTMASK_TIMERINT0_1 (1 << INT_TIMERINT0_1)
+#define INTMASK_TIMERINT2_3 (1 << INT_TIMERINT2_3)
+#define INTMASK_GPIOINT0 (1 << INT_GPIOINT0)
+#define INTMASK_GPIOINT1 (1 << INT_GPIOINT1)
+#define INTMASK_GPIOINT2 (1 << INT_GPIOINT2)
+#define INTMASK_GPIOINT3 (1 << INT_GPIOINT3)
+#define INTMASK_RTCINT (1 << INT_RTCINT)
+#define INTMASK_SSPINT (1 << INT_SSPINT)
+#define INTMASK_UARTINT0 (1 << INT_UARTINT0)
+#define INTMASK_UARTINT1 (1 << INT_UARTINT1)
+#define INTMASK_UARTINT2 (1 << INT_UARTINT2)
+#define INTMASK_SCIINT (1 << INT_SCIINT)
+#define INTMASK_CLCDINT (1 << INT_CLCDINT)
+#define INTMASK_DMAINT (1 << INT_DMAINT)
+#define INTMASK_PWRFAILINT (1 << INT_PWRFAILINT)
+#define INTMASK_MBXINT (1 << INT_MBXINT)
+#define INTMASK_GNDINT (1 << INT_GNDINT)
+#define INTMASK_VICSOURCE21 (1 << INT_VICSOURCE21)
+#define INTMASK_VICSOURCE22 (1 << INT_VICSOURCE22)
+#define INTMASK_VICSOURCE23 (1 << INT_VICSOURCE23)
+#define INTMASK_VICSOURCE24 (1 << INT_VICSOURCE24)
+#define INTMASK_VICSOURCE25 (1 << INT_VICSOURCE25)
+#define INTMASK_VICSOURCE26 (1 << INT_VICSOURCE26)
+#define INTMASK_VICSOURCE27 (1 << INT_VICSOURCE27)
+#define INTMASK_VICSOURCE28 (1 << INT_VICSOURCE28)
+#define INTMASK_VICSOURCE29 (1 << INT_VICSOURCE29)
+#define INTMASK_VICSOURCE30 (1 << INT_VICSOURCE30)
+#define INTMASK_VICSOURCE31 (1 << INT_VICSOURCE31)
+
+
+#define VERSATILE_SC_VALID_INT 0x003FFFFF
+
+#define MAXIRQNUM 31
+#define MAXFIQNUM 31
+#define MAXSWINUM 31
+
+/* ------------------------------------------------------------------------
+ * Interrupts - bit assignment (secondary)
+ * ------------------------------------------------------------------------
+ */
+#define SIC_INT_MMCI0B 1 /* Multimedia Card 0B */
+#define SIC_INT_MMCI1B 2 /* Multimedia Card 1B */
+#define SIC_INT_KMI0 3 /* Keyboard/Mouse port 0 */
+#define SIC_INT_KMI1 4 /* Keyboard/Mouse port 1 */
+#define SIC_INT_SCI3 5 /* Smart Card interface */
+#define SIC_INT_UART3 6 /* UART 3 empty or data available */
+#define SIC_INT_CLCD 7 /* Character LCD */
+#define SIC_INT_TOUCH 8 /* Touchscreen */
+#define SIC_INT_KEYPAD 9 /* Key pressed on display keypad */
+ /* 10:20 - reserved */
+#define SIC_INT_DoC 21 /* Disk on Chip memory controller */
+#define SIC_INT_MMCI0A 22 /* MMC 0A */
+#define SIC_INT_MMCI1A 23 /* MMC 1A */
+#define SIC_INT_AACI 24 /* Audio Codec */
+#define SIC_INT_ETH 25 /* Ethernet controller */
+#define SIC_INT_USB 26 /* USB controller */
+#define SIC_INT_PCI0 27
+#define SIC_INT_PCI1 28
+#define SIC_INT_PCI2 29
+#define SIC_INT_PCI3 30
+
+
+#define SIC_INTMASK_MMCI0B (1 << SIC_INT_MMCI0B)
+#define SIC_INTMASK_MMCI1B (1 << SIC_INT_MMCI1B)
+#define SIC_INTMASK_KMI0 (1 << SIC_INT_KMI0)
+#define SIC_INTMASK_KMI1 (1 << SIC_INT_KMI1)
+#define SIC_INTMASK_SCI3 (1 << SIC_INT_SCI3)
+#define SIC_INTMASK_UART3 (1 << SIC_INT_UART3)
+#define SIC_INTMASK_CLCD (1 << SIC_INT_CLCD)
+#define SIC_INTMASK_TOUCH (1 << SIC_INT_TOUCH)
+#define SIC_INTMASK_KEYPAD (1 << SIC_INT_KEYPAD)
+#define SIC_INTMASK_DoC (1 << SIC_INT_DoC)
+#define SIC_INTMASK_MMCI0A (1 << SIC_INT_MMCI0A)
+#define SIC_INTMASK_MMCI1A (1 << SIC_INT_MMCI1A)
+#define SIC_INTMASK_AACI (1 << SIC_INT_AACI)
+#define SIC_INTMASK_ETH (1 << SIC_INT_ETH)
+#define SIC_INTMASK_USB (1 << SIC_INT_USB)
+#define SIC_INTMASK_PCI0 (1 << SIC_INT_PCI0)
+#define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1)
+#define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2)
+#define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3)
+/*
+ * Application Flash
+ *
+ */
+#define FLASH_BASE VERSATILE_FLASH_BASE
+#define FLASH_SIZE VERSATILE_FLASH_SIZE
+#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
+#define FLASH_BLOCK_SIZE SZ_128K
+
+/*
+ * Boot Flash
+ *
+ */
+#define EPROM_BASE VERSATILE_BOOT_ROM_HI
+#define EPROM_SIZE VERSATILE_BOOT_ROM_SIZE
+#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
+
+/*
+ * Clean base - dummy
+ *
+ */
+#define CLEAN_BASE EPROM_BASE
+
+/*
+ * System controller bit assignment
+ */
+#define VERSATILE_REFCLK 0
+#define VERSATILE_TIMCLK 1
+
+#define VERSATILE_TIMER1_EnSel 15
+#define VERSATILE_TIMER2_EnSel 17
+#define VERSATILE_TIMER3_EnSel 19
+#define VERSATILE_TIMER4_EnSel 21
+
+
+#define MAX_TIMER 2
+#define MAX_PERIOD 699050
+#define TICKS_PER_uSEC 1
+
+/*
+ * These are useconds NOT ticks.
+ *
+ */
+#define mSEC_1 1000
+#define mSEC_5 (mSEC_1 * 5)
+#define mSEC_10 (mSEC_1 * 10)
+#define mSEC_25 (mSEC_1 * 25)
+#define SEC_1 (mSEC_1 * 1000)
+
+#define VERSATILE_CSR_BASE 0x10000000
+#define VERSATILE_CSR_SIZE 0x10000000
+
+#endif
+
+/* END */
diff --git a/include/asm-arm/arch-versatile/serial.h b/include/asm-arm/arch-versatile/serial.h
new file mode 100644
index 000000000000..f578f8910b3e
--- /dev/null
+++ b/include/asm-arm/arch-versatile/serial.h
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-versatile/serial.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+/*
+ * This assumes you have a 14.7456 MHz clock UART.
+ */
+#define BASE_BAUD 115200
+
+ /* UART CLK PORT IRQ FLAGS */
+#define STD_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, 0, 0, ASYNC_SKIP_TEST }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0, 0, ASYNC_SKIP_TEST }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0, 0, ASYNC_SKIP_TEST }, /* ttyS2 */ \
+ { 0, BASE_BAUD, 0, 0, ASYNC_SKIP_TEST }, /* ttyS3 */
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif
diff --git a/include/asm-arm/arch-versatile/system.h b/include/asm-arm/arch-versatile/system.h
new file mode 100644
index 000000000000..8889a189739f
--- /dev/null
+++ b/include/asm-arm/arch-versatile/system.h
@@ -0,0 +1,51 @@
+/*
+ * linux/include/asm-arm/arch-versatile/system.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+ unsigned int hdr_ctrl = (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_RESETCTL_OFFSET);
+ unsigned int val;
+
+ /*
+ * To reset, we hit the on-board reset register
+ * in the system FPGA
+ */
+ val = __raw_readl(hdr_ctrl);
+ val |= VERSATILE_SYS_CTRL_RESET_CONFIGCLR;
+ __raw_writel(val, hdr_ctrl);
+}
+
+#endif
diff --git a/include/asm-arm/arch-versatile/time.h b/include/asm-arm/arch-versatile/time.h
new file mode 100644
index 000000000000..7d97d9565a4b
--- /dev/null
+++ b/include/asm-arm/arch-versatile/time.h
@@ -0,0 +1,158 @@
+/*
+ * linux/include/asm-arm/arch-versatile/time.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <asm/system.h>
+#include <asm/leds.h>
+
+/*
+ * Where is the timer (VA)?
+ */
+#define TIMER0_VA_BASE IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
+#define TIMER1_VA_BASE (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
+#define TIMER2_VA_BASE IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
+#define TIMER3_VA_BASE (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
+#define VA_IC_BASE IO_ADDRESS(VERSATILE_VIC_BASE)
+
+/*
+ * How long is the timer interval?
+ */
+#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
+#if TIMER_INTERVAL >= 0x100000
+#define TIMER_RELOAD (TIMER_INTERVAL >> 8) /* Divide by 256 */
+#define TIMER_CTRL 0x88 /* Enable, Clock / 256 */
+#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
+#elif TIMER_INTERVAL >= 0x10000
+#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
+#define TIMER_CTRL 0x84 /* Enable, Clock / 16 */
+#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
+#else
+#define TIMER_RELOAD (TIMER_INTERVAL)
+#define TIMER_CTRL 0x80 /* Enable */
+#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
+#endif
+
+#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */
+
+/*
+ * What does it look like?
+ */
+typedef struct TimerStruct {
+ unsigned long TimerLoad;
+ unsigned long TimerValue;
+ unsigned long TimerControl;
+ unsigned long TimerClear;
+} TimerStruct_t;
+
+extern unsigned long (*gettimeoffset)(void);
+
+/*
+ * Returns number of ms since last clock interrupt. Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long versatile_gettimeoffset(void)
+{
+ volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
+ unsigned long ticks1, ticks2, status;
+
+ /*
+ * Get the current number of ticks. Note that there is a race
+ * condition between us reading the timer and checking for
+ * an interrupt. We get around this by ensuring that the
+ * counter has not reloaded between our two reads.
+ */
+ ticks2 = timer0->TimerValue & 0xffff;
+ do {
+ ticks1 = ticks2;
+ status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
+ ticks2 = timer0->TimerValue & 0xffff;
+ } while (ticks2 > ticks1);
+
+ /*
+ * Number of ticks since last interrupt.
+ */
+ ticks1 = TIMER_RELOAD - ticks2;
+
+ /*
+ * Interrupt pending? If so, we've reloaded once already.
+ *
+ * FIXME: Need to check this is effectively timer 0 that expires
+ */
+ if (status & IRQMASK_TIMERINT0_1)
+ ticks1 += TIMER_RELOAD;
+
+ /*
+ * Convert the ticks to usecs
+ */
+ return TICKS2USECS(ticks1);
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+
+ // ...clear the interrupt
+ timer0->TimerClear = 1;
+
+ do_leds();
+ do_timer(regs);
+ do_profile(regs);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init time_init(void)
+{
+ volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+ volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
+ volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
+ volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
+
+ /*
+ * set clock frequency:
+ * VERSATILE_REFCLK is 32KHz
+ * VERSATILE_TIMCLK is 1MHz
+ */
+ *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |=
+ ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) |
+ (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
+
+ timer_irq.handler = versatile_timer_interrupt;
+
+ /*
+ * Initialise to a known state (all timers off)
+ */
+ timer0->TimerControl = 0;
+ timer1->TimerControl = 0;
+ timer2->TimerControl = 0;
+ timer3->TimerControl = 0;
+
+ timer0->TimerLoad = TIMER_RELOAD;
+ timer0->TimerValue = TIMER_RELOAD;
+ timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */
+
+ /*
+ * Make irqs happen for the system timer
+ */
+ setup_irq(IRQ_TIMERINT0_1, &timer_irq);
+ gettimeoffset = versatile_gettimeoffset;
+}
diff --git a/include/asm-arm/arch-versatile/timex.h b/include/asm-arm/arch-versatile/timex.h
new file mode 100644
index 000000000000..61da0c6ab38a
--- /dev/null
+++ b/include/asm-arm/arch-versatile/timex.h
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-versatile/timex.h
+ *
+ * Versatile PB architecture timex specifications
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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
+ */
+
+#define CLOCK_TICK_RATE (50000000 / 16)
diff --git a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h
new file mode 100644
index 000000000000..148ad3755abf
--- /dev/null
+++ b/include/asm-arm/arch-versatile/uncompress.h
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-arm/arch-versatile/uncompress.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+
+#define AMBA_UART_DR (*(volatile unsigned char *)0x101F1000)
+#define AMBA_UART_LCRH (*(volatile unsigned char *)0x101F102C)
+#define AMBA_UART_CR (*(volatile unsigned char *)0x101F1030)
+#define AMBA_UART_FR (*(volatile unsigned char *)0x101F1018)
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+ while (*s) {
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
+
+ AMBA_UART_DR = *s;
+
+ if (*s == '\n') {
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
+
+ AMBA_UART_DR = '\r';
+ }
+ s++;
+ }
+ while (AMBA_UART_FR & (1 << 3))
+ barrier();
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-versatile/vmalloc.h b/include/asm-arm/arch-versatile/vmalloc.h
new file mode 100644
index 000000000000..adfb34829bfc
--- /dev/null
+++ b/include/asm-arm/arch-versatile/vmalloc.h
@@ -0,0 +1,33 @@
+/*
+ * linux/include/asm-arm/arch-versatile/vmalloc.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ * Copyright (C) 2000 Russell King.
+ *
+ * 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
+ */
+
+/*
+ * 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
+ * physical memory until the kernel virtual memory starts. That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END (PAGE_OFFSET + 0x18000000)
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 8ae0be984492..7fb3046c6729 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -212,6 +212,8 @@ extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
extern int _find_first_zero_bit_le(void * p, unsigned size);
extern int _find_next_zero_bit_le(void * p, int size, int offset);
+extern int _find_first_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
/*
* Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
@@ -224,7 +226,8 @@ extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
extern int _find_first_zero_bit_be(void * p, unsigned size);
extern int _find_next_zero_bit_be(void * p, int size, int offset);
-
+extern int _find_first_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_bit_be(unsigned long *p, int size, int offset);
/*
* The __* form of bitops are non-atomic and may be reordered.
@@ -255,6 +258,8 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
+#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
+#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)
#define WORD_BITOFF_TO_LE(x) ((x))
@@ -272,6 +277,8 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
+#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
+#define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off)
#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18)
diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
index e7c7fd2265cd..0439ec64301c 100644
--- a/include/asm-ppc/processor.h
+++ b/include/asm-ppc/processor.h
@@ -121,6 +121,8 @@ struct thread_struct {
#endif /* CONFIG_ALTIVEC */
};
+#define ARCH_MIN_TASKALIGN 16
+
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
#define INIT_THREAD { \
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index ea8bf67f7007..d3e83108c064 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -553,6 +553,8 @@ struct thread_struct {
#endif /* CONFIG_ALTIVEC */
};
+#define ARCH_MIN_TASKALIGN 16
+
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
#define INIT_THREAD { \
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index ebe0b1221579..99cb4139354b 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -157,6 +157,8 @@ void __wait_on_buffer(struct buffer_head *);
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
void wake_up_buffer(struct buffer_head *bh);
int fsync_bdev(struct block_device *);
+struct super_block *freeze_bdev(struct block_device *);
+void thaw_bdev(struct block_device *, struct super_block *);
int fsync_super(struct super_block *);
int fsync_no_super(struct block_device *);
struct buffer_head *__find_get_block(struct block_device *, sector_t, int);
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 278c533b6994..aa9733c90045 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -597,7 +597,7 @@ COMPATIBLE_IOCTL(RNDGETPOOL)
COMPATIBLE_IOCTL(RNDADDENTROPY)
COMPATIBLE_IOCTL(RNDZAPENTCNT)
COMPATIBLE_IOCTL(RNDCLEARPOOL)
-/* Bluetooth ioctls */
+/* Bluetooth */
COMPATIBLE_IOCTL(HCIDEVUP)
COMPATIBLE_IOCTL(HCIDEVDOWN)
COMPATIBLE_IOCTL(HCIDEVRESET)
@@ -631,6 +631,20 @@ COMPATIBLE_IOCTL(CMTPCONNADD)
COMPATIBLE_IOCTL(CMTPCONNDEL)
COMPATIBLE_IOCTL(CMTPGETCONNLIST)
COMPATIBLE_IOCTL(CMTPGETCONNINFO)
+/* CAPI */
+COMPATIBLE_IOCTL(CAPI_REGISTER)
+COMPATIBLE_IOCTL(CAPI_GET_MANUFACTURER)
+COMPATIBLE_IOCTL(CAPI_GET_VERSION)
+COMPATIBLE_IOCTL(CAPI_GET_SERIAL)
+COMPATIBLE_IOCTL(CAPI_GET_PROFILE)
+COMPATIBLE_IOCTL(CAPI_MANUFACTURER_CMD)
+COMPATIBLE_IOCTL(CAPI_GET_ERRCODE)
+COMPATIBLE_IOCTL(CAPI_INSTALLED)
+COMPATIBLE_IOCTL(CAPI_GET_FLAGS)
+COMPATIBLE_IOCTL(CAPI_SET_FLAGS)
+COMPATIBLE_IOCTL(CAPI_CLR_FLAGS)
+COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT)
+COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT)
/* Misc. */
COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */
COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ed06629b972e..8971ae34dbdf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -345,6 +345,7 @@ struct block_device {
struct inode * bd_inode; /* will die */
int bd_openers;
struct semaphore bd_sem; /* open/close mutex */
+ struct semaphore bd_mount_sem; /* mount mutex */
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
@@ -749,6 +750,9 @@ struct super_block {
struct list_head s_instances;
struct quota_info s_dquot; /* Diskquota specific options */
+ int s_frozen;
+ wait_queue_head_t s_wait_unfrozen;
+
char s_id[32]; /* Informational name */
void *s_fs_info; /* Filesystem private info */
@@ -761,6 +765,18 @@ struct super_block {
};
/*
+ * Snapshotting support.
+ */
+enum {
+ SB_UNFROZEN = 0,
+ SB_FREEZE_WRITE = 1,
+ SB_FREEZE_TRANS = 2,
+};
+
+#define vfs_check_frozen(sb, level) \
+ wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level)))
+
+/*
* Superblock locking.
*/
static inline void lock_super(struct super_block * sb)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 0b12bd800fd1..2d439a8390c0 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -24,8 +24,6 @@ enum {
PROC_ROOT_INO = 1,
};
-/* Finally, the dynamically allocatable proc entries are reserved: */
-
#define PROC_SUPER_MAGIC 0x9fa0
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 428b48964fc8..e414003e872b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -151,7 +151,6 @@ extern void init_idle(task_t *idle, int cpu);
extern void show_state(void);
extern void show_regs(struct pt_regs *);
-extern void show_trace_task(task_t *tsk);
/*
* TASK is a pointer to the task whose backtrace we want to see (or NULL for current
diff --git a/include/linux/security.h b/include/linux/security.h
index 9baa2ed4ac96..2d16f6577669 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -44,7 +44,7 @@ extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kern
extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
extern int cap_bprm_set_security (struct linux_binprm *bprm);
-extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
+extern void cap_bprm_apply_creds (struct linux_binprm *bprm);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
@@ -102,7 +102,7 @@ struct swap_info_struct;
* @bprm_free_security:
* @bprm contains the linux_binprm structure to be modified.
* Deallocate and clear the @bprm->security field.
- * @bprm_compute_creds:
+ * @bprm_apply_creds:
* Compute and set the security attributes of a process being transformed
* by an execve operation based on the old attributes (current->security)
* and the information saved in @bprm->security by the set_security hook.
@@ -115,7 +115,7 @@ struct swap_info_struct;
* @bprm contains the linux_binprm structure.
* @bprm_set_security:
* Save security information in the bprm->security field, typically based
- * on information about the bprm->file, for later use by the compute_creds
+ * on information about the bprm->file, for later use by the apply_creds
* hook. This hook may also optionally check permissions (e.g. for
* transitions between security domains).
* This hook may be called multiple times during a single execve, e.g. for
@@ -924,7 +924,7 @@ struct swap_info_struct;
* Check permission before allowing the @parent process to trace the
* @child process.
* Security modules may also want to perform a process tracing check
- * during an execve in the set_security or compute_creds hooks of
+ * during an execve in the set_security or apply_creds hooks of
* binprm_security_ops if the process is being traced and its security
* attributes would be changed by the execve.
* @parent contains the task_struct structure for parent process.
@@ -1026,7 +1026,7 @@ struct security_operations {
int (*bprm_alloc_security) (struct linux_binprm * bprm);
void (*bprm_free_security) (struct linux_binprm * bprm);
- void (*bprm_compute_creds) (struct linux_binprm * bprm);
+ void (*bprm_apply_creds) (struct linux_binprm * bprm);
int (*bprm_set_security) (struct linux_binprm * bprm);
int (*bprm_check_security) (struct linux_binprm * bprm);
int (*bprm_secureexec) (struct linux_binprm * bprm);
@@ -1290,9 +1290,9 @@ static inline void security_bprm_free (struct linux_binprm *bprm)
{
security_ops->bprm_free_security (bprm);
}
-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
{
- security_ops->bprm_compute_creds (bprm);
+ security_ops->bprm_apply_creds (bprm);
}
static inline int security_bprm_set (struct linux_binprm *bprm)
{
@@ -1962,9 +1962,9 @@ static inline int security_bprm_alloc (struct linux_binprm *bprm)
static inline void security_bprm_free (struct linux_binprm *bprm)
{ }
-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
{
- cap_bprm_compute_creds (bprm);
+ cap_bprm_apply_creds (bprm);
}
static inline int security_bprm_set (struct linux_binprm *bprm)
diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
index a444c9edb9e9..3a2206f61de0 100644
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -20,6 +20,7 @@
#include <linux/sunrpc/auth_gss.h>
int gss_svc_init(void);
+void gss_svc_shutdown(void);
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
#endif /* __KERNEL__ */
diff --git a/init/Kconfig b/init/Kconfig
index 55261afdc3bf..337feb1026ea 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -149,7 +149,7 @@ config AUDIT
config AUDITSYSCALL
bool "Enable system-call auditing support"
- depends on AUDIT && (X86 || PPC64)
+ depends on AUDIT && (X86 || PPC64 || ARCH_S390)
default y if SECURITY_SELINUX
default n
help
diff --git a/init/main.c b/init/main.c
index c500c6fe296d..84cf96dddf4e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -89,6 +89,7 @@ extern void radix_tree_init(void);
extern void free_initmem(void);
extern void populate_rootfs(void);
extern void driver_init(void);
+extern void prepare_namespace(void);
#ifdef CONFIG_TC
extern void tc_init(void);
@@ -471,7 +472,6 @@ asmlinkage void __init start_kernel(void)
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
- populate_rootfs();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
@@ -577,8 +577,6 @@ static void run_init_process(char *init_filename)
execve(init_filename, argv_init, envp_init);
}
-extern void prepare_namespace(void);
-
static int init(void * unused)
{
lock_kernel();
@@ -600,14 +598,15 @@ static int init(void * unused)
smp_init();
do_basic_setup();
- /*
- * check if there is an early userspace init, if yes
- * let it do all the work
- */
- if (sys_access("/init", 0) == 0)
- execute_command = "/init";
- else
- prepare_namespace();
+ populate_rootfs();
+ /*
+ * check if there is an early userspace init. If yes, let it do all
+ * the work
+ */
+ if (sys_access("/init", 0) == 0)
+ execute_command = "/init";
+ else
+ prepare_namespace();
/*
* Ok, we have completed the initial bootup, and
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index b1b922f09257..971124109c8c 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -984,6 +984,7 @@ out:
static void __exit exit_rpcsec_gss(void)
{
+ gss_svc_shutdown();
gss_mech_unregister_all();
rpcauth_unregister(&authgss_ops);
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index a60a541e9f5e..dae18e9792a6 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1063,3 +1063,10 @@ gss_svc_init(void)
svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss);
return 0;
}
+
+void
+gss_svc_shutdown(void)
+{
+ cache_unregister(&rsc_cache);
+ cache_unregister(&rsi_cache);
+}
diff --git a/security/capability.c b/security/capability.c
index ba7daa4592dd..f1e81ba6b79d 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -35,7 +35,7 @@ static struct security_operations capability_ops = {
.netlink_send = cap_netlink_send,
.netlink_recv = cap_netlink_recv,
- .bprm_compute_creds = cap_bprm_compute_creds,
+ .bprm_apply_creds = cap_bprm_apply_creds,
.bprm_set_security = cap_bprm_set_security,
.bprm_secureexec = cap_bprm_secureexec,
diff --git a/security/commoncap.c b/security/commoncap.c
index e902b60ecc30..07265810c353 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -115,13 +115,15 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
return 0;
}
-/* Copied from fs/exec.c */
static inline int must_not_trace_exec (struct task_struct *p)
{
- return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
+ return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+ || atomic_read(&p->fs->count) > 1
+ || atomic_read(&p->files->count) > 1
+ || atomic_read(&p->sighand->count) > 1;
}
-void cap_bprm_compute_creds (struct linux_binprm *bprm)
+void cap_bprm_apply_creds (struct linux_binprm *bprm)
{
/* Derived from fs/exec.c:compute_creds. */
kernel_cap_t new_permitted, working;
@@ -132,18 +134,26 @@ void cap_bprm_compute_creds (struct linux_binprm *bprm)
new_permitted = cap_combine (new_permitted, working);
task_lock(current);
+
+ if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+ current->mm->dumpable = 0;
+
+ if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+ bprm->e_uid = current->uid;
+ bprm->e_gid = current->gid;
+ }
+ }
+
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
if (!cap_issubset (new_permitted, current->cap_permitted)) {
current->mm->dumpable = 0;
- if (must_not_trace_exec (current)
- || atomic_read (&current->fs->count) > 1
- || atomic_read (&current->files->count) > 1
- || atomic_read (&current->sighand->count) > 1) {
- if (!capable (CAP_SETPCAP)) {
- new_permitted = cap_intersect (new_permitted,
- current->
- cap_permitted);
- }
+ if (must_not_trace_exec (current) && !capable (CAP_SETPCAP)) {
+ new_permitted = cap_intersect (new_permitted,
+ current->
+ cap_permitted);
}
}
@@ -315,7 +325,7 @@ int cap_vm_enough_memory(long pages)
vm_acct_memory(pages);
- /*
+ /*
* Sometimes we want to use more memory than we have
*/
if (sysctl_overcommit_memory == 1)
@@ -377,7 +387,7 @@ EXPORT_SYMBOL(cap_capget);
EXPORT_SYMBOL(cap_capset_check);
EXPORT_SYMBOL(cap_capset_set);
EXPORT_SYMBOL(cap_bprm_set_security);
-EXPORT_SYMBOL(cap_bprm_compute_creds);
+EXPORT_SYMBOL(cap_bprm_apply_creds);
EXPORT_SYMBOL(cap_bprm_secureexec);
EXPORT_SYMBOL(cap_inode_setxattr);
EXPORT_SYMBOL(cap_inode_removexattr);
diff --git a/security/dummy.c b/security/dummy.c
index 3bf46b0f5997..c34991da5d6e 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -26,6 +26,8 @@
#include <net/sock.h>
#include <linux/xattr.h>
#include <linux/hugetlb.h>
+#include <linux/ptrace.h>
+#include <linux/file.h>
static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
{
@@ -116,7 +118,7 @@ static int dummy_vm_enough_memory(long pages)
vm_acct_memory(pages);
- /*
+ /*
* Sometimes we want to use more memory than we have
*/
if (sysctl_overcommit_memory == 1)
@@ -169,9 +171,30 @@ static void dummy_bprm_free_security (struct linux_binprm *bprm)
return;
}
-static void dummy_bprm_compute_creds (struct linux_binprm *bprm)
+static inline int must_not_trace_exec (struct task_struct *p)
{
- return;
+ return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+ || atomic_read(&p->fs->count) > 1
+ || atomic_read(&p->files->count) > 1
+ || atomic_read(&p->sighand->count) > 1;
+}
+
+static void dummy_bprm_apply_creds (struct linux_binprm *bprm)
+{
+ task_lock(current);
+ if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+ current->mm->dumpable = 0;
+
+ if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+ bprm->e_uid = current->uid;
+ bprm->e_gid = current->gid;
+ }
+ }
+
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+ task_unlock(current);
}
static int dummy_bprm_set_security (struct linux_binprm *bprm)
@@ -887,7 +910,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, vm_enough_memory);
set_to_dummy_if_null(ops, bprm_alloc_security);
set_to_dummy_if_null(ops, bprm_free_security);
- set_to_dummy_if_null(ops, bprm_compute_creds);
+ set_to_dummy_if_null(ops, bprm_apply_creds);
set_to_dummy_if_null(ops, bprm_set_security);
set_to_dummy_if_null(ops, bprm_check_security);
set_to_dummy_if_null(ops, bprm_secureexec);
diff --git a/security/root_plug.c b/security/root_plug.c
index c683d6133321..ec8955dcba29 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -90,7 +90,7 @@ static struct security_operations rootplug_security_ops = {
.capset_set = cap_capset_set,
.capable = cap_capable,
- .bprm_compute_creds = cap_bprm_compute_creds,
+ .bprm_apply_creds = cap_bprm_apply_creds,
.bprm_set_security = cap_bprm_set_security,
.task_post_setuid = cap_task_post_setuid,
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 387729cc6a0a..be4d39864576 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -24,6 +24,21 @@ config SECURITY_SELINUX_BOOTPARAM
If you are unsure how to answer this question, answer N.
+config SECURITY_SELINUX_DISABLE
+ bool "NSA SELinux runtime disable"
+ depends on SECURITY_SELINUX
+ default n
+ help
+ This option enables writing to a selinuxfs node 'disable', which
+ allows SELinux to be disabled at runtime prior to the policy load.
+ SELinux will then remain disabled until the next boot.
+ This option is similar to the selinux=0 boot parameter, but is to
+ support runtime disabling of SELinux, e.g. from /sbin/init, for
+ portability across platforms where boot parameters are difficult
+ to employ.
+
+ If you are unsure how to answer this question, answer N.
+
config SECURITY_SELINUX_DEVELOP
bool "NSA SELinux Development Support"
depends on SECURITY_SELINUX
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5e765cd7535b..2273c5f851b4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1745,7 +1745,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
spin_unlock(&files->file_lock);
}
-static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
+static void selinux_bprm_apply_creds(struct linux_binprm *bprm)
{
struct task_security_struct *tsec, *psec;
struct bprm_security_struct *bsec;
@@ -1755,7 +1755,7 @@ static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
struct rlimit *rlim, *initrlim;
int rc, i;
- secondary_ops->bprm_compute_creds(bprm);
+ secondary_ops->bprm_apply_creds(bprm);
tsec = current->security;
@@ -2560,7 +2560,7 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim
/* Control the ability to change the hard limit (whether
lowering or raising it), so that the hard limit can
later be used as a safe reset point for the soft limit
- upon context transitions. See selinux_bprm_compute_creds. */
+ upon context transitions. See selinux_bprm_apply_creds. */
if (old_rlim->rlim_max != new_rlim->rlim_max)
return task_has_perm(current, current, PROCESS__SETRLIMIT);
@@ -3971,7 +3971,7 @@ struct security_operations selinux_ops = {
.bprm_alloc_security = selinux_bprm_alloc_security,
.bprm_free_security = selinux_bprm_free_security,
- .bprm_compute_creds = selinux_bprm_compute_creds,
+ .bprm_apply_creds = selinux_bprm_apply_creds,
.bprm_set_security = selinux_bprm_set_security,
.bprm_check_security = selinux_bprm_check_security,
.bprm_secureexec = selinux_bprm_secureexec,
@@ -4216,4 +4216,57 @@ out:
__initcall(selinux_nf_ip_init);
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+static void selinux_nf_ip_exit(void)
+{
+ printk(KERN_INFO "SELinux: Unregistering netfilter hooks\n");
+
+ nf_unregister_hook(&selinux_ipv4_op);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ nf_unregister_hook(&selinux_ipv6_op);
+#endif /* IPV6 */
+}
+#endif
+
+#else /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+#define selinux_nf_ip_exit()
+#endif
+
#endif /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
+
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+int selinux_disable(void)
+{
+ extern void exit_sel_fs(void);
+ static int selinux_disabled = 0;
+
+ if (ss_initialized) {
+ /* Not permitted after initial policy load. */
+ return -EINVAL;
+ }
+
+ if (selinux_disabled) {
+ /* Only do this once. */
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "SELinux: Disabled at runtime.\n");
+
+ selinux_disabled = 1;
+
+ /* Reset security_ops to the secondary module, dummy or capability. */
+ security_ops = secondary_ops;
+
+ /* Unregister netfilter hooks. */
+ selinux_nf_ip_exit();
+
+ /* Unregister selinuxfs. */
+ exit_sel_fs();
+
+ return 0;
+}
+#endif
+
+
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c944d72ecce4..1a589da54f1b 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -46,6 +46,8 @@ int task_has_security(struct task_struct *tsk,
struct task_security_struct *tsec;
tsec = tsk->security;
+ if (!tsec)
+ return -EACCES;
return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
SECCLASS_SECURITY, perms, NULL, NULL);
@@ -61,8 +63,9 @@ enum sel_inos {
SEL_RELABEL, /* compute relabeling decision */
SEL_USER, /* compute reachable user contexts */
SEL_POLICYVERS, /* return policy version for this kernel */
- SEL_COMMIT_BOOLS,
- SEL_MLS /* return if MLS policy is enabled */
+ SEL_COMMIT_BOOLS, /* commit new boolean values */
+ SEL_MLS, /* return if MLS policy is enabled */
+ SEL_DISABLE /* disable SELinux until next reboot */
};
static ssize_t sel_read_enforce(struct file *filp, char *buf,
@@ -151,6 +154,53 @@ static struct file_operations sel_enforce_ops = {
.write = sel_write_enforce,
};
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+static ssize_t sel_write_disable(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+
+{
+ char *page;
+ ssize_t length;
+ int new_value;
+ extern int selinux_disable(void);
+
+ if (count < 0 || count >= PAGE_SIZE)
+ return -ENOMEM;
+ if (*ppos != 0) {
+ /* No partial writes. */
+ return -EINVAL;
+ }
+ page = (char*)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ memset(page, 0, PAGE_SIZE);
+ length = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ length = -EINVAL;
+ if (sscanf(page, "%d", &new_value) != 1)
+ goto out;
+
+ if (new_value) {
+ length = selinux_disable();
+ if (length < 0)
+ goto out;
+ }
+
+ length = count;
+out:
+ free_page((unsigned long) page);
+ return length;
+}
+#else
+#define sel_write_disable NULL
+#endif
+
+static struct file_operations sel_disable_ops = {
+ .write = sel_write_disable,
+};
+
static ssize_t sel_read_policyvers(struct file *filp, char *buf,
size_t count, loff_t *ppos)
{
@@ -1005,6 +1055,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
[SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
[SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
[SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
+ [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
@@ -1054,3 +1105,10 @@ static int __init init_sel_fs(void)
}
__initcall(init_sel_fs);
+
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+void exit_sel_fs(void)
+{
+ unregister_filesystem(&sel_fs_type);
+}
+#endif
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 7532053898a6..7d0fedf04179 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -456,9 +456,7 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
goto out;
}
}
- printk(KERN_ERR "security_context_to_sid: called before "
- "initial load_policy on unknown context %s\n", scontext);
- rc = -EINVAL;
+ *sid = SECINITSID_KERNEL;
goto out;
}
*sid = SECSID_NULL;
@@ -1343,8 +1341,6 @@ int security_get_user_sids(u32 fromsid,
if (!ebitmap_get_bit(&role->types, j))
continue;
usercon.type = j+1;
- if (usercon.type == fromcon->type)
- continue;
mls_for_user_ranges(user,usercon) {
rc = context_struct_compute_av(fromcon, &usercon,
SECCLASS_PROCESS,