aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt7
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--Documentation/powerpc/booting-without-of.txt6
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile2
-rw-r--r--arch/arm/Makefile3
-rw-r--r--arch/arm/common/sa1111.c6
-rw-r--r--arch/arm/configs/csb337_defconfig37
-rw-r--r--arch/arm/kernel/Makefile3
-rw-r--r--arch/arm/kernel/isa.c63
-rw-r--r--arch/arm/mach-footbridge/dc21285.c1
-rw-r--r--arch/arm/mach-integrator/pci_v3.c2
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c20
-rw-r--r--arch/arm/mach-pxa/ssp.c35
-rw-r--r--arch/arm/mach-s3c2410/dma.c88
-rw-r--r--arch/arm/mach-sa1100/ssp.c46
-rw-r--r--arch/arm/mm/Kconfig13
-rw-r--r--arch/arm/mm/flush.c26
-rw-r--r--arch/arm/vfp/vfp.h18
-rw-r--r--arch/arm/vfp/vfpdouble.c50
-rw-r--r--arch/arm/vfp/vfphw.S10
-rw-r--r--arch/arm/vfp/vfpmodule.c4
-rw-r--r--arch/arm/vfp/vfpsingle.c55
-rw-r--r--arch/i386/kernel/head.S14
-rw-r--r--arch/i386/kernel/hpet.c2
-rw-r--r--arch/i386/kernel/irq.c5
-rw-r--r--arch/i386/kernel/setup.c32
-rw-r--r--arch/i386/kernel/traps.c27
-rw-r--r--arch/i386/pci/common.c5
-rw-r--r--arch/i386/pci/mmconfig.c34
-rw-r--r--arch/i386/pci/pci.h3
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/kernel/topology.c6
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c4
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c28
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c24
-rw-r--r--arch/powerpc/Kconfig20
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts190
-rw-r--r--arch/powerpc/boot/dts/mpc8349emds.dts328
-rw-r--r--arch/powerpc/configs/mpc834x_mds_defconfig (renamed from arch/powerpc/configs/mpc834x_sys_defconfig)0
-rw-r--r--arch/powerpc/kernel/fpu.S5
-rw-r--r--arch/powerpc/kernel/irq.c84
-rw-r--r--arch/powerpc/kernel/pci_64.c11
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c4
-rw-r--r--arch/powerpc/kernel/prom_init.c10
-rw-r--r--arch/powerpc/kernel/prom_parse.c17
-rw-r--r--arch/powerpc/kernel/smp-tbsync.c5
-rw-r--r--arch/powerpc/kernel/time.c25
-rw-r--r--arch/powerpc/lib/memcpy_64.S11
-rw-r--r--arch/powerpc/mm/44x_mmu.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c49
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c56
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h1
-rw-r--r--arch/powerpc/platforms/83xx/pci.c9
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c26
-rw-r--r--arch/powerpc/platforms/86xx/pci.c3
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c2
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c2
-rw-r--r--arch/powerpc/platforms/powermac/pic.c6
-rw-r--r--arch/powerpc/sysdev/Makefile4
-rw-r--r--arch/powerpc/sysdev/ipic.c303
-rw-r--r--arch/powerpc/sysdev/ipic.h23
-rw-r--r--arch/powerpc/sysdev/mpic.c223
-rw-r--r--arch/ppc/kernel/smp-tbsync.c7
-rw-r--r--arch/ppc/syslib/Makefile2
-rw-r--r--arch/ppc/syslib/ipic.c646
-rw-r--r--arch/ppc/syslib/ipic.h47
-rw-r--r--arch/s390/lib/uaccess.S33
-rw-r--r--arch/s390/lib/uaccess64.S35
-rw-r--r--arch/sparc64/mm/generic.c2
-rw-r--r--arch/x86_64/defconfig66
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c57
-rw-r--r--arch/x86_64/kernel/e820.c35
-rw-r--r--arch/x86_64/kernel/entry.S3
-rw-r--r--arch/x86_64/kernel/head.S1
-rw-r--r--arch/x86_64/kernel/init_task.c5
-rw-r--r--arch/x86_64/kernel/setup.c6
-rw-r--r--arch/x86_64/kernel/setup64.c3
-rw-r--r--arch/x86_64/kernel/traps.c30
-rw-r--r--arch/x86_64/pci/mmconfig.c34
-rw-r--r--arch/xtensa/kernel/ptrace.c2
-rw-r--r--drivers/block/floppy.c12
-rw-r--r--drivers/char/drm/radeon_state.c9
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c1
-rw-r--r--drivers/char/synclink_gt.c14
-rw-r--r--drivers/char/watchdog/sbc8360.c4
-rw-r--r--drivers/ide/pci/sgiioc4.c60
-rw-r--r--drivers/ide/pci/via82cxxx.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c15
-rw-r--r--drivers/macintosh/via-pmu-backlight.c99
-rw-r--r--drivers/macintosh/via-pmu.c12
-rw-r--r--drivers/md/raid1.c57
-rw-r--r--drivers/net/e100.c6
-rw-r--r--drivers/net/sunlance.c27
-rw-r--r--drivers/net/wireless/strip.c6
-rw-r--r--drivers/pci/quirks.c1
-rw-r--r--drivers/s390/block/dasd.c192
-rw-r--r--drivers/s390/block/dasd_genhd.c10
-rw-r--r--drivers/s390/cio/ccwgroup.c14
-rw-r--r--drivers/s390/cio/chsc.c10
-rw-r--r--drivers/s390/cio/device.c19
-rw-r--r--drivers/s390/cio/device_fsm.c20
-rw-r--r--drivers/s390/cio/device_pgid.c27
-rw-r--r--drivers/serial/8250_pci.c31
-rw-r--r--drivers/serial/serial_core.c3
-rw-r--r--drivers/usb/gadget/ether.c45
-rw-r--r--drivers/usb/host/uhci-q.c4
-rw-r--r--drivers/usb/input/hid-core.c149
-rw-r--r--drivers/usb/net/pegasus.h3
-rw-r--r--drivers/usb/net/rtl8150.c1
-rw-r--r--drivers/usb/storage/unusual_devs.h24
-rw-r--r--drivers/video/aty/aty128fb.c18
-rw-r--r--drivers/video/aty/atyfb_base.c18
-rw-r--r--drivers/video/aty/radeon_backlight.c4
-rw-r--r--drivers/video/nvidia/nv_backlight.c18
-rw-r--r--drivers/video/riva/fbdev.c18
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/README2
-rw-r--r--fs/cifs/cifsencrypt.c3
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c28
-rw-r--r--fs/cifs/connect.c32
-rw-r--r--fs/cifs/dir.c4
-rw-r--r--fs/cifs/file.c97
-rw-r--r--fs/cifs/netmisc.c1
-rw-r--r--fs/cifs/readdir.c2
-rw-r--r--fs/cifs/sess.c2
-rw-r--r--fs/cifs/smberr.h1
-rw-r--r--fs/cifs/transport.c618
-rw-r--r--fs/cifs/xattr.c6
-rw-r--r--fs/jbd/transaction.c2
-rw-r--r--fs/xfs/xfs_bmap.c2
-rw-r--r--include/asm-arm/arch-pxa/ssp.h4
-rw-r--r--include/asm-arm/arch-s3c2410/dma.h150
-rw-r--r--include/asm-arm/cacheflush.h18
-rw-r--r--include/asm-arm/hardware/ssp.h4
-rw-r--r--include/asm-arm/io.h7
-rw-r--r--include/asm-arm/spinlock.h16
-rw-r--r--include/asm-i386/alternative.h20
-rw-r--r--include/asm-i386/mach-default/mach_mpspec.h4
-rw-r--r--include/asm-i386/rwlock.h28
-rw-r--r--include/asm-i386/spinlock.h17
-rw-r--r--include/asm-i386/unistd.h4
-rw-r--r--include/asm-i386/unwind.h1
-rw-r--r--include/asm-ia64/sn/sn_sal.h6
-rw-r--r--include/asm-ia64/sn/xp.h22
-rw-r--r--include/asm-ia64/sn/xpc.h4
-rw-r--r--include/asm-powerpc/io.h7
-rw-r--r--include/asm-powerpc/ipic.h12
-rw-r--r--include/asm-powerpc/mpc86xx.h3
-rw-r--r--include/asm-powerpc/mpic.h125
-rw-r--r--include/asm-powerpc/prom.h4
-rw-r--r--include/asm-powerpc/time.h4
-rw-r--r--include/asm-x86_64/alternative.h21
-rw-r--r--include/asm-x86_64/processor.h6
-rw-r--r--include/asm-x86_64/spinlock.h11
-rw-r--r--include/asm-x86_64/unistd.h11
-rw-r--r--include/asm-x86_64/unwind.h1
-rw-r--r--include/linux/delayacct.h10
-rw-r--r--include/linux/mmzone.h1
-rw-r--r--include/linux/pci_ids.h4
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/delayacct.c16
-rw-r--r--kernel/exit.c3
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/irq/handle.c5
-rw-r--r--mm/mempolicy.c10
-rw-r--r--mm/mempool.c9
-rw-r--r--mm/vmstat.c151
-rw-r--r--net/ipv4/ip_output.c1
-rw-r--r--net/ipv4/tcp_cong.c2
-rw-r--r--net/ipv4/tcp_input.c9
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/exthdrs.c29
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/netlink/af_netlink.c14
-rw-r--r--net/sctp/socket.c10
-rw-r--r--net/socket.c3
-rw-r--r--sound/oss/Kconfig30
-rw-r--r--sound/pci/ac97/ac97_codec.c4
184 files changed, 4071 insertions, 1683 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 87851efb022..d1cd5f93e02 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -120,6 +120,13 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
+What: drivers depending on OSS_OBSOLETE_DRIVER
+When: options in 2.6.20, code in 2.6.22
+Why: OSS drivers with ALSA replacements
+Who: Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
What: pci_module_init(driver)
When: January 2007
Why: Is replaced by pci_register_driver(pci_driver).
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b50595a0550..7947cede871 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1183,6 +1183,8 @@ running once the system is up.
Mechanism 2.
nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
Configuration
+ mmconf [IA-32,X86_64] Force MMCONFIG. This is useful
+ to override the builtin blacklist.
nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to
disable the use of MSI interrupts system-wide.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 8c48b8a27b9..5c0ba235f5a 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1136,10 +1136,10 @@ Sense and level information should be encoded as follows:
Devices connected to openPIC-compatible controllers should encode
sense and polarity as follows:
- 0 = high to low edge sensitive type enabled
+ 0 = low to high edge sensitive type enabled
1 = active low level sensitive type enabled
- 2 = low to high edge sensitive type enabled
- 3 = active high level sensitive type enabled
+ 2 = active high level sensitive type enabled
+ 3 = high to low edge sensitive type enabled
ISA PIC interrupt controllers should adhere to the ISA PIC
encodings listed below:
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bbd7064f94..6c399b872e3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3314,10 +3314,11 @@ S: Maintained
XFS FILESYSTEM
P: Silicon Graphics Inc
+P: Tim Shimmin, David Chatterton
M: xfs-masters@oss.sgi.com
-M: nathans@sgi.com
L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs
+T: git git://oss.sgi.com:8090/xfs/xfs-2.6
S: Supported
X86 3-LEVEL PAGING (PAE) SUPPORT
diff --git a/Makefile b/Makefile
index 33559b56644..c9ed7b42873 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 18
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
NAME=Crazed Snow-Weasel
# *DOCUMENTATION*
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 3345c6d0fd1..92873cdee31 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,7 +47,8 @@ comma = ,
# testing for a specific architecture or later rather impossible.
arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
-arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index a331c12cead..29818bd3248 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -618,7 +618,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
{
struct sa1111 *sachip;
unsigned long id;
- unsigned int has_devs, val;
+ unsigned int has_devs;
int i, ret = -ENODEV;
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
@@ -669,6 +669,9 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
sa1111_wake(sachip);
#ifdef CONFIG_ARCH_SA1100
+ {
+ unsigned int val;
+
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
@@ -692,6 +695,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
+ }
#endif
/*
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 3594155a813..cf3fa5cb26e 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -621,9 +621,8 @@ CONFIG_AT91_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_AT91_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -956,10 +955,42 @@ CONFIG_USB_AT91=y
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_BLOCK=y
-# CONFIG_MMC_WBSD is not set
CONFIG_MMC_AT91RM9200=y
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+
+#
+# RTC interfaces
+#
+# CONFIG_RTC_INTF_SYSFS is not set
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index f0c0cdb1c18..1320a0efca7 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -13,12 +13,11 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o
-obj-$(CONFIG_FOOTBRIDGE) += isa.o
obj-$(CONFIG_FIQ) += fiq.o
obj-$(CONFIG_MODULES) += armksyms.o module.o
obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
-obj-$(CONFIG_PCI) += bios32.o
+obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 685c3e591a7..54bbd9fe255 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -3,21 +3,14 @@
*
* Copyright (C) 1999 Phil Blundell
*
- * ISA shared memory and I/O port support
- */
-
-/*
* 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.
+ *
+ * ISA shared memory and I/O port support, and is required to support
+ * iopl, inb, outb and friends in userspace via glibc emulation.
*/
-
-/*
- * Nothing about this is actually ARM specific. One day we could move
- * it into kernel/resource.c or some place like that.
- */
-
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/fs.h>
@@ -27,21 +20,49 @@
static unsigned int isa_membase, isa_portbase, isa_portshift;
static ctl_table ctl_isa_vars[4] = {
- {BUS_ISA_MEM_BASE, "membase", &isa_membase,
- sizeof(isa_membase), 0444, NULL, &proc_dointvec},
- {BUS_ISA_PORT_BASE, "portbase", &isa_portbase,
- sizeof(isa_portbase), 0444, NULL, &proc_dointvec},
- {BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift,
- sizeof(isa_portshift), 0444, NULL, &proc_dointvec},
- {0}
+ {
+ .ctl_name = BUS_ISA_MEM_BASE,
+ .procname = "membase",
+ .data = &isa_membase,
+ .maxlen = sizeof(isa_membase),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {
+ .ctl_name = BUS_ISA_PORT_BASE,
+ .procname = "portbase",
+ .data = &isa_portbase,
+ .maxlen = sizeof(isa_portbase),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {
+ .ctl_name = BUS_ISA_PORT_SHIFT,
+ .procname = "portshift",
+ .data = &isa_portshift,
+ .maxlen = sizeof(isa_portshift),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
+ }, {0}
};
static struct ctl_table_header *isa_sysctl_header;
-static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
- {0}};
-static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
- {0}};
+static ctl_table ctl_isa[2] = {
+ {
+ .ctl_name = CTL_BUS_ISA,
+ .procname = "isa",
+ .mode = 0555,
+ .child = ctl_isa_vars,
+ }, {0}
+};
+
+static ctl_table ctl_bus[2] = {
+ {
+ .ctl_name = CTL_BUS,
+ .procname = "bus",
+ .mode = 0555,
+ .child = ctl_isa,
+ }, {0}
+};
void __init
register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 607ed1f5b3f..823e25d4547 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -35,7 +35,6 @@
extern int setup_arm_irq(int, struct irqaction *);
extern void pcibios_report_status(u_int status_mask, int warn);
-extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
static unsigned long
dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index f9043592e29..4418f6d7572 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -600,4 +600,6 @@ void __init pci_v3_postinit(void)
printk(KERN_ERR "PCI: unable to grab local bus timeout "
"interrupt: %d\n", ret);
#endif
+
+ register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
}
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index f9421318cb7..ff6b4ee037f 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -47,14 +47,15 @@ static struct corgissp_machinfo *ssp_machinfo;
*/
unsigned long corgi_ssp_ads7846_putget(ulong data)
{
- unsigned long ret,flag;
+ unsigned long flag;
+ u32 ret = 0;
spin_lock_irqsave(&corgi_ssp_lock, flag);
if (ssp_machinfo->cs_ads7846 >= 0)
GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
ssp_write_word(&corgi_ssp_dev,data);
- ret = ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, &ret);
if (ssp_machinfo->cs_ads7846 >= 0)
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
@@ -88,7 +89,9 @@ void corgi_ssp_ads7846_put(ulong data)
unsigned long corgi_ssp_ads7846_get(void)
{
- return ssp_read_word(&corgi_ssp_dev);
+ u32 ret = 0;
+ ssp_read_word(&corgi_ssp_dev, &ret);
+ return ret;
}
EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
@@ -104,6 +107,7 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get);
unsigned long corgi_ssp_dac_put(ulong data)
{
unsigned long flag, sscr1 = SSCR1_SPH;
+ u32 tmp;
spin_lock_irqsave(&corgi_ssp_lock, flag);
@@ -118,7 +122,7 @@ unsigned long corgi_ssp_dac_put(ulong data)
GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_write_word(&corgi_ssp_dev,data);
/* Read null data back from device to prevent SSP overflow */
- ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, &tmp);
if (ssp_machinfo->cs_lcdcon >= 0)
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
@@ -150,7 +154,7 @@ EXPORT_SYMBOL(corgi_ssp_blduty_set);
int corgi_ssp_max1111_get(ulong data)
{
unsigned long flag;
- int voltage,voltage1,voltage2;
+ long voltage = 0, voltage1 = 0, voltage2 = 0;
spin_lock_irqsave(&corgi_ssp_lock, flag);
if (ssp_machinfo->cs_max1111 >= 0)
@@ -163,15 +167,15 @@ int corgi_ssp_max1111_get(ulong data)
/* TB1/RB1 */
ssp_write_word(&corgi_ssp_dev,data);
- ssp_read_word(&corgi_ssp_dev); /* null read */
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */
/* TB12/RB2 */
ssp_write_word(&corgi_ssp_dev,0);
- voltage1=ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1);
/* TB13/RB3*/
ssp_write_word(&corgi_ssp_dev,0);
- voltage2=ssp_read_word(&corgi_ssp_dev);
+ ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2);
ssp_disable(&corgi_ssp_dev);
ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 93096befd01..1fddfeaa630 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -40,6 +40,8 @@
#define PXA_SSP_PORTS 3
+#define TIMEOUT 100000
+
struct ssp_info_ {
int irq;
u32 clock;
@@ -92,13 +94,18 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 0 success
*/
int ssp_write_word(struct ssp_dev *dev, u32 data)
{
- while (!(SSSR_P(dev->port) & SSSR_TNF))
+ int timeout = TIMEOUT;
+
+ while (!(SSSR_P(dev->port) & SSSR_TNF)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
SSDR_P(dev->port) = data;
@@ -117,15 +124,21 @@ int ssp_write_word(struct ssp_dev *dev, u32 data)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 32-bit data success
*/
-int ssp_read_word(struct ssp_dev *dev)
+int ssp_read_word(struct ssp_dev *dev, u32 *data)
{
- while (!(SSSR_P(dev->port) & SSSR_RNE))
+ int timeout = TIMEOUT;
+
+ while (!(SSSR_P(dev->port) & SSSR_RNE)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
- return SSDR_P(dev->port);
+ *data = SSDR_P(dev->port);
+ return 0;
}
/**
@@ -136,13 +149,21 @@ int ssp_read_word(struct ssp_dev *dev)
*
* The caller is expected to perform the necessary locking.
*/
-void ssp_flush(struct ssp_dev *dev)
+int ssp_flush(struct ssp_dev *dev)
{
+ int timeout = TIMEOUT * 2;
+
do {
while (SSSR_P(dev->port) & SSSR_RNE) {
+ if (!--timeout)
+ return -ETIMEDOUT;
(void) SSDR_P(dev->port);
}
+ if (!--timeout)
+ return -ETIMEDOUT;
} while (SSSR_P(dev->port) & SSSR_BSY);
+
+ return 0;
}
/**
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 25855452fe8..cc92a7b2db8 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -60,7 +60,7 @@ static void __iomem *dma_base;
static kmem_cache_t *dma_kmem;
/* dma channel state information */
-s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
/* debugging functions */
@@ -74,7 +74,7 @@ s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
#else
static inline void
-dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val)
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
{
pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
writel(val, dma_regaddr(chan, reg));
@@ -102,7 +102,7 @@ struct s3c2410_dma_regstate {
*/
static void
-dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
{
regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
@@ -112,7 +112,7 @@ dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
}
static void
-dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
struct s3c2410_dma_regstate *regs)
{
printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
@@ -122,7 +122,7 @@ dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
}
static void
-dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
{
struct s3c2410_dma_regstate state;
@@ -136,7 +136,7 @@ dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
}
static void
-dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan)
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
{
struct s3c2410_dma_regstate state;
@@ -164,7 +164,7 @@ dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan)
*/
static void
-s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
{
if (stats == NULL)
return;
@@ -183,7 +183,7 @@ s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
*/
static int
-s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
{
int timeout = chan->load_timeout;
int took;
@@ -230,8 +230,8 @@ s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
*/
static inline int
-s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
- s3c2410_dma_buf_t *buf)
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+ struct s3c2410_dma_buf *buf)
{
unsigned long reload;
@@ -304,7 +304,7 @@ s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
*/
static void
-s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
{
if (chan->op_fn != NULL) {
(chan->op_fn)(chan, op);
@@ -318,8 +318,8 @@ s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
*/
static inline void
-s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
- s3c2410_dma_buffresult_t result)
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+ enum s3c2410_dma_buffresult result)
{
pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
chan->callback_fn, buf, buf->id, buf->size, result);
@@ -334,7 +334,7 @@ s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
* start a dma channel going
*/
-static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
{
unsigned long tmp;
unsigned long flags;
@@ -430,7 +430,7 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
*/
static int
-s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
{
if (chan->load_state == S3C2410_DMALOAD_NONE ||
chan->load_state == S3C2410_DMALOAD_1RUNNING)
@@ -460,8 +460,8 @@ s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
int s3c2410_dma_enqueue(unsigned int channel, void *id,
dma_addr_t data, int size)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
- s3c2410_dma_buf_t *buf;
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_buf *buf;
unsigned long flags;
check_channel(channel);
@@ -540,7 +540,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
EXPORT_SYMBOL(s3c2410_dma_enqueue);
static inline void
-s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
{
int magicok = (buf->magic == BUF_MAGIC);
@@ -560,7 +560,7 @@ s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
*/
static inline void
-s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
{
pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
chan->number, chan->load_state);
@@ -601,8 +601,8 @@ s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
static irqreturn_t
s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
{
- s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw;
- s3c2410_dma_buf_t *buf;
+ struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+ struct s3c2410_dma_buf *buf;
buf = chan->curr;
@@ -731,10 +731,10 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
* get control of an dma channel
*/
-int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
+int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client,
void *dev)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
unsigned long flags;
int err;
@@ -807,9 +807,9 @@ EXPORT_SYMBOL(s3c2410_dma_request);
* allowed to go through.
*/
-int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
unsigned long flags;
check_channel(channel);
@@ -846,7 +846,7 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
EXPORT_SYMBOL(s3c2410_dma_free);
-static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
{
unsigned long tmp;
unsigned long flags;
@@ -880,7 +880,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
return 0;
}
-void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan)
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
{
unsigned long tmp;
unsigned int timeout = 0x10000;
@@ -901,9 +901,9 @@ void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan)
* stop the channel, and remove all current and pending transfers
*/
-static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
{
- s3c2410_dma_buf_t *buf, *next;
+ struct s3c2410_dma_buf *buf, *next;
unsigned long flags;
pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
@@ -958,7 +958,7 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
}
int
-s3c2410_dma_started(s3c2410_dma_chan_t *chan)
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
{
unsigned long flags;
@@ -995,9 +995,9 @@ s3c2410_dma_started(s3c2410_dma_chan_t *chan)
}
int
-s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1046,7 +1046,7 @@ int s3c2410_dma_config(dmach_t channel,
int xferunit,
int dcon)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
__FUNCTION__, channel, xferunit, dcon);
@@ -1086,7 +1086,7 @@ EXPORT_SYMBOL(s3c2410_dma_config);
int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1106,7 +1106,7 @@ EXPORT_SYMBOL(s3c2410_dma_setflags);
int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1121,7 +1121,7 @@ EXPORT_SYMBOL(s3c2410_dma_set_opfn);
int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1149,11 +1149,11 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
*/
int s3c2410_dma_devconfig(int channel,
- s3c2410_dmasrc_t source,
+ enum s3c2410_dmasrc source,
int hwcfg,
unsigned long devaddr)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig);
int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
{
- s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
check_channel(channel);
@@ -1222,7 +1222,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition);
static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
{
- s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev);
+ struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
@@ -1262,7 +1262,7 @@ static struct sysdev_class dma_sysclass = {
static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
{
- memset(p, 0, sizeof(s3c2410_dma_buf_t));
+ memset(p, 0, sizeof(struct s3c2410_dma_buf));
}
@@ -1270,7 +1270,7 @@ static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
static int __init s3c2410_init_dma(void)
{
- s3c2410_dma_chan_t *cp;
+ struct s3c2410_dma_chan *cp;
int channel;
int ret;
@@ -1288,7 +1288,7 @@ static int __init s3c2410_init_dma(void)
goto err;
}
- dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0,
+ dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
SLAB_HWCACHE_ALIGN,
s3c2410_dma_cache_ctor, NULL);
@@ -1301,7 +1301,7 @@ static int __init s3c2410_init_dma(void)
for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
cp = &s3c2410_chans[channel];
- memset(cp, 0, sizeof(s3c2410_dma_chan_t));
+ memset(cp, 0, sizeof(struct s3c2410_dma_chan));
/* dma channel irqs are in order.. */
cp->number = channel;
diff --git a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
index 1604dadf27f..5eba5fbbb56 100644
--- a/arch/arm/mach-sa1100/ssp.c
+++ b/arch/arm/mach-sa1100/ssp.c
@@ -23,6 +23,8 @@
#include <asm/hardware.h>
#include <asm/hardware/ssp.h>
+#define TIMEOUT 100000
+
static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int status = Ser4SSSR;
@@ -47,18 +49,27 @@ static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 0 success
*/
int ssp_write_word(u16 data)
{
- while (!(Ser4SSSR & SSSR_TNF))
+ int timeout = TIMEOUT;
+
+ while (!(Ser4SSSR & SSSR_TNF)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
Ser4SSDR = data;
- while (!(Ser4SSSR & SSSR_BSY))
+ timeout = TIMEOUT;
+ while (!(Ser4SSSR & SSSR_BSY)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
return 0;
}
@@ -75,15 +86,22 @@ int ssp_write_word(u16 data)
* The caller is expected to perform the necessary locking.
*
* Returns:
- * %-ETIMEDOUT timeout occurred (for future)
+ * %-ETIMEDOUT timeout occurred
* 16-bit data success
*/
-int ssp_read_word(void)
+int ssp_read_word(u16 *data)
{
- while (!(Ser4SSSR & SSSR_RNE))
+ int timeout = TIMEOUT;
+
+ while (!(Ser4SSSR & SSSR_RNE)) {
+ if (!--timeout)
+ return -ETIMEDOUT;
cpu_relax();
+ }
+
+ *data = (u16)Ser4SSDR;
- return Ser4SSDR;
+ return 0;
}
/**
@@ -93,14 +111,26 @@ int ssp_read_word(void)
* is empty.
*
* The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ * %-ETIMEDOUT timeout occurred
+ * 0 success
*/
-void ssp_flush(void)
+int ssp_flush(void)
{
+ int timeout = TIMEOUT * 2;
+
do {
while (Ser4SSSR & SSSR_RNE) {
+ if (!--timeout)
+ return -ETIMEDOUT;
(void) Ser4SSDR;
}
+ if (!--timeout)
+ return -ETIMEDOUT;
} while (Ser4SSSR & SSSR_BSY);
+
+ return 0;
}
/**
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5f80f184cd3..b4f220dd5eb 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -46,7 +46,7 @@ config CPU_ARM710
config CPU_ARM720T
bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_LV4T
select CPU_CACHE_V4
select CPU_CACHE_VIVT
@@ -64,7 +64,7 @@ config CPU_ARM920T
bool "Support ARM920T processor"
depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -85,7 +85,7 @@ config CPU_ARM922T
bool "Support ARM922T processor" if ARCH_INTEGRATOR
depends on ARCH_LH7A40X || ARCH_INTEGRATOR
default y if ARCH_LH7A40X
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -104,7 +104,7 @@ config CPU_ARM925T
bool "Support ARM925T processor" if ARCH_OMAP1
depends on ARCH_OMAP15XX
default y if ARCH_OMAP15XX
- select CPU_32v4
+ select CPU_32v4T
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
select CPU_CACHE_VIVT
@@ -285,6 +285,11 @@ config CPU_32v4
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+config CPU_32v4T
+ bool
+ select TLS_REG_EMUL if SMP || !MMU
+ select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+
config CPU_32v5
bool
select TLS_REG_EMUL if SMP || !MMU
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index b103e56806b..d438ce41cdd 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -87,6 +87,32 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
if (cache_is_vipt_aliasing())
flush_pfn_alias(pfn, user_addr);
}
+
+void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+ unsigned long uaddr, void *kaddr,
+ unsigned long len, int write)
+{
+ if (cache_is_vivt()) {
+ if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
+ unsigned long addr = (unsigned long)kaddr;
+ __cpuc_coherent_kern_range(addr, addr + len);
+ }
+ return;
+ }
+
+ if (cache_is_vipt_aliasing()) {
+ flush_pfn_alias(page_to_pfn(page), uaddr);
+ return;
+ }
+
+ /* VIPT non-aliasing cache */
+ if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) &&
+ vma->vm_flags | VM_EXEC) {
+ unsigned long addr = (unsigned long)kaddr;
+ /* only flushing the kernel mapping on non-aliasing VIPT */
+ __cpuc_coherent_kern_range(addr, addr + len);
+ }
+}
#else
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
#endif
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 4b97950984e..96fdf30f6a3 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -156,7 +156,7 @@ struct vfp_single {
};
extern s32 vfp_get_float(unsigned int reg);
-extern void vfp_put_float(unsigned int reg, s32 val);
+extern void vfp_put_float(s32 val, unsigned int reg);
/*
* VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
@@ -267,7 +267,7 @@ struct vfp_double {
*/
#define VFP_REG_ZERO 16
extern u64 vfp_get_double(unsigned int reg);
-extern void vfp_put_double(unsigned int reg, u64 val);
+extern void vfp_put_double(u64 val, unsigned int reg);
#define VFP_DOUBLE_MANTISSA_BITS (52)
#define VFP_DOUBLE_EXPONENT_BITS (11)
@@ -341,15 +341,17 @@ static inline int vfp_double_type(struct vfp_double *s)
u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
-/*
- * System registers
- */
-extern u32 vfp_get_sys(unsigned int reg);
-extern void vfp_put_sys(unsigned int reg, u32 val);
-
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
/*
* A special flag to tell the normalisation code not to normalise.
*/
#define VFP_NAN_FLAG 0x100
+
+/*
+ * A bit pattern used to indicate the initial (unset) value of the
+ * exception mask, in case nothing handles an instruction. This
+ * doesn't include the NAN flag, which get masked out before
+ * we check for an error.
+ */
+#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 009038c8113..add48e36c2d 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -195,7 +195,7 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce
s64 d = vfp_double_pack(vd);
pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
dd, d, exceptions);
- vfp_put_double(dd, d);
+ vfp_put_double(d, dd);
}
return exceptions;
}
@@ -250,19 +250,19 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
*/
static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr)
{
- vfp_put_double(dd, vfp_double_packed_abs(vfp_get_double(dm)));
+ vfp_put_double(vfp_double_packed_abs(vfp_get_double(dm)), dd);
return 0;
}
static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr)
{
- vfp_put_double(dd, vfp_get_double(dm));
+ vfp_put_double(vfp_get_double(dm), dd);
return 0;
}
static u32 vfp_double_fneg(int dd, int unused, int dm, u32 fpscr)
{
- vfp_put_double(dd, vfp_double_packed_negate(vfp_get_double(dm)));
+ vfp_put_double(vfp_double_packed_negate(vfp_get_double(dm)), dd);
return 0;
}
@@ -287,7 +287,7 @@ static u32 vfp_double_fsqrt(int dd, int unused, int dm, u32 fpscr)
vdp = &vfp_double_default_qnan;
ret = FPSCR_IOC;
}
- vfp_put_double(dd, vfp_double_pack(vdp));
+ vfp_put_double(vfp_double_pack(vdp), dd);
return ret;
}
@@ -465,7 +465,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
vsd.exponent = 255;
- if (tm & VFP_NAN)
+ if (tm == VFP_QNAN)
vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
goto pack_nan;
} else if (tm & VFP_ZERO)
@@ -476,7 +476,7 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts");
pack_nan:
- vfp_put_float(sd, vfp_single_pack(&vsd));
+ vfp_put_float(vfp_single_pack(&vsd), sd);
return exceptions;
}
@@ -573,7 +573,7 @@ static u32 vfp_double_ftoui(int sd, int unused, int dm, u32 fpscr)
pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
- vfp_put_float(sd, d);
+ vfp_put_float(d, sd);
return exceptions;
}
@@ -648,7 +648,7 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
- vfp_put_float(sd, (s32)d);
+ vfp_put_float((s32)d, sd);
return exceptions;
}
@@ -1084,7 +1084,7 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr)
vdn_nan:
exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
pack:
- vfp_put_double(dd, vfp_double_pack(&vdd));
+ vfp_put_double(vfp_double_pack(&vdd), dd);
return exceptions;
vdm_nan:
@@ -1104,7 +1104,7 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr)
goto pack;
invalid:
- vfp_put_double(dd, vfp_double_pack(&vfp_double_default_qnan));
+ vfp_put_double(vfp_double_pack(&vfp_double_default_qnan), dd);
return FPSCR_IOC;
}
@@ -1127,7 +1127,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int dd = vfp_get_dd(inst);
+ unsigned int dest;
unsigned int dn = vfp_get_dn(inst);
unsigned int dm = vfp_get_dm(inst);
unsigned int vecitr, veclen, vecstride;
@@ -1137,10 +1137,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
/*
+ * fcvtds takes an sN register number as destination, not dN.
+ * It also always operates on scalars.
+ */
+ if ((inst & FEXT_MASK) == FEXT_FCVT) {
+ veclen = 0;
+ dest = vfp_get_sd(inst);
+ } else
+ dest = vfp_get_dd(inst);
+
+ /*
* If destination bank is zero, vector length is always '1'.
* ARM DDI0100F C5.1.3, C5.3.2.
*/
- if (FREG_BANK(dd) == 0)
+ if (FREG_BANK(dest) == 0)
veclen = 0;
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1153,16 +1163,20 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
u32 except;
- if (op == FOP_EXT)
+ if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+ pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
+ vecitr >> FPSCR_LENGTH_BIT,
+ dest, dn, dm);
+ else if (op == FOP_EXT)
pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd, dn, dm);
+ dest, dn, dm);
else
pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd, dn, FOP_TO_IDX(op), dm);
+ dest, dn, FOP_TO_IDX(op), dm);
- except = fop(dd, dn, dm, fpscr);
+ except = fop(dest, dn, dm, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
vecitr >> FPSCR_LENGTH_BIT, except);
@@ -1180,7 +1194,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
* we encounter an exception. We continue.
*/
- dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6);
+ dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
if (FREG_BANK(dm) != 0)
dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index eb683cd7716..e51e6679c40 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -178,12 +178,12 @@ vfp_get_float:
.globl vfp_put_float
vfp_put_float:
- add pc, pc, r0, lsl #3
+ add pc, pc, r1, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- mcr p10, 0, r1, c\dr, c0, 0 @ fmsr r0, s0
+ mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0
mov pc, lr
- mcr p10, 0, r1, c\dr, c0, 4 @ fmsr r0, s1
+ mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1
mov pc, lr
.endr
@@ -203,9 +203,9 @@ vfp_get_double:
.globl vfp_put_double
vfp_put_double:
- add pc, pc, r0, lsl #3
+ add pc, pc, r2, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- fmdrr d\dr, r1, r2
+ fmdrr d\dr, r0, r1
mov pc, lr
.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 9d265d5e748..4178f6cc3d3 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -131,7 +131,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
pr_debug("VFP: raising exceptions %08x\n", exceptions);
- if (exceptions == (u32)-1) {
+ if (exceptions == VFP_EXCEPTION_ERROR) {
vfp_panic("unhandled bounce");
vfp_raise_sigfpe(0, regs);
return;
@@ -170,7 +170,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
*/
static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
{
- u32 exceptions = (u32)-1;
+ u32 exceptions = VFP_EXCEPTION_ERROR;
pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index dae2c2f4605..8f6c179cafb 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -200,7 +200,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce
s32 d = vfp_single_pack(vs);
pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
sd, d, exceptions);
- vfp_put_float(sd, d);
+ vfp_put_float(d, sd);
}
return exceptions;
@@ -257,19 +257,19 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
*/
static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr)
{
- vfp_put_float(sd, vfp_single_packed_abs(m));
+ vfp_put_float(vfp_single_packed_abs(m), sd);
return 0;
}
static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr)
{
- vfp_put_float(sd, m);
+ vfp_put_float(m, sd);
return 0;
}
static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr)
{
- vfp_put_float(sd, vfp_single_packed_negate(m));
+ vfp_put_float(vfp_single_packed_negate(m), sd);
return 0;
}
@@ -333,7 +333,7 @@ static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr)
vsp = &vfp_single_default_qnan;
ret = FPSCR_IOC;
}
- vfp_put_float(sd, vfp_single_pack(vsp));
+ vfp_put_float(vfp_single_pack(vsp), sd);
return ret;
}
@@ -506,7 +506,7 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
*/
if (tm & (VFP_INFINITY|VFP_NAN)) {
vdd.exponent = 2047;
- if (tm & VFP_NAN)
+ if (tm == VFP_QNAN)
vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
goto pack_nan;
} else if (tm & VFP_ZERO)
@@ -514,14 +514,10 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
else
vdd.exponent = vsm.exponent + (1023 - 127);
- /*
- * Technically, if bit 0 of dd is set, this is an invalid
- * instruction. However, we ignore this for efficiency.
- */
return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
pack_nan:
- vfp_put_double(dd, vfp_double_pack(&vdd));
+ vfp_put_double(vfp_double_pack(&vdd), dd);
return exceptions;
}
@@ -617,7 +613,7 @@ static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr)
pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
- vfp_put_float(sd, d);
+ vfp_put_float(d, sd);
return exceptions;
}
@@ -696,7 +692,7 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
- vfp_put_float(sd, (s32)d);
+ vfp_put_float((s32)d, sd);
return exceptions;
}
@@ -1131,7 +1127,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
vsn_nan:
exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
pack:
- vfp_put_float(sd, vfp_single_pack(&vsd));
+ vfp_put_float(vfp_single_pack(&vsd), sd);
return exceptions;
vsm_nan:
@@ -1151,7 +1147,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
goto pack;
invalid:
- vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan));
+ vfp_put_float(vfp_single_pack(&vfp_single_default_qnan), sd);
return FPSCR_IOC;
}
@@ -1174,7 +1170,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int sd = vfp_get_sd(inst);
+ unsigned int dest;
unsigned int sn = vfp_get_sn(inst);
unsigned int sm = vfp_get_sm(inst);
unsigned int vecitr, veclen, vecstride;
@@ -1184,10 +1180,22 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
/*
+ * fcvtsd takes a dN register number as destination, not sN.
+ * Technically, if bit 0 of dd is set, this is an invalid
+ * instruction. However, we ignore this for efficiency.
+ * It also only operates on scalars.
+ */
+ if ((inst & FEXT_MASK) == FEXT_FCVT) {
+ veclen = 0;
+ dest = vfp_get_dd(inst);
+ } else
+ dest = vfp_get_sd(inst);
+
+ /*
* If destination bank is zero, vector length is always '1'.
* ARM DDI0100F C5.1.3, C5.3.2.
*/
- if (FREG_BANK(sd) == 0)
+ if (FREG_BANK(dest) == 0)
veclen = 0;
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1201,15 +1209,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
s32 m = vfp_get_float(sm);
u32 except;
- if (op == FOP_EXT)
+ if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+ pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
+ else if (op == FOP_EXT)
pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m);
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
else
pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, sd, sn,
+ vecitr >> FPSCR_LENGTH_BIT, dest, sn,
FOP_TO_IDX(op), sm, m);
- except = fop(sd, sn, m, fpscr);
+ except = fop(dest, sn, m, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
vecitr >> FPSCR_LENGTH_BIT, except);
@@ -1227,7 +1238,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
* we encounter an exception. We continue.
*/
- sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7);
+ dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
if (FREG_BANK(sm) != 0)
sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index eb79aa2fa8b..a6b8bd89aa2 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,20 +317,14 @@ is386: movl $2,%ecx # set MP
movl %eax,%gs
lldt %ax
cld # gcc2 wants the direction flag cleared at all times
+ pushl %eax # fake return address
#ifdef CONFIG_SMP
movb ready, %cl
movb $1, ready
- cmpb $0,%cl
- je 1f # the first CPU calls start_kernel
- # all other CPUs call initialize_secondary
- call initialize_secondary
- jmp L6
-1:
+ cmpb $0,%cl # the first CPU calls start_kernel
+ jne initialize_secondary # all other CPUs call initialize_secondary
#endif /* CONFIG_SMP */
- call start_kernel
-L6:
- jmp L6 # main should never return here, but
- # just in case, we know what happens.
+ jmp start_kernel
/*
* We depend on ET to be correct. This checks for 287/387.
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index c6737c35815..17647a530b2 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -35,7 +35,7 @@ static int __init init_hpet_clocksource(void)
void __iomem* hpet_base;
u64 tmp;
- if (!hpet_address)
+ if (!is_hpet_enabled())
return -ENODEV;
/* calculate the hpet address: */
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 6cb529f60dc..5fe547cd8f9 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -82,10 +82,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
}
#endif
- if (!irq_desc[irq].handle_irq) {
- __do_IRQ(irq, regs);
- goto out_exit;
- }
#ifdef CONFIG_4KSTACKS
curctx = (union irq_ctx *) current_thread_info();
@@ -125,7 +121,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
#endif
__do_IRQ(irq, regs);
-out_exit:
irq_exit();
return 1;
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f1682206d30..345ffb7d904 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -956,38 +956,6 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0;
}
- /*
- * This function checks if the entire range <start,end> is mapped with type.
- *
- * Note: this function only works correct if the e820 table is sorted and
- * not-overlapping, which is the case
- */
-int __init
-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
-{
- u64 start = s;
- u64 end = e;
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- if (type && ei->type != type)
- continue;
- /* is the region (part) in overlap with the current region ?*/
- if (ei->addr >= end || ei->addr + ei->size <= start)
- continue;
- /* if the region is at the beginning of <start,end> we move
- * start to the end of the region since it's ok until there
- */
- if (ei->addr <= start)
- start = ei->addr + ei->size;
- /* if start is now at or beyond end, we're done, full
- * coverage */
- if (start >= end)
- return 1; /* we're done */
- }
- return 0;
-}
-
/*
* Find the highest page frame number we have available
*/
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 82e0fd02af1..7e9edafffd8 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
+#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
@@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (unwind_init_blocked(&info, task) == 0)
unw_ret = show_trace_unwind(&info, log_lvl);
}
- if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
-#ifdef CONFIG_STACK_UNWIND
- print_symbol("DWARF2 unwinder stuck at %s\n",
- UNW_PC(&info));
- if (call_trace == 1) {
- printk("Leftover inexact backtrace:\n");
- if (UNW_SP(&info))
+ if (unw_ret > 0) {
+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+ print_symbol("DWARF2 unwinder stuck at %s\n",
+ UNW_PC(&info));
+ if (UNW_SP(&info) >= PAGE_OFFSET) {
+ printk("Leftover inexact backtrace:\n");
stack = (void *)UNW_SP(&info);
- } else if (call_trace > 1)
+ } else
+ printk("Full inexact backtrace again:\n");
+ } else if (call_trace >= 1)
return;
else
printk("Full inexact backtrace again:\n");
-#else
+ } else
printk("Inexact backtrace:\n");
-#endif
- }
}
if (task == current) {
@@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);
+#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
@@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s)
return 1;
}
__setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 0a362e3aeac..1220dd828ce 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -237,6 +237,11 @@ char * __devinit pcibios_setup(char *str)
pci_probe &= ~PCI_PROBE_MMCONF;
return NULL;
}
+ /* override DMI blacklist */
+ else if (!strcmp(str, "mmconf")) {
+ pci_probe |= PCI_PROBE_MMCONF_FORCE;
+ return NULL;
+ }
#endif
else if (!strcmp(str, "noacpi")) {
acpi_noirq_set();
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 972180f738d..ef5a2faa7d8 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <asm/e820.h>
#include "pci.h"
@@ -187,9 +188,31 @@ static __init void unreachable_devices(void)
}
}
+static int disable_mcfg(struct dmi_system_id *d)
+{
+ printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+ /* Has broken MCFG table that makes the system hang when used */
+ {
+ .callback = disable_mcfg,
+ .ident = "Intel D3C5105 SDV",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+ },
+ },
+ {}
+};
+
void __init pci_mmcfg_init(void)
{
- if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ dmi_check_system(dmi_bad_mcfg);
+
+ if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -198,15 +221,6 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
- pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
- E820_RESERVED)) {
- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
- pci_mmcfg_config[0].base_address);
- printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
- return;
- }
-
printk(KERN_INFO "PCI: Using MMCONFIG\n");
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index bf4e7933538..49a849b3a24 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -16,7 +16,8 @@
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008
-#define PCI_PROBE_MASK 0x000f
+#define PCI_PROBE_MMCONF_FORCE 0x0010
+#define PCI_PROBE_MASK 0x00ff
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 47de9ee6bcd..674de894347 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -258,7 +258,7 @@ config NR_CPUS
int "Maximum number of CPUs (2-1024)"
range 2 1024
depends on SMP
- default "64"
+ default "1024"
help
You should set this to the number of CPUs in your system, but
keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but
@@ -354,7 +354,7 @@ config NUMA
config NODES_SHIFT
int "Max num nodes shift(3-10)"
range 3 10
- default "8"
+ default "10"
depends on NEED_MULTIPLE_NODES
help
This option specifies the maximum number of nodes in your SSI system.
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index d24fa393b18..f648c610b10 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -67,10 +67,8 @@ static int __init topology_init(void)
#endif
sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
- if (!sysfs_cpus) {
- err = -ENOMEM;
- goto out;
- }
+ if (!sysfs_cpus)
+ panic("kzalloc in topology_init failed - NR_CPUS too big?");
for_each_present_cpu(i) {
if((err = arch_register_cpu(i)))
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index c2f69f7942a..1f3540826e6 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -279,8 +279,8 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
return part->reason;
}
- bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),
- (u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);
+ bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt,
+ (BTE_NORMAL | BTE_WACQUIRE), NULL);
if (bte_ret == BTE_SUCCESS) {
return xpcSuccess;
}
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 5e8e59efb34..4d026f9dd98 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -1052,6 +1052,8 @@ xpc_do_exit(enum xpc_retval reason)
if (xpc_sysctl) {
unregister_sysctl_table(xpc_sysctl);
}
+
+ kfree(xpc_remote_copy_buffer_base);
}
@@ -1212,24 +1214,20 @@ xpc_init(void)
partid_t partid;
struct xpc_partition *part;
pid_t pid;
+ size_t buf_size;
if (!ia64_platform_is("sn2")) {
return -ENODEV;
}
- /*
- * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
- * various portions of a partition's reserved page. Its size is based
- * on the size of the reserved page header and part_nasids mask. So we
- * need to ensure that the other items will fit as well.
- */
- if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {
- dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
- return -EPERM;
- }
- DBUG_ON((u64) xpc_remote_copy_buffer !=
- L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));
+
+ buf_size = max(XPC_RP_VARS_SIZE,
+ XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
+ xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
+ GFP_KERNEL, &xpc_remote_copy_buffer_base);
+ if (xpc_remote_copy_buffer == NULL)
+ return -ENOMEM;
snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
@@ -1293,6 +1291,8 @@ xpc_init(void)
if (xpc_sysctl) {
unregister_sysctl_table(xpc_sysctl);
}
+
+ kfree(xpc_remote_copy_buffer_base);
return -EBUSY;
}
@@ -1311,6 +1311,8 @@ xpc_init(void)
if (xpc_sysctl) {
unregister_sysctl_table(xpc_sysctl);
}
+
+ kfree(xpc_remote_copy_buffer_base);
return -EBUSY;
}
@@ -1362,6 +1364,8 @@ xpc_init(void)
if (xpc_sysctl) {
unregister_sysctl_table(xpc_sysctl);
}
+
+ kfree(xpc_remote_copy_buffer_base);
return -EBUSY;
}
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 2a89cfce495..57c723f5cba 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -71,19 +71,15 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
* Generic buffer used to store a local copy of portions of a remote
* partition's reserved page (either its header and part_nasids mask,
* or its vars).
- *
- * xpc_discovery runs only once and is a seperate thread that is
- * very likely going to be processing in parallel with receiving
- * interrupts.
*/
-char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
- XP_NASID_MASK_BYTES];
+char *xpc_remote_copy_buffer;
+void *xpc_remote_copy_buffer_base;
/*
* Guarantee that the kmalloc'd memory is cacheline aligned.
*/
-static void *
+void *
xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
{
/* see if kmalloc will give us cachline aligned memory by default */
@@ -148,7 +144,7 @@ xpc_get_rsvd_page_pa(int nasid)
}
}
- bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len,
+ bte_res = xp_bte_copy(rp_pa, buf, buf_len,
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
if (bte_res != BTE_SUCCESS) {
dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
@@ -447,7 +443,7 @@ xpc_check_remote_hb(void)
/* pull the remote_hb cache line */
bres = xp_bte_copy(part->remote_vars_pa,
- ia64_tpa((u64) remote_vars),
+ (u64) remote_vars,
XPC_RP_VARS_SIZE,
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
if (bres != BTE_SUCCESS) {
@@ -498,8 +494,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
/* pull over the reserved page header and part_nasids mask */
-
- bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
+ bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp,
XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
if (bres != BTE_SUCCESS) {
@@ -554,11 +549,8 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
return xpcVarsNotSet;
}
-
/* pull over the cross partition variables */
-
- bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
- XPC_RP_VARS_SIZE,
+ bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE,
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
if (bres != BTE_SUCCESS) {
return xpc_map_bte_errors(bres);
@@ -1239,7 +1231,7 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
- bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
+ bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask,
xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
return xpc_map_bte_errors(bte_res);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index abb325eb8f7..4d4b6fb156e 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -354,6 +354,7 @@ endchoice
config PPC_PSERIES
depends on PPC_MULTIPLATFORM && PPC64
bool "IBM pSeries & new (POWER5-based) iSeries"
+ select MPIC
select PPC_I8259
select PPC_RTAS
select RTAS_ERROR_LOGGING
@@ -363,6 +364,7 @@ config PPC_PSERIES
config PPC_CHRP
bool "Common Hardware Reference Platform (CHRP) based machines"
depends on PPC_MULTIPLATFORM && PPC32
+ select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_RTAS
@@ -373,6 +375,7 @@ config PPC_CHRP
config PPC_PMAC
bool "Apple PowerMac based machines"
depends on PPC_MULTIPLATFORM
+ select MPIC
select PPC_INDIRECT_PCI if PPC32
select PPC_MPC106 if PPC32
default y
@@ -380,6 +383,7 @@ config PPC_PMAC
config PPC_PMAC64
bool
depends on PPC_PMAC && POWER4
+ select MPIC
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
@@ -389,6 +393,7 @@ config PPC_PMAC64
config PPC_PREP
bool "PowerPC Reference Platform (PReP) based machines"
depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
+ select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_UDBG_16550
@@ -397,6 +402,7 @@ config PPC_PREP
config PPC_MAPLE
depends on PPC_MULTIPLATFORM && PPC64
bool "Maple 970FX Evaluation Board"
+ select MPIC
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
@@ -439,12 +445,6 @@ config U3_DART
depends on PPC_MULTIPLATFORM && PPC64
default n
-config MPIC
- depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
- || MPC7448HPC2
- bool
- default y
-
config PPC_RTAS
bool
default n
@@ -812,6 +812,14 @@ config GENERIC_ISA_DMA
depends on PPC64 || POWER4 || 6xx && !CPM2
default y
+config MPIC
+ bool
+ default n
+
+config MPIC_WEIRD
+ bool
+ default n
+
config PPC_I8259
bool
default n
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
new file mode 100644
index 00000000000..d7b985e6bd2
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -0,0 +1,190 @@
+/*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at freescale.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.
+ */
+
+
+/ {
+ model = "mpc7448hpc2";
+ compatible = "mpc74xx";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ linux,phandle = <100>;
+
+ cpus {
+ #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells =<0>;
+ linux,phandle = <200>;
+
+ PowerPC,7448@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <20>; // 32 bytes
+ i-cache-line-size = <20>; // 32 bytes
+ d-cache-size = <8000>; // L1, 32K bytes
+ i-cache-size = <8000>; // L1, 32K bytes
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ clock-frequency = <0>; // From U-Boot
+ bus-frequency = <0>; // From U-Boot
+ 32-bit;
+ linux,phandle = <201>;
+ linux,boot-cpu;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ linux,phandle = <300>;
+ reg = <00000000 20000000 // DDR2 512M at 0
+ >;
+ };
+
+ tsi108@c0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "tsi-bridge";
+ ranges = <00000000 c0000000 00010000>;
+ reg = <c0000000 00010000>;
+ bus-frequency = <0>;
+
+ i2c@7000 {
+ interrupt-parent = <7400>;
+ interrupts = <E 0>;
+ reg = <7000 400>;
+ device_type = "i2c";
+ compatible = "tsi-i2c";
+ };
+
+ mdio@6000 {
+ device_type = "mdio";
+ compatible = "tsi-ethernet";
+
+ ethernet-phy@6000 {
+ linux,phandle = <6000>;
+ interrupt-parent = <7400>;
+ interrupts = <2 1>;
+ reg = <6000 50>;
+ phy-id = <8>;
+ device_type = "ethernet-phy";
+ };
+
+ ethernet-phy@6400 {
+ linux,phandle = <6400>;
+ interrupt-parent = <7400>;
+ interrupts = <2 1>;
+ reg = <6000 50>;
+ phy-id = <9>;
+ device_type = "ethernet-phy";
+ };
+
+ };
+
+ ethernet@6200 {
+ #size-cells = <0>;
+ device_type = "network";
+ model = "TSI-ETH";
+ compatible = "tsi-ethernet";
+ reg = <6000 200>;
+ address = [ 00 06 D2 00 00 01 ];
+ interrupts = <10 2>;
+ interrupt-parent = <7400>;
+ phy-handle = <6000>;
+ };
+
+ ethernet@6600 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "network";
+ model = "TSI-ETH";
+ compatible = "tsi-ethernet";
+ reg = <6400 200>;
+ address = [ 00 06 D2 00 00 02 ];
+ interrupts = <11 2>;
+ interrupt-parent = <7400>;
+ phy-handle = <6400>;
+ };
+
+ serial@7808 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <7808 200>;
+ clock-frequency = <3f6b5a00>;
+ interrupts = <c 0>;
+ interrupt-parent = <7400>;
+ };
+
+ serial@7c08 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <7c08 200>;
+ clock-frequency = <3f6b5a00>;
+ interrupts = <d 0>;
+ interrupt-parent = <7400>;
+ };
+
+ pic@7400 {
+ linux,phandle = <7400>;
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <7400 400>;
+ built-in;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+ };
+ pci@1000 {
+ compatible = "tsi10x";
+ device_type = "pci";
+ linux,phandle = <1000>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <1000 1000>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 e0000000 e0000000 0 1A000000
+ 01000000 0 00000000 fa000000 0 00010000>;
+ clock-frequency = <7f28154>;
+ interrupt-parent = <7400>;
+ interrupts = <17 2>;
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 */
+ 0800 0 0 1 7400 24 0
+ 0800 0 0 2 7400 25 0
+ 0800 0 0 3 7400 26 0
+ 0800 0 0 4 7400 27 0
+
+ /* IDSEL 0x12 */
+ 1000 0 0 1 7400 25 0
+ 1000 0 0 2 7400 26 0
+ 1000 0 0 3 7400 27 0
+ 1000 0 0 4 7400 24 0
+
+ /* IDSEL 0x13 */
+ 1800 0 0 1 7400 26 0
+ 1800 0 0 2 7400 27 0
+ 1800 0 0 3 7400 24 0
+ 1800 0 0 4 7400 25 0
+
+ /* IDSEL 0x14 */
+ 2000 0 0 1 7400 27 0
+ 2000 0 0 2 7400 24 0
+ 2000 0 0 3 7400 25 0
+ 2000 0 0 4 7400 26 0
+ >;
+ };
+ };
+
+};
diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts
new file mode 100644
index 00000000000..12f5dbf3055
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emds.dts
@@ -0,0 +1,328 @@
+/*
+ * MPC8349E MDS Device Tree Source
+ *
+ * Copyright 2005, 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+/ {
+ model = "MPC8349EMDS";
+ compatible = "MPC834xMDS";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8349@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <20>; // 32 bytes
+ i-cache-line-size = <20>; // 32 bytes
+ d-cache-size = <8000>; // L1, 32K
+ i-cache-size = <8000>; // L1, 32K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ 32-bit;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <00000000 10000000>; // 256MB at 0
+ };
+
+ soc8349@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "soc";
+ ranges = <0 e0000000 00100000>;
+ reg = <e0000000 00000200>;
+ bus-frequency = <0>;
+
+ wdt@200 {
+ device_type = "watchdog";
+ compatible = "mpc83xx_wdt";
+ reg = <200 100>;
+ };
+
+ i2c@3000 {
+ device_type = "i2c";
+ compatible = "fsl-i2c";
+ reg = <3000 100>;
+ interrupts = <e 8>;
+ interrupt-parent = <700>;
+ dfsrr;
+ };
+
+ i2c@3100 {
+ device_type = "i2c";
+ compatible = "fsl-i2c";
+ reg = <3100 100>;
+ interrupts = <f 8>;
+ interrupt-parent = <700>;
+ dfsrr;
+ };
+
+ spi@7000 {
+ device_type = "spi";
+ compatible = "mpc83xx_spi";
+ reg = <7000 1000>;
+ interrupts = <10 8>;
+ interrupt-parent = <700>;
+ mode = <0>;
+ };
+
+ /* phy type (ULPI or SERIAL) are only types supportted for MPH */
+ /* port = 0 or 1 */
+ usb@22000 {
+ device_type = "usb";
+ compatible = "fsl-usb2-mph";
+ reg = <22000 1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <700>;
+ interrupts = <27 2>;
+ phy_type = "ulpi";
+ port1;
+ };
+ /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+ usb@23000 {
+ device_type = "usb";
+ compatible = "fsl-usb2-dr";
+ reg = <23000 1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <700>;
+ interrupts = <26 2>;
+ phy_type = "ulpi";
+ };
+
+ mdio@24520 {
+ device_type = "mdio";
+ compatible = "gianfar";
+ reg = <24520 20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ linux,phandle = <24520>;
+ ethernet-phy@0 {
+ linux,phandle = <2452000>;
+ interrupt-parent = <700>;
+ interrupts = <11 2>;
+ reg = <0>;
+ device_type = "ethernet-phy";
+ };
+ ethernet-phy@1 {
+ linux,phandle = <2452001>;
+ interrupt-parent = <700>;
+ interrupts = <12 2>;
+ reg = <1>;
+ device_type = "ethernet-phy";
+ };
+ };
+
+ ethernet@24000 {
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <24000 1000>;
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <20 8 21 8 22 8>;
+ interrupt-parent = <700>;
+ phy-handle = <2452000>;
+ };
+
+ ethernet@25000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+ reg = <25000 1000>;
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 8 24 8 25 8>;
+ interrupt-parent = <700>;
+ phy-handle = <2452001>;
+ };
+
+ serial@4500 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <4500 100>;
+ clock-frequency = <0>;
+ interrupts = <9 8>;
+ interrupt-parent = <700>;
+ };
+
+ serial@4600 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <4600 100>;
+ clock-frequency = <0>;
+ interrupts = <a 8>;
+ interrupt-parent = <700>;
+ };
+
+ pci@8500 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 */
+ 8800 0 0 1 700 14 8
+ 8800 0 0 2 700 15 8
+ 8800 0 0 3 700 16 8
+ 8800 0 0 4 700 17 8
+
+ /* IDSEL 0x12 */
+ 9000 0 0 1 700 16 8
+ 9000 0 0 2 700 17 8
+ 9000 0 0 3 700 14 8
+ 9000 0 0 4 700 15 8
+
+ /* IDSEL 0x13 */
+ 9800 0 0 1 700 17 8
+ 9800 0 0 2 700 14 8
+ 9800 0 0 3 700 15 8
+ 9800 0 0 4 700 16 8
+
+ /* IDSEL 0x15 */
+ a800 0 0 1 700 14 8
+ a800 0 0 2 700 15 8
+ a800 0 0 3 700 16 8
+ a800 0 0 4 700 17 8
+
+ /* IDSEL 0x16 */
+ b000 0 0 1 700 17 8
+ b000 0 0 2 700 14 8
+ b000 0 0 3 700 15 8
+ b000 0 0 4 700 16 8
+
+ /* IDSEL 0x17 */
+ b800 0 0 1 700 16 8
+ b800 0 0 2 700 17 8
+ b800 0 0 3 700 14 8
+ b800 0 0 4 700 15 8
+
+ /* IDSEL 0x18 */
+ b000 0 0 1 700 15 8
+ b000 0 0 2 700 16 8
+ b000 0 0 3 700 17 8
+ b000 0 0 4 700 14 8>;
+ interrupt-parent = <700>;
+ interrupts = <42 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 a0000000 a0000000 0 10000000
+ 42000000 0 80000000 80000000 0 10000000
+ 01000000 0 00000000 e2000000 0 00100000>;
+ clock-frequency = <3f940aa>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <8500 100>;
+ compatible = "83xx";
+ device_type = "pci";
+ };
+
+ pci@8600 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 */
+ 8800 0 0 1 700 14 8
+ 8800 0 0 2 700 15 8
+ 8800 0 0 3 700 16 8
+ 8800 0 0 4 700 17 8
+
+ /* IDSEL 0x12 */
+ 9000 0 0 1 700 16 8
+ 9000 0 0 2 700 17 8
+ 9000 0 0 3 700 14 8
+ 9000 0 0 4 700 15 8
+
+ /* IDSEL 0x13 */
+ 9800 0 0 1 700 17 8
+ 9800 0 0 2 700 14 8
+ 9800 0 0 3 700 15 8
+ 9800 0 0 4 700 16 8
+
+ /* IDSEL 0x15 */
+ a800 0 0 1 700 14 8
+ a800 0 0 2 700 15 8
+ a800 0 0 3 700 16 8
+ a800 0 0 4 700 17 8
+
+ /* IDSEL 0x16 */
+ b000 0 0 1 700 17 8
+ b000 0 0 2 700 14 8
+ b000 0 0 3 700 15 8
+ b000 0 0 4 700 16 8
+
+ /* IDSEL 0x17 */
+ b800 0 0 1 700 16 8
+ b800 0 0 2 700 17 8
+ b800 0 0 3 700 14 8
+ b800 0 0 4 700 15 8
+
+ /* IDSEL 0x18 */
+ b000 0 0 1 700 15 8
+ b000 0 0 2 700 16 8
+ b000 0 0 3 700 17 8
+ b000 0 0 4 700 14 8>;
+ interrupt-parent = <700>;
+ interrupts = <42 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 b0000000 b0000000 0 10000000
+ 42000000 0 90000000 90000000 0 10000000
+ 01000000 0 00000000 e2100000 0 00100000>;
+ clock-frequency = <3f940aa>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <8600 100>;
+ compatible = "83xx";
+ device_type = "pci";
+ };
+
+ /* May need to remove if on a part without crypto engine */
+ crypto@30000 {
+ device_type = "crypto";
+ model = "SEC2";
+ compatible = "talitos";
+ reg = <30000 10000>;
+ interrupts = <b 8>;
+ interrupt-parent = <700>;
+ num-channels = <4>;
+ channel-fifo-len = <18>;
+ exec-units-mask = <0000007e>;
+ /* desc mask is for rev2.0,
+ * we need runtime fixup for >2.0 */
+ descriptor-types-mask = <01010ebf>;
+ };
+
+ /* IPIC
+ * interrupts cell = <intr #, sense>
+ * sense values match linux IORESOURCE_IRQ_* defines:
+ * sense == 8: Level, low assertion
+ * sense == 2: Edge, high-to-low change
+ */
+ pic@700 {
+ linux,phandle = <700>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <700 100>;
+ built-in;
+ device_type = "ipic";
+ };
+ };
+};
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 5078b0441d6..5078b0441d6 100644
--- a/arch/powerpc/configs/mpc834x_sys_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 7e2c9fe44ac..821e152e093 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -2,6 +2,11 @@
* FPU support code, moved here from head.S so that it can be used
* by chips which use other head-whatever.S files.
*
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
* 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
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 7ee68543331..12c5971d656 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -322,7 +322,8 @@ EXPORT_SYMBOL(do_softirq);
static LIST_HEAD(irq_hosts);
static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED;
-
+static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
+static unsigned int irq_radix_writer;
struct irq_map_entry irq_map[NR_IRQS];
static unsigned int irq_virq_count = NR_IRQS;
static struct irq_host *irq_default_host;
@@ -455,6 +456,58 @@ void irq_set_virq_count(unsigned int count)
irq_virq_count = count;
}
+/* radix tree not lockless safe ! we use a brlock-type mecanism
+ * for now, until we can use a lockless radix tree
+ */
+static void irq_radix_wrlock(unsigned long *flags)
+{
+ unsigned int cpu, ok;
+
+ spin_lock_irqsave(&irq_big_lock, *flags);
+ irq_radix_writer = 1;
+ smp_mb();
+ do {
+ barrier();
+ ok = 1;
+ for_each_possible_cpu(cpu) {
+ if (per_cpu(irq_radix_reader, cpu)) {
+ ok = 0;
+ break;
+ }
+ }
+ if (!ok)
+ cpu_relax();
+ } while(!ok);
+}
+
+static void irq_radix_wrunlock(unsigned long flags)
+{
+ smp_wmb();
+ irq_radix_writer = 0;
+ spin_unlock_irqrestore(&irq_big_lock, flags);
+}
+
+static void irq_radix_rdlock(unsigned long *flags)
+{
+ local_irq_save(*flags);
+ __get_cpu_var(irq_radix_reader) = 1;
+ smp_mb();
+ if (likely(irq_radix_writer == 0))
+ return;
+ __get_cpu_var(irq_radix_reader) = 0;
+ smp_wmb();
+ spin_lock(&irq_big_lock);
+ __get_cpu_var(irq_radix_reader) = 1;
+ spin_unlock(&irq_big_lock);
+}
+
+static void irq_radix_rdunlock(unsigned long flags)
+{
+ __get_cpu_var(irq_radix_reader) = 0;
+ local_irq_restore(flags);
+}
+
+
unsigned int irq_create_mapping(struct irq_host *host,
irq_hw_number_t hwirq)
{
@@ -604,13 +657,9 @@ void irq_dispose_mapping(unsigned int virq)
/* Check if radix tree allocated yet */
if (host->revmap_data.tree.gfp_mask == 0)
break;
- /* XXX radix tree not safe ! remove lock whem it becomes safe
- * and use some RCU sync to make sure everything is ok before we
- * can re-use that map entry
- */
- spin_lock_irqsave(&irq_big_lock, flags);
+ irq_radix_wrlock(&flags);
radix_tree_delete(&host->revmap_data.tree, hwirq);
- spin_unlock_irqrestore(&irq_big_lock, flags);
+ irq_radix_wrunlock(flags);
break;
}
@@ -677,25 +726,24 @@ unsigned int irq_radix_revmap(struct irq_host *host,
if (tree->gfp_mask == 0)
return irq_find_mapping(host, hwirq);
- /* XXX Current radix trees are NOT SMP safe !!! Remove that lock
- * when that is fixed (when Nick's patch gets in
- */
- spin_lock_irqsave(&irq_big_lock, flags);
-
/* Now try to resolve */
+ irq_radix_rdlock(&flags);
ptr = radix_tree_lookup(tree, hwirq);
+ irq_radix_rdunlock(flags);
+
/* Found it, return */
if (ptr) {
virq = ptr - irq_map;
- goto bail;
+ return virq;
}
/* If not there, try to insert it */
virq = irq_find_mapping(host, hwirq);
- if (virq != NO_IRQ)
+ if (virq != NO_IRQ) {
+ irq_radix_wrlock(&flags);
radix_tree_insert(tree, hwirq, &irq_map[virq]);
- bail:
- spin_unlock_irqrestore(&irq_big_lock, flags);
+ irq_radix_wrunlock(flags);
+ }
return virq;
}
@@ -806,12 +854,12 @@ static int irq_late_init(void)
struct irq_host *h;
unsigned long flags;
- spin_lock_irqsave(&irq_big_lock, flags);
+ irq_radix_wrlock(&flags);
list_for_each_entry(h, &irq_hosts, link) {
if (h->revmap_type == IRQ_HOST_MAP_TREE)
INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
}
- spin_unlock_irqrestore(&irq_big_lock, flags);
+ irq_radix_wrunlock(flags);
return 0;
}
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 2fce7738e9e..138134c8c17 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1289,6 +1289,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+#ifdef DEBUG
+ memset(&oirq, 0xff, sizeof(oirq));
+#endif
/* Try to get a mapping from the device-tree */
if (of_irq_map_pci(pci_dev, &oirq)) {
u8 line, pin;
@@ -1314,8 +1317,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
if (virq != NO_IRQ)
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
} else {
- DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
- oirq.size, oirq.specifier[0], oirq.controller->full_name);
+ DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+ oirq.size, oirq.specifier[0], oirq.specifier[1],
+ oirq.controller->full_name);
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
@@ -1324,6 +1328,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
DBG(" -> failed to map !\n");
return -1;
}
+
+ DBG(" -> mapped to linux irq %d\n", virq);
+
pci_dev->irq = virq;
pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq);
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index f6a05f090b2..39d3bfcabcd 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -126,10 +126,6 @@ EXPORT_SYMBOL(pci_bus_mem_base_phys);
EXPORT_SYMBOL(pci_bus_to_hose);
#endif /* CONFIG_PCI */
-#ifdef CONFIG_NOT_COHERENT_CACHE
-EXPORT_SYMBOL(flush_dcache_all);
-#endif
-
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 462bced40c1..4394e545f9f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -646,13 +646,13 @@ static unsigned char ibm_architecture_vec[] = {
5 - 1, /* 5 option vectors */
/* option vector 1: processor architectures supported */
- 3 - 1, /* length */
+ 3 - 2, /* length */
0, /* don't ignore, don't halt */
OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
OV1_PPC_2_04 | OV1_PPC_2_05,
/* option vector 2: Open Firmware options supported */
- 34 - 1, /* length */
+ 34 - 2, /* length */
OV2_REAL_MODE,
0, 0,
W(0xffffffff), /* real_base */
@@ -666,16 +666,16 @@ static unsigned char ibm_architecture_vec[] = {
48, /* max log_2(hash table size) */
/* option vector 3: processor options supported */
- 3 - 1, /* length */
+ 3 - 2, /* length */
0, /* don't ignore, don't halt */
OV3_FP | OV3_VMX,
/* option vector 4: IBM PAPR implementation */
- 2 - 1, /* length */
+ 2 - 2, /* length */
0, /* don't halt */
/* option vector 5: PAPR/OF options */
- 3 - 1, /* length */
+ 3 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
};
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 11052c212ad..a10825a5dfe 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -639,14 +639,17 @@ void of_irq_map_init(unsigned int flags)
}
-int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
- struct of_irq *out_irq)
+int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
+ u32 *addr, struct of_irq *out_irq)
{
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
u32 *tmp, *imap, *imask;
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
int imaplen, match, i;
+ DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+ parent->full_name, intspec[0], intspec[1], ointsize);
+
ipar = of_node_get(parent);
/* First get the #interrupt-cells property of the current cursor
@@ -670,6 +673,9 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
+ if (ointsize != intsize)
+ return -EINVAL;
+
/* Look for this #address-cells. We have to implement the old linux
* trick of looking for the parent here as some device-trees rely on it
*/
@@ -875,12 +881,15 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
}
intsize = *tmp;
+ DBG(" intsize=%d intlen=%d\n", intsize, intlen);
+
/* Check index */
if ((index + 1) * intsize > intlen)
return -EINVAL;
/* Get new specifier and map it */
- res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq);
+ res = of_irq_map_raw(p, intspec + index * intsize, intsize,
+ addr, out_irq);
of_node_put(p);
return res;
}
@@ -965,7 +974,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
laddr[0] = (pdev->bus->number << 16)
| (pdev->devfn << 8);
laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, laddr, out_irq);
+ return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
}
EXPORT_SYMBOL_GPL(of_irq_map_pci);
#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index f19e2e0e61e..de59c6c31a5 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -45,8 +45,9 @@ void __devinit smp_generic_take_timebase(void)
{
int cmd;
u64 tb;
+ unsigned long flags;
- local_irq_disable();
+ local_irq_save(flags);
while (!running)
barrier();
rmb();
@@ -70,7 +71,7 @@ void __devinit smp_generic_take_timebase(void)
set_tb(tb >> 32, tb & 0xfffffffful);
enter_contest(tbsync->mark, -1);
}
- local_irq_enable();
+ local_irq_restore(flags);
}
static int __devinit start_contest(int cmd, long offset, int num)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 18e59e43d2b..a124499e65d 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -125,15 +125,8 @@ static long timezone_offset;
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
-u64 tb_last_jiffy __cacheline_aligned_in_smp;
-unsigned long tb_last_stamp;
-
-/*
- * Note that on ppc32 this only stores the bottom 32 bits of
- * the timebase value, but that's enough to tell when a jiffy
- * has passed.
- */
-DEFINE_PER_CPU(unsigned long, last_jiffy);
+static u64 tb_last_jiffy __cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(u64, last_jiffy);
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
/*
@@ -458,7 +451,7 @@ void do_gettimeofday(struct timeval *tv)
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
sec = xtime.tv_sec;
- nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp);
+ nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
usec = nsec / 1000;
while (usec >= 1000000) {
@@ -700,7 +693,6 @@ void timer_interrupt(struct pt_regs * regs)
tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
tb_last_jiffy = tb_next_jiffy;
- tb_last_stamp = per_cpu(last_jiffy, cpu);
do_timer(regs);
timer_recalc_offset(tb_last_jiffy);
timer_check_rtc();
@@ -749,7 +741,7 @@ void __init smp_space_timers(unsigned int max_cpus)
int i;
unsigned long half = tb_ticks_per_jiffy / 2;
unsigned long offset = tb_ticks_per_jiffy / max_cpus;
- unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
+ u64 previous_tb = per_cpu(last_jiffy, boot_cpuid);
/* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
previous_tb -= tb_ticks_per_jiffy;
@@ -830,7 +822,7 @@ int do_settimeofday(struct timespec *tv)
* and therefore the (jiffies - wall_jiffies) computation
* has been removed.
*/
- tb_delta = tb_ticks_since(tb_last_stamp);
+ tb_delta = tb_ticks_since(tb_last_jiffy);
tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
@@ -950,8 +942,7 @@ void __init time_init(void)
if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
ppc_tb_freq = 1000000000;
- tb_last_stamp = get_rtcl();
- tb_last_jiffy = tb_last_stamp;
+ tb_last_jiffy = get_rtcl();
} else {
/* Normal PowerPC with timebase register */
ppc_md.calibrate_decr();
@@ -959,7 +950,7 @@ void __init time_init(void)
ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n",
ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
- tb_last_stamp = tb_last_jiffy = get_tb();
+ tb_last_jiffy = get_tb();
}
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
@@ -1036,7 +1027,7 @@ void __init time_init(void)
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
- __get_cpu_var(last_jiffy) = tb_last_stamp;
+ __get_cpu_var(last_jiffy) = tb_last_jiffy;
do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
do_gtod.varp->tb_to_xs = tb_to_xs;
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
index fd66acfd3e3..7173ba98f42 100644
--- a/arch/powerpc/lib/memcpy_64.S
+++ b/arch/powerpc/lib/memcpy_64.S
@@ -11,6 +11,7 @@
.align 7
_GLOBAL(memcpy)
+ std r3,48(r1) /* save destination pointer for return value */
mtcrf 0x01,r5
cmpldi cr1,r5,16
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
@@ -38,7 +39,7 @@ _GLOBAL(memcpy)
stdu r9,16(r3)
bdnz 1b
3: std r8,8(r3)
- beqlr
+ beq 3f
addi r3,r3,16
ld r9,8(r4)
.Ldo_tail:
@@ -53,7 +54,8 @@ _GLOBAL(memcpy)
2: bf cr7*4+3,3f
rotldi r9,r9,8
stb r9,0(r3)
-3: blr
+3: ld r3,48(r1) /* return dest pointer */
+ blr
.Lsrc_unaligned:
srdi r6,r5,3
@@ -115,7 +117,7 @@ _GLOBAL(memcpy)
5: srd r12,r9,r11
or r12,r8,r12
std r12,24(r3)
- beqlr
+ beq 4f
cmpwi cr1,r5,8
addi r3,r3,32
sld r9,r9,r10
@@ -167,4 +169,5 @@ _GLOBAL(memcpy)
3: bf cr7*4+3,4f
lbz r0,0(r4)
stb r0,0(r3)
-4: blr
+4: ld r3,48(r1) /* return dest pointer */
+ blr
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 376829ed221..0a0a0487b33 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -103,7 +103,7 @@ unsigned long __init mmu_mapin_ram(void)
/* Determine number of entries necessary to cover lowmem */
pinned_tlbs = (unsigned int)
- (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT);
+ (_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT);
/* Write upper watermark to save location */
tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
@@ -111,7 +111,7 @@ unsigned long __init mmu_mapin_ram(void)
/* If necessary, set additional pinned TLBs */
if (pinned_tlbs > 1)
for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
- unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
+ unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE;
ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
}
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index b46305645d3..cf3967a66fb 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,26 +46,6 @@ unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
#endif
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */
- {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */
- {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */
- };
-
- const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif /* CONFIG_PCI */
-
/* ************************************************************************
*
* Setup the architecture
@@ -92,8 +72,6 @@ static void __init mpc834x_itx_setup_arch(void)
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = mpc83xx_map_irq;
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
@@ -106,25 +84,13 @@ static void __init mpc834x_itx_setup_arch(void)
void __init mpc834x_itx_init_IRQ(void)
{
- u8 senses[8] = {
- 0, /* EXT 0 */
- IRQ_SENSE_LEVEL, /* EXT 1 */
- IRQ_SENSE_LEVEL, /* EXT 2 */
- 0, /* EXT 3 */
-#ifdef CONFIG_PCI
- IRQ_SENSE_LEVEL, /* EXT 4 */
- IRQ_SENSE_LEVEL, /* EXT 5 */
- IRQ_SENSE_LEVEL, /* EXT 6 */
- IRQ_SENSE_LEVEL, /* EXT 7 */
-#else
- 0, /* EXT 4 */
- 0, /* EXT 5 */
- 0, /* EXT 6 */
- 0, /* EXT 7 */
-#endif
- };
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (!np)
+ return;
- ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+ ipic_init(np, 0);
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
@@ -153,4 +119,7 @@ define_machine(mpc834x_itx) {
.time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup = mpc83xx_pcibios_fixup,
+#endif
};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 3e1c16eb4a6..32df239d1c4 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -43,33 +43,6 @@ unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
#endif
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
- {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
- {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */
- {0, 0, 0, 0},
- {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
- {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
- {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
- {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
- {0, 0, 0, 0}, /* idsel 0x19 */
- {0, 0, 0, 0}, /* idsel 0x20 */
- };
-
- const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif /* CONFIG_PCI */
-
/* ************************************************************************
*
* Setup the architecture
@@ -96,8 +69,6 @@ static void __init mpc834x_sys_setup_arch(void)
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = mpc83xx_map_irq;
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
@@ -110,25 +81,13 @@ static void __init mpc834x_sys_setup_arch(void)
void __init mpc834x_sys_init_IRQ(void)
{
- u8 senses[8] = {
- 0, /* EXT 0 */
- IRQ_SENSE_LEVEL, /* EXT 1 */
- IRQ_SENSE_LEVEL, /* EXT 2 */
- 0, /* EXT 3 */
-#ifdef CONFIG_PCI
- IRQ_SENSE_LEVEL, /* EXT 4 */
- IRQ_SENSE_LEVEL, /* EXT 5 */
- IRQ_SENSE_LEVEL, /* EXT 6 */
- IRQ_SENSE_LEVEL, /* EXT 7 */
-#else
- 0, /* EXT 4 */
- 0, /* EXT 5 */
- 0, /* EXT 6 */
- 0, /* EXT 7 */
-#endif
- };
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (!np)
+ return;
- ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+ ipic_init(np, 0);
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
@@ -178,4 +137,7 @@ define_machine(mpc834x_sys) {
.time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup = mpc83xx_pcibios_fixup,
+#endif
};
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 01cae106912..2c82bca9bfb 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -11,6 +11,7 @@
extern int add_bridge(struct device_node *dev);
extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern void mpc83xx_pcibios_fixup(void);
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 3b5e563c279..5d84a9ccd10 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -45,6 +45,15 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_SUCCESSFUL;
}
+void __init mpc83xx_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+
+ /* map all the PCI irqs */
+ for_each_pci_dev(dev)
+ pci_read_irq_line(dev);
+}
+
int __init add_bridge(struct device_node *dev)
{
int len;
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 146da3001c6..0b1b52168bb 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -52,6 +52,7 @@ unsigned long pci_dram_offset = 0;
#endif
+#ifdef CONFIG_PCI
static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs)
{
@@ -60,40 +61,43 @@ static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
generic_handle_irq(cascade_irq, regs);
desc->chip->eoi(irq);
}
+#endif /* CONFIG_PCI */
void __init
mpc86xx_hpcn_init_irq(void)
{
struct mpic *mpic1;
- struct device_node *np, *cascade_node = NULL;
+ struct device_node *np;
+ struct resource res;
+#ifdef CONFIG_PCI
+ struct device_node *cascade_node = NULL;
int cascade_irq;
- phys_addr_t openpic_paddr;
+#endif
+ /* Determine PIC address. */
np = of_find_node_by_type(NULL, "open-pic");
if (np == NULL)
return;
-
- /* Determine the Physical Address of the OpenPIC regs */
- openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
+ of_address_to_resource(np, 0, &res);
/* Alloc mpic structure and per isu has 16 INT entries. */
- mpic1 = mpic_alloc(np, openpic_paddr,
+ mpic1 = mpic_alloc(np, res.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
16, NR_IRQS - 4,
" MPIC ");
BUG_ON(mpic1 == NULL);
- mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10000);
+ mpic_assign_isu(mpic1, 0, res.start + 0x10000);
/* 48 Internal Interrupts */
- mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10200);
- mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10400);
- mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10600);
+ mpic_assign_isu(mpic1, 1, res.start + 0x10200);
+ mpic_assign_isu(mpic1, 2, res.start + 0x10400);
+ mpic_assign_isu(mpic1, 3, res.start + 0x10600);
/* 16 External interrupts
* Moving them from [0 - 15] to [64 - 79]
*/
- mpic_assign_isu(mpic1, 4, openpic_paddr + 0x10000);
+ mpic_assign_isu(mpic1, 4, res.start + 0x10000);
mpic_init(mpic1);
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index bc513904311..a8c8f0a4405 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -188,7 +188,8 @@ int __init add_bridge(struct device_node *dev)
printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
"Firmware bus number: %d->%d\n",
- rsrc.start, hose->first_busno, hose->last_busno);
+ (unsigned long) rsrc.start,
+ hose->first_busno, hose->last_busno);
DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
hose, hose->cfg_addr, hose->cfg_data);
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index ba07a9a7c03..234a861870a 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -80,6 +80,7 @@ config MPC7448HPC2
select DEFAULT_UIMAGE
select PPC_UDBG_16550
select MPIC
+ select MPIC_WEIRD
help
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
platform
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index ed00ed2455d..5d393eb9493 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -215,7 +215,7 @@ static void __init mpc7448_hpc2_init_IRQ(void)
mpic = mpic_alloc(tsi_pic, mpic_paddr,
MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
- MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
+ MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
0, /* num_sources used */
0, /* num_sources used */
"Tsi108_PIC");
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 6d66359ec8c..aacfa59595d 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -256,7 +256,7 @@ static struct pmf_handlers macio_mmio_handlers = {
.write_reg32 = macio_do_write_reg32,
.read_reg32 = macio_do_read_reg32,
.write_reg8 = macio_do_write_reg8,
- .read_reg32 = macio_do_read_reg8,
+ .read_reg8 = macio_do_read_reg8,
.read_reg32_msrx = macio_do_read_reg32_msrx,
.read_reg8_msrx = macio_do_read_reg8_msrx,
.write_reg32_slm = macio_do_write_reg32_slm,
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 060789e31c6..39f7ddb554e 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -87,8 +87,8 @@ static void __pmac_retrigger(unsigned int irq_nr)
static void pmac_mask_and_ack_irq(unsigned int virq)
{
unsigned int src = irq_map[virq].hwirq;
- unsigned long bit = 1UL << (virq & 0x1f);
- int i = virq >> 5;
+ unsigned long bit = 1UL << (src & 0x1f);
+ int i = src >> 5;
unsigned long flags;
spin_lock_irqsave(&pmac_pic_lock, flags);
@@ -175,7 +175,7 @@ static void pmac_mask_irq(unsigned int virq)
spin_lock_irqsave(&pmac_pic_lock, flags);
__clear_bit(src, ppc_cached_irq_mask);
- __pmac_set_irq_mask(src, 0);
+ __pmac_set_irq_mask(src, 1);
spin_unlock_irqrestore(&pmac_pic_lock, flags);
}
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index cebfae24260..e5e999ea891 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE) += dcr.o
obj-$(CONFIG_40x) += dcr.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
-obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_PPC_TODC) += todc.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
- endif
+obj-$(CONFIG_PPC_83xx) += ipic.o
+endif
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 46801f5ec03..70e707785d4 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -19,15 +19,18 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/sysdev.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/prom.h>
#include <asm/ipic.h>
-#include <asm/mpc83xx.h>
#include "ipic.h"
-static struct ipic p_ipic;
static struct ipic * primary_ipic;
+static DEFINE_SPINLOCK(ipic_lock);
static struct ipic_info ipic_info[] = {
[9] = {
@@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32
out_be32(base + (reg >> 2), value);
}
-static inline struct ipic * ipic_from_irq(unsigned int irq)
+static inline struct ipic * ipic_from_irq(unsigned int virq)
{
return primary_ipic;
}
-static void ipic_enable_irq(unsigned int irq)
+#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
+
+static void ipic_unmask_irq(unsigned int virq)
{
- struct ipic *ipic = ipic_from_irq(irq);
- unsigned int src = irq - ipic->irq_offset;
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
+ unsigned long flags;
u32 temp;
+ spin_lock_irqsave(&ipic_lock, flags);
+
temp = ipic_read(ipic->regs, ipic_info[src].mask);
temp |= (1 << (31 - ipic_info[src].bit));
ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+ spin_unlock_irqrestore(&ipic_lock, flags);
}
-static void ipic_disable_irq(unsigned int irq)
+static void ipic_mask_irq(unsigned int virq)
{
- struct ipic *ipic = ipic_from_irq(irq);
- unsigned int src = irq - ipic->irq_offset;
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
+ unsigned long flags;
u32 temp;
+ spin_lock_irqsave(&ipic_lock, flags);
+
temp = ipic_read(ipic->regs, ipic_info[src].mask);
temp &= ~(1 << (31 - ipic_info[src].bit));
ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+ spin_unlock_irqrestore(&ipic_lock, flags);
}
-static void ipic_disable_irq_and_ack(unsigned int irq)
+static void ipic_ack_irq(unsigned int virq)
{
- struct ipic *ipic = ipic_from_irq(irq);
- unsigned int src = irq - ipic->irq_offset;
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
+ unsigned long flags;
u32 temp;
- ipic_disable_irq(irq);
+ spin_lock_irqsave(&ipic_lock, flags);
temp = ipic_read(ipic->regs, ipic_info[src].pend);
temp |= (1 << (31 - ipic_info[src].bit));
ipic_write(ipic->regs, ipic_info[src].pend, temp);
+
+ spin_unlock_irqrestore(&ipic_lock, flags);
}
-static void ipic_end_irq(unsigned int irq)
+static void ipic_mask_irq_and_ack(unsigned int virq)
{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- ipic_enable_irq(irq);
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
+ unsigned long flags;
+ u32 temp;
+
+ spin_lock_irqsave(&ipic_lock, flags);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp &= ~(1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].pend);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].pend, temp);
+
+ spin_unlock_irqrestore(&ipic_lock, flags);
}
-struct hw_interrupt_type ipic = {
- .typename = " IPIC ",
- .enable = ipic_enable_irq,
- .disable = ipic_disable_irq,
- .ack = ipic_disable_irq_and_ack,
- .end = ipic_end_irq,
+static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
+ struct irq_desc *desc = get_irq_desc(virq);
+ unsigned int vold, vnew, edibit;
+
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ /* ipic supports only low assertion and high-to-low change senses
+ */
+ if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
+ printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
+ flow_type);
+ return -EINVAL;
+ }
+
+ desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+ desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+ if (flow_type & IRQ_TYPE_LEVEL_LOW) {
+ desc->status |= IRQ_LEVEL;
+ set_irq_handler(virq, handle_level_irq);
+ } else {
+ set_irq_handler(virq, handle_edge_irq);
+ }
+
+ /* only EXT IRQ senses are programmable on ipic
+ * internal IRQ senses are LEVEL_LOW
+ */
+ if (src == IPIC_IRQ_EXT0)
+ edibit = 15;
+ else
+ if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
+ edibit = (14 - (src - IPIC_IRQ_EXT1));
+ else
+ return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
+
+ vold = ipic_read(ipic->regs, IPIC_SECNR);
+ if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
+ vnew = vold | (1 << edibit);
+ } else {
+ vnew = vold & ~(1 << edibit);
+ }
+ if (vold != vnew)
+ ipic_write(ipic->regs, IPIC_SECNR, vnew);
+ return 0;
+}
+
+static struct irq_chip ipic_irq_chip = {
+ .typename = " IPIC ",
+ .unmask = ipic_unmask_irq,
+ .mask = ipic_mask_irq,
+ .mask_ack = ipic_mask_irq_and_ack,
+ .ack = ipic_ack_irq,
+ .set_type = ipic_set_irq_type,
+};
+
+static int ipic_host_match(struct irq_host *h, struct device_node *node)
+{
+ struct ipic *ipic = h->host_data;
+
+ /* Exact match, unless ipic node is NULL */
+ return ipic->of_node == NULL || ipic->of_node == node;
+}
+
+static int ipic_host_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct ipic *ipic = h->host_data;
+ struct irq_chip *chip;
+
+ /* Default chip */
+ chip = &ipic->hc_irq;
+
+ set_irq_chip_data(virq, ipic);
+ set_irq_chip_and_handler(virq, chip, handle_level_irq);
+
+ /* Set default irq type */
+ set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
+ u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+ /* interrupt sense values coming from the device tree equal either
+ * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
+ */
+ *out_hwirq = intspec[0];
+ if (intsize > 1)
+ *out_flags = intspec[1];
+ else
+ *out_flags = IRQ_TYPE_NONE;
+ return 0;
+}
+
+static struct irq_host_ops ipic_host_ops = {
+ .match = ipic_host_match,
+ .map = ipic_host_map,
+ .xlate = ipic_host_xlate,
};
-void __init ipic_init(phys_addr_t phys_addr,
- unsigned int flags,
- unsigned int irq_offset,
- unsigned char *senses,
- unsigned int senses_count)
+void __init ipic_init(struct device_node *node,
+ unsigned int flags)
{
- u32 i, temp = 0;
+ struct ipic *ipic;
+ struct resource res;
+ u32 temp = 0, ret;
+
+ ipic = alloc_bootmem(sizeof(struct ipic));
+ if (ipic == NULL)
+ return;
+
+ memset(ipic, 0, sizeof(struct ipic));
+ ipic->of_node = node ? of_node_get(node) : NULL;
+
+ ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+ NR_IPIC_INTS,
+ &ipic_host_ops, 0);
+ if (ipic->irqhost == NULL) {
+ of_node_put(node);
+ return;
+ }
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret)
+ return;
- primary_ipic = &p_ipic;
- primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+ ipic->regs = ioremap(res.start, res.end - res.start + 1);
- primary_ipic->irq_offset = irq_offset;
+ ipic->irqhost->host_data = ipic;
+ ipic->hc_irq = ipic_irq_chip;
- ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+ /* init hw */
+ ipic_write(ipic->regs, IPIC_SICNR, 0x0);
/* default priority scheme is grouped. If spread mode is required
* configure SICFR accordingly */
@@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr,
if (flags & IPIC_SPREADMODE_MIX_B)
temp |= SICFR_MPSB;
- ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+ ipic_write(ipic->regs, IPIC_SICNR, temp);
/* handle MCP route */
temp = 0;
if (flags & IPIC_DISABLE_MCP_OUT)
temp = SERCR_MCPR;
- ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+ ipic_write(ipic->regs, IPIC_SERCR, temp);
/* handle routing of IRQ0 to MCP */
- temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+ temp = ipic_read(ipic->regs, IPIC_SEMSR);
if (flags & IPIC_IRQ0_MCP)
temp |= SEMSR_SIRQ0;
else
temp &= ~SEMSR_SIRQ0;
- ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+ ipic_write(ipic->regs, IPIC_SEMSR, temp);
- for (i = 0 ; i < NR_IPIC_INTS ; i++) {
- irq_desc[i+irq_offset].chip = &ipic;
- irq_desc[i+irq_offset].status = IRQ_LEVEL;
- }
+ primary_ipic = ipic;
+ irq_set_default_host(primary_ipic->irqhost);
- temp = 0;
- for (i = 0 ; i < senses_count ; i++) {
- if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
- temp |= 1 << (15 - i);
- if (i != 0)
- irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
- else
- irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
- }
- }
- ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
-
- printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
- senses_count, primary_ipic->regs);
+ printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
+ primary_ipic->regs);
}
-int ipic_set_priority(unsigned int irq, unsigned int priority)
+int ipic_set_priority(unsigned int virq, unsigned int priority)
{
- struct ipic *ipic = ipic_from_irq(irq);
- unsigned int src = irq - ipic->irq_offset;
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
u32 temp;
if (priority > 7)
@@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority)
return 0;
}
-void ipic_set_highest_priority(unsigned int irq)
+void ipic_set_highest_priority(unsigned int virq)
{
- struct ipic *ipic = ipic_from_irq(irq);
- unsigned int src = irq - ipic->irq_offset;
+ struct ipic *ipic = ipic_from_irq(virq);
+ unsigned int src = ipic_irq_to_hw(virq);
u32 temp;
temp = ipic_read(ipic->regs, IPIC_SICFR);
@@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq)
void ipic_set_default_priority(void)
{
- ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
- ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
- ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
- ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
- ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
- ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
- ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
- ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
-
- ipic_set_priority(MPC83xx_IRQ_UART1, 0);
- ipic_set_priority(MPC83xx_IRQ_UART2, 1);
- ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
- ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
- ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
- ipic_set_priority(MPC83xx_IRQ_SPI, 7);
- ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
- ipic_set_priority(MPC83xx_IRQ_PIT, 1);
- ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
- ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
- ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
- ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
- ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
- ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
- ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
- ipic_set_priority(MPC83xx_IRQ_MU, 1);
- ipic_set_priority(MPC83xx_IRQ_SBA, 2);
- ipic_set_priority(MPC83xx_IRQ_DMA, 3);
- ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
- ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
- ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
- ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+ ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
+ ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
+ ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
+ ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
}
void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
@@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask)
ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
}
-/* Return an interrupt vector or -1 if no interrupt is pending. */
-int ipic_get_irq(struct pt_regs *regs)
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int ipic_get_irq(struct pt_regs *regs)
{
int irq;
- irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+ BUG_ON(primary_ipic == NULL);
+
+#define IPIC_SIVCR_VECTOR_MASK 0x7f
+ irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
if (irq == 0) /* 0 --> no irq is pending */
- irq = -1;
+ return NO_IRQ;
- return irq;
+ return irq_linear_revmap(primary_ipic->irqhost, irq);
}
static struct sysdev_class ipic_sysclass = {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index a60c9d18bb7..c28e589877e 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -15,7 +15,18 @@
#include <asm/ipic.h>
-#define MPC83xx_IPIC_SIZE (0x00100)
+#define NR_IPIC_INTS 128
+
+/* External IRQS */
+#define IPIC_IRQ_EXT0 48
+#define IPIC_IRQ_EXT1 17
+#define IPIC_IRQ_EXT7 23
+
+/* Default Priority Registers */
+#define IPIC_SIPRR_A_DEFAULT 0x05309770
+#define IPIC_SIPRR_D_DEFAULT 0x05309770
+#define IPIC_SMPRR_A_DEFAULT 0x05309770
+#define IPIC_SMPRR_B_DEFAULT 0x05309770
/* System Global Interrupt Configuration Register */
#define SICFR_IPSA 0x00010000
@@ -31,7 +42,15 @@
struct ipic {
volatile u32 __iomem *regs;
- unsigned int irq_offset;
+
+ /* The remapper for this IPIC */
+ struct irq_host *irqhost;
+
+ /* The "linux" controller struct */
+ struct irq_chip hc_irq;
+
+ /* The device node of the interrupt controller */
+ struct device_node *of_node;
};
struct ipic_info {
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6e0281afa6c..b604926401f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock);
#endif
#endif
+#ifdef CONFIG_MPIC_WEIRD
+static u32 mpic_infos[][MPIC_IDX_END] = {
+ [0] = { /* Original OpenPIC compatible MPIC */
+ MPIC_GREG_BASE,
+ MPIC_GREG_FEATURE_0,
+ MPIC_GREG_GLOBAL_CONF_0,
+ MPIC_GREG_VENDOR_ID,
+ MPIC_GREG_IPI_VECTOR_PRI_0,
+ MPIC_GREG_IPI_STRIDE,
+ MPIC_GREG_SPURIOUS,
+ MPIC_GREG_TIMER_FREQ,
+
+ MPIC_TIMER_BASE,
+ MPIC_TIMER_STRIDE,
+ MPIC_TIMER_CURRENT_CNT,
+ MPIC_TIMER_BASE_CNT,
+ MPIC_TIMER_VECTOR_PRI,
+ MPIC_TIMER_DESTINATION,
+
+ MPIC_CPU_BASE,
+ MPIC_CPU_STRIDE,
+ MPIC_CPU_IPI_DISPATCH_0,
+ MPIC_CPU_IPI_DISPATCH_STRIDE,
+ MPIC_CPU_CURRENT_TASK_PRI,
+ MPIC_CPU_WHOAMI,
+ MPIC_CPU_INTACK,
+ MPIC_CPU_EOI,
+
+ MPIC_IRQ_BASE,
+ MPIC_IRQ_STRIDE,
+ MPIC_IRQ_VECTOR_PRI,
+ MPIC_VECPRI_VECTOR_MASK,
+ MPIC_VECPRI_POLARITY_POSITIVE,
+ MPIC_VECPRI_POLARITY_NEGATIVE,
+ MPIC_VECPRI_SENSE_LEVEL,
+ MPIC_VECPRI_SENSE_EDGE,
+ MPIC_VECPRI_POLARITY_MASK,
+ MPIC_VECPRI_SENSE_MASK,
+ MPIC_IRQ_DESTINATION
+ },
+ [1] = { /* Tsi108/109 PIC */
+ TSI108_GREG_BASE,
+ TSI108_GREG_FEATURE_0,
+ TSI108_GREG_GLOBAL_CONF_0,
+ TSI108_GREG_VENDOR_ID,
+ TSI108_GREG_IPI_VECTOR_PRI_0,
+ TSI108_GREG_IPI_STRIDE,
+ TSI108_GREG_SPURIOUS,
+ TSI108_GREG_TIMER_FREQ,
+
+ TSI108_TIMER_BASE,
+ TSI108_TIMER_STRIDE,
+ TSI108_TIMER_CURRENT_CNT,
+ TSI108_TIMER_BASE_CNT,
+ TSI108_TIMER_VECTOR_PRI,
+ TSI108_TIMER_DESTINATION,
+
+ TSI108_CPU_BASE,
+ TSI108_CPU_STRIDE,
+ TSI108_CPU_IPI_DISPATCH_0,
+ TSI108_CPU_IPI_DISPATCH_STRIDE,
+ TSI108_CPU_CURRENT_TASK_PRI,
+ TSI108_CPU_WHOAMI,
+ TSI108_CPU_INTACK,
+ TSI108_CPU_EOI,
+
+ TSI108_IRQ_BASE,
+ TSI108_IRQ_STRIDE,
+ TSI108_IRQ_VECTOR_PRI,
+ TSI108_VECPRI_VECTOR_MASK,
+ TSI108_VECPRI_POLARITY_POSITIVE,
+ TSI108_VECPRI_POLARITY_NEGATIVE,
+ TSI108_VECPRI_SENSE_LEVEL,
+ TSI108_VECPRI_SENSE_EDGE,
+ TSI108_VECPRI_POLARITY_MASK,
+ TSI108_VECPRI_SENSE_MASK,
+ TSI108_IRQ_DESTINATION
+ },
+};
+
+#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
+
+#else /* CONFIG_MPIC_WEIRD */
+
+#define MPIC_INFO(name) MPIC_##name
+
+#endif /* CONFIG_MPIC_WEIRD */
+
/*
* Register accessor functions
*/
@@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
{
unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+ (ipi * MPIC_INFO(GREG_IPI_STRIDE));
if (mpic->flags & MPIC_BROKEN_IPI)
be = !be;
@@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
{
- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+ unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+ (ipi * MPIC_INFO(GREG_IPI_STRIDE));
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
}
@@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
unsigned int idx = src_no & mpic->isu_mask;
return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
- reg + (idx * MPIC_IRQ_STRIDE));
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)));
}
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
unsigned int idx = src_no & mpic->isu_mask;
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
- reg + (idx * MPIC_IRQ_STRIDE), value);
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
}
#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
@@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
{
u32 r;
- mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
- r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
+ r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
@@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq)
/* Send an EOI */
static inline void mpic_eoi(struct mpic *mpic)
{
- mpic_cpu_write(MPIC_CPU_EOI, 0);
- (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+ mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
+ (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
}
#ifdef CONFIG_SMP
@@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq)
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+ mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
~MPIC_VECPRI_MASK);
/* make sure mask gets to controller before we return to user */
do {
@@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq)
printk(KERN_ERR "mpic_enable_irq timeout\n");
break;
}
- } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+ } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
}
static void mpic_mask_irq(unsigned int irq)
@@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq)
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+ mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
MPIC_VECPRI_MASK);
/* make sure mask gets to controller before we return to user */
@@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq)
printk(KERN_ERR "mpic_enable_irq timeout\n");
break;
}
- } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+ } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
}
static void mpic_end_irq(unsigned int irq)
@@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
cpus_and(tmp, cpumask, cpu_online_map);
- mpic_irq_write(src, MPIC_IRQ_DESTINATION,
+ mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
mpic_physmask(cpus_addr(tmp)[0]));
}
-static unsigned int mpic_type_to_vecpri(unsigned int type)
+static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
{
/* Now convert sense value */
switch(type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
- return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
+ return MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE);
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_EDGE_BOTH:
- return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
+ return MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
case IRQ_TYPE_LEVEL_HIGH:
- return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
+ return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE);
case IRQ_TYPE_LEVEL_LOW:
default:
- return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
+ return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
}
}
@@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
MPIC_VECPRI_SENSE_EDGE;
else
- vecpri = mpic_type_to_vecpri(flow_type);
+ vecpri = mpic_type_to_vecpri(mpic, flow_type);
- vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
- vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
+ vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+ vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
+ MPIC_INFO(VECPRI_SENSE_MASK));
vnew |= vecpri;
if (vold != vnew)
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
return 0;
}
@@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->irq_count = irq_count;
mpic->num_sources = 0; /* so far */
+#ifdef CONFIG_MPIC_WEIRD
+ mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
+#endif
+
/* Map the global registers */
- mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
- mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+ mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000);
+ mpic->tmregs = mpic->gregs +
+ ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
BUG_ON(mpic->gregs == NULL);
/* Reset */
if (flags & MPIC_WANTS_RESET) {
- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
| MPIC_GREG_GCONF_RESET);
- while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+ while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
& MPIC_GREG_GCONF_RESET)
mb();
}
@@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
* MPICs, num sources as well. On ISU MPICs, sources are counted
* as ISUs are added
*/
- reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+ reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
>> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
if (isu_size == 0)
@@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
/* Map the per-CPU registers */
for (i = 0; i < mpic->num_cpus; i++) {
- mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
- i * MPIC_CPU_STRIDE, 0x1000);
+ mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) +
+ i * MPIC_INFO(CPU_STRIDE), 0x1000);
BUG_ON(mpic->cpuregs[i] == NULL);
}
/* Initialize main ISU if none provided */
if (mpic->isu_size == 0) {
mpic->isu_size = mpic->num_sources;
- mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
- MPIC_IRQ_STRIDE * mpic->isu_size);
+ mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE),
+ MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
BUG_ON(mpic->isus[0] == NULL);
}
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
BUG_ON(isu_num >= MPIC_MAX_ISU);
- mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+ mpic->isus[isu_num] = ioremap(phys_addr,
+ MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
if ((isu_first + mpic->isu_size) > mpic->num_sources)
mpic->num_sources = isu_first + mpic->isu_size;
}
@@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic)
printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
/* Set current processor priority to max */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
/* Initialize timers: just disable them all */
for (i = 0; i < 4; i++) {
mpic_write(mpic->tmregs,
- i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+ i * MPIC_INFO(TIMER_STRIDE) +
+ MPIC_INFO(TIMER_DESTINATION), 0);
mpic_write(mpic->tmregs,
- i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+ i * MPIC_INFO(TIMER_STRIDE) +
+ MPIC_INFO(TIMER_VECTOR_PRI),
MPIC_VECPRI_MASK |
(MPIC_VEC_TIMER_0 + i));
}
@@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic)
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
/* init hw */
- mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+ mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
1 << hard_smp_processor_id());
}
/* Init spurrious vector */
- mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS);
- /* Disable 8259 passthrough */
- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
- | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+ /* Disable 8259 passthrough, if supported */
+ if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | MPIC_GREG_GCONF_8259_PTHROU_DIS);
/* Set current processor priority to 0 */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
mpic_ipi_write(src - MPIC_VEC_IPI_0,
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
} else {
- reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
+ reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
& ~MPIC_VECPRI_PRIORITY_MASK;
- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
}
spin_unlock_irqrestore(&mpic_lock, flags);
@@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
if (is_ipi)
reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
else
- reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
+ reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
spin_unlock_irqrestore(&mpic_lock, flags);
return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
}
@@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void)
*/
if (distribute_irqs) {
for (i = 0; i < mpic->num_sources ; i++)
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
- mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+ mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
}
/* Set current processor priority to 0 */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
spin_unlock_irqrestore(&mpic_lock, flags);
#endif /* CONFIG_SMP */
@@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void)
{
struct mpic *mpic = mpic_primary;
- return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+ return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
}
void mpic_cpu_set_priority(int prio)
@@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio)
struct mpic *mpic = mpic_primary;
prio &= MPIC_CPU_TASKPRI_MASK;
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
}
/*
@@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary)
/* let the mpic know we don't want intrs. */
for (i = 0; i < mpic->num_sources ; i++)
- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
- mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+ mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
/* Set current processor priority to max */
- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
spin_unlock_irqrestore(&mpic_lock, flags);
}
@@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
#endif
- mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+ mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
+ ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
}
@@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
{
u32 src;
- src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+ src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
#ifdef DEBUG_LOW
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
#endif
diff --git a/arch/ppc/kernel/smp-tbsync.c b/arch/ppc/kernel/smp-tbsync.c
index 1576758deba..d0cf3f86931 100644
--- a/arch/ppc/kernel/smp-tbsync.c
+++ b/arch/ppc/kernel/smp-tbsync.c
@@ -47,8 +47,9 @@ void __devinit
smp_generic_take_timebase( void )
{
int cmd, tbl, tbu;
+ unsigned long flags;
- local_irq_disable();
+ local_irq_save(flags);
while( !running )
;
rmb();
@@ -64,7 +65,7 @@ smp_generic_take_timebase( void )
tbu = tbsync->tbu;
tbsync->ack = 0;
if( cmd == kExit )
- return;
+ break;
if( cmd == kSetAndTest ) {
while( tbsync->handshake )
@@ -77,7 +78,7 @@ smp_generic_take_timebase( void )
}
enter_contest( tbsync->mark, -1 );
}
- local_irq_enable();
+ local_irq_restore(flags);
}
static int __devinit
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 2497bbc07e7..dca23f2ef85 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o
endif
obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \
- mpc83xx_sys.o mpc83xx_devices.o
+ mpc83xx_sys.o mpc83xx_devices.o ipic.o
ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += pci_auto.o
endif
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 00000000000..46801f5ec03
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+ [9] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 24,
+ .prio_mask = 0,
+ },
+ [10] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 25,
+ .prio_mask = 1,
+ },
+ [11] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 26,
+ .prio_mask = 2,
+ },
+ [14] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 29,
+ .prio_mask = 5,
+ },
+ [15] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 30,
+ .prio_mask = 6,
+ },
+ [16] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 31,
+ .prio_mask = 7,
+ },
+ [17] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 1,
+ .prio_mask = 5,
+ },
+ [18] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 2,
+ .prio_mask = 6,
+ },
+ [19] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 3,
+ .prio_mask = 7,
+ },
+ [20] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [21] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [22] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [23] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [32] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [33] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [34] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [35] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [36] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [37] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [38] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [39] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [48] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 0,
+ .prio_mask = 4,
+ },
+ [64] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [65] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [66] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [67] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [68] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 4,
+ .prio_mask = 0,
+ },
+ [69] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 5,
+ .prio_mask = 1,
+ },
+ [70] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 6,
+ .prio_mask = 2,
+ },
+ [71] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 7,
+ .prio_mask = 3,
+ },
+ [72] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 8,
+ },
+ [73] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 9,
+ },
+ [74] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 10,
+ },
+ [75] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 11,
+ },
+ [76] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 12,
+ },
+ [77] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 13,
+ },
+ [78] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 14,
+ },
+ [79] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 15,
+ },
+ [80] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 16,
+ },
+ [84] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 20,
+ },
+ [85] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 21,
+ },
+ [90] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 26,
+ },
+ [91] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 27,
+ },
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+ return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+ out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+ return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp &= ~(1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ ipic_disable_irq(irq);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].pend);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+ .typename = " IPIC ",
+ .enable = ipic_enable_irq,
+ .disable = ipic_disable_irq,
+ .ack = ipic_disable_irq_and_ack,
+ .end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+ unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses,
+ unsigned int senses_count)
+{
+ u32 i, temp = 0;
+
+ primary_ipic = &p_ipic;
+ primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+ primary_ipic->irq_offset = irq_offset;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+ /* default priority scheme is grouped. If spread mode is required
+ * configure SICFR accordingly */
+ if (flags & IPIC_SPREADMODE_GRP_A)
+ temp |= SICFR_IPSA;
+ if (flags & IPIC_SPREADMODE_GRP_D)
+ temp |= SICFR_IPSD;
+ if (flags & IPIC_SPREADMODE_MIX_A)
+ temp |= SICFR_MPSA;
+ if (flags & IPIC_SPREADMODE_MIX_B)
+ temp |= SICFR_MPSB;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+ /* handle MCP route */
+ temp = 0;
+ if (flags & IPIC_DISABLE_MCP_OUT)
+ temp = SERCR_MCPR;
+ ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+ /* handle routing of IRQ0 to MCP */
+ temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+ if (flags & IPIC_IRQ0_MCP)
+ temp |= SEMSR_SIRQ0;
+ else
+ temp &= ~SEMSR_SIRQ0;
+
+ ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+ for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+ irq_desc[i+irq_offset].chip = &ipic;
+ irq_desc[i+irq_offset].status = IRQ_LEVEL;
+ }
+
+ temp = 0;
+ for (i = 0 ; i < senses_count ; i++) {
+ if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+ temp |= 1 << (15 - i);
+ if (i != 0)
+ irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+ else
+ irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+ }
+ }
+ ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+ printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+ senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ if (priority > 7)
+ return -EINVAL;
+ if (src > 127)
+ return -EINVAL;
+ if (ipic_info[src].prio == 0)
+ return -EINVAL;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+ if (priority < 4) {
+ temp &= ~(0x7 << (20 + (3 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+ } else {
+ temp &= ~(0x7 << (4 + (7 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+ }
+
+ ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+ return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+ /* clear and set HPI */
+ temp &= 0x7f000000;
+ temp |= (src & 0x7f) << 24;
+
+ ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+ ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+ ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+ ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+ ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+ ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+ ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+ ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+ ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+ ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+ ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+ ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+ ipic_set_priority(MPC83xx_IRQ_MU, 1);
+ ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+ ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp |= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp &= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+ return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+ ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+ if (irq == 0) /* 0 --> no irq is pending */
+ irq = -1;
+
+ return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+ set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+ .id = 0,
+ .cls = &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+ int rc;
+
+ if (!primary_ipic->regs)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+ rc = sysdev_class_register(&ipic_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_ipic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys device\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 00000000000..a60c9d18bb7
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,47 @@
+/*
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * 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 __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE (0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define SICFR_IPSA 0x00010000
+#define SICFR_IPSD 0x00080000
+#define SICFR_MPSA 0x00200000
+#define SICFR_MPSB 0x00400000
+
+/* System External Interrupt Mask Register */
+#define SEMSR_SIRQ0 0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR 0x00000001
+
+struct ipic {
+ volatile u32 __iomem *regs;
+ unsigned int irq_offset;
+};
+
+struct ipic_info {
+ u8 pend; /* pending register offset from base */
+ u8 mask; /* mask register offset from base */
+ u8 prio; /* priority register offset from base */
+ u8 force; /* force register offset from base */
+ u8 bit; /* register bit position (as per doc)
+ bit mask = 1 << (31 - bit) */
+ u8 prio_mask; /* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index 5d59e262504..837275284d9 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -88,30 +88,31 @@ __copy_to_user_asm:
.globl __copy_in_user_asm
# %r2 = from, %r3 = n, %r4 = to
__copy_in_user_asm:
+ ahi %r3,-1
+ jo 6f
sacf 256
- bras 1,1f
- mvc 0(1,%r4),0(%r2)
-0: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-1: ahi %r3,-256
- jnm 0b
-2: ex %r3,0(%r1)
- sacf 0
- slr %r2,%r2
- br 14
-3: mvc 0(1,%r4),0(%r2)
+ bras %r1,4f
+0: ahi %r3,257
+1: mvc 0(1,%r4),0(%r2)
la %r2,1(%r2)
la %r4,1(%r4)
ahi %r3,-1
+ jnz 1b
+2: lr %r2,%r3
+ br %r14
+3: mvc 0(256,%r4),0(%r2)
+ la %r2,256(%r2)
+ la %r4,256(%r4)
+4: ahi %r3,-256
jnm 3b
-4: lr %r2,%r3
+5: ex %r3,4(%r1)
sacf 0
+6: slr %r2,%r2
br %r14
.section __ex_table,"a"
- .long 0b,3b
- .long 2b,3b
- .long 3b,4b
+ .long 1b,2b
+ .long 3b,0b
+ .long 5b,0b
.previous
.align 4
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
index 19b41a33c23..1f755be22f9 100644
--- a/arch/s390/lib/uaccess64.S
+++ b/arch/s390/lib/uaccess64.S
@@ -88,30 +88,31 @@ __copy_to_user_asm:
.globl __copy_in_user_asm
# %r2 = from, %r3 = n, %r4 = to
__copy_in_user_asm:
+ aghi %r3,-1
+ jo 6f
sacf 256
- bras 1,1f
- mvc 0(1,%r4),0(%r2)
-0: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-1: aghi %r3,-256
- jnm 0b
-2: ex %r3,0(%r1)
- sacf 0
- slgr %r2,%r2
- br 14
-3: mvc 0(1,%r4),0(%r2)
+ bras %r1,4f
+0: aghi %r3,257
+1: mvc 0(1,%r4),0(%r2)
la %r2,1(%r2)
la %r4,1(%r4)
aghi %r3,-1
+ jnz 1b
+2: lgr %r2,%r3
+ br %r14
+3: mvc 0(256,%r4),0(%r2)
+ la %r2,256(%r2)
+ la %r4,256(%r4)
+4: aghi %r3,-256
jnm 3b
-4: lgr %r2,%r3
+5: ex %r3,4(%r1)
sacf 0
- br %r14
+6: slgr %r2,%r2
+ br 14
.section __ex_table,"a"
- .quad 0b,3b
- .quad 2b,3b
- .quad 3b,4b
+ .quad 1b,2b
+ .quad 3b,0b
+ .quad 5b,0b
.previous
.align 4
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index 8cb06205d26..af9d81db0b3 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -69,6 +69,8 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
} else
offset += PAGE_SIZE;
+ if (pte_write(entry))
+ entry = pte_mkdirty(entry);
do {
BUG_ON(!pte_none(*pte));
set_pte_at(mm, address, pte, entry);
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 840d5d93d5c..5fb97071594 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc2
-# Tue Jul 18 17:13:20 2006
+# Linux kernel version: 2.6.18-rc4
+# Thu Aug 24 21:05:55 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -201,7 +201,7 @@ CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_ASUS is not set
# CONFIG_ACPI_IBM is not set
-CONFIG_ACPI_TOSHIBA=y
+# CONFIG_ACPI_TOSHIBA is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_EC=y
@@ -216,7 +216,7 @@ CONFIG_ACPI_CONTAINER=y
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
@@ -495,8 +495,9 @@ CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
# CONFIG_CHR_DEV_SCH is not set
#
@@ -512,7 +513,7 @@ CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
#
# SCSI low-level drivers
@@ -538,7 +539,7 @@ CONFIG_MEGARAID_MAILBOX=y
CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_SATA=y
CONFIG_SCSI_SATA_AHCI=y
-# CONFIG_SCSI_SATA_SVW is not set
+CONFIG_SCSI_SATA_SVW=y
CONFIG_SCSI_ATA_PIIX=y
# CONFIG_SCSI_SATA_MV is not set
CONFIG_SCSI_SATA_NV=y
@@ -589,7 +590,7 @@ CONFIG_BLK_DEV_DM=y
CONFIG_FUSION=y
CONFIG_FUSION_SPI=y
# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_SAS=y
CONFIG_FUSION_MAX_SGE=128
# CONFIG_FUSION_CTL is not set
@@ -675,7 +676,7 @@ CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
+CONFIG_B44=y
CONFIG_FORCEDETH=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
@@ -712,7 +713,7 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
-# CONFIG_BNX2 is not set
+CONFIG_BNX2=y
#
# Ethernet (10000 Mbit)
@@ -842,44 +843,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_ALIM1535_WDT is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_IBMASR is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_I6300ESB_WDT is not set
-# CONFIG_I8XX_TCO is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_SBC8360_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_W83627HF_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_W83977F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SBC_EPX_C3_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_INTEL=y
CONFIG_HW_RANDOM_AMD=y
@@ -1056,6 +1020,7 @@ CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
CONFIG_VIDEO_SELECT=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -1301,7 +1266,7 @@ CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set
@@ -1494,4 +1459,5 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index a9dc0f3b5b5..2fd5a67fd43 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -73,39 +73,44 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the vsyscall DSO was being used.
*/
-#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum)
+#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
+ (VSYSCALL32_EHDR->e_phnum) : 0)
#define ELF_CORE_WRITE_EXTRA_PHDRS \
do { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff); \
- int i; \
- Elf32_Off ofs = 0; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- struct elf32_phdr phdr = vsyscall_phdrs[i]; \
- if (phdr.p_type == PT_LOAD) { \
- BUG_ON(ofs != 0); \
- ofs = phdr.p_offset = offset; \
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
- phdr.p_filesz = phdr.p_memsz; \
- offset += phdr.p_filesz; \
+ if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+ const struct elf32_phdr *const vsyscall_phdrs = \
+ (const struct elf32_phdr *) (VSYSCALL32_BASE \
+ + VSYSCALL32_EHDR->e_phoff);\
+ int i; \
+ Elf32_Off ofs = 0; \
+ for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+ struct elf32_phdr phdr = vsyscall_phdrs[i]; \
+ if (phdr.p_type == PT_LOAD) { \
+ BUG_ON(ofs != 0); \
+ ofs = phdr.p_offset = offset; \
+ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
+ phdr.p_filesz = phdr.p_memsz; \
+ offset += phdr.p_filesz; \
+ } \
+ else \
+ phdr.p_offset += ofs; \
+ phdr.p_paddr = 0; /* match other core phdrs */ \
+ DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
} while (0)
#define ELF_CORE_WRITE_EXTRA_DATA \
do { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff); \
- int i; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
- DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \
- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ if (find_vma(current->mm, VSYSCALL32_BASE)) { \
+ const struct elf32_phdr *const vsyscall_phdrs = \
+ (const struct elf32_phdr *) (VSYSCALL32_BASE \
+ + VSYSCALL32_EHDR->e_phoff); \
+ int i; \
+ for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+ DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
+ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ } \
} \
} while (0)
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index e56c2adf57a..764bf23c710 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -71,7 +71,11 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
#endif
/* kernel code + 640k memory hole (later should not be needed, but
be paranoid for now) */
- if (last >= 640*1024 && addr < __pa_symbol(&_end)) {
+ if (last >= 640*1024 && addr < 1024*1024) {
+ *addrp = 1024*1024;
+ return 1;
+ }
+ if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
*addrp = __pa_symbol(&_end);
return 1;
}
@@ -104,35 +108,6 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
return 0;
}
-/*
- * This function checks if the entire range <start,end> is mapped with type.
- *
- * Note: this function only works correct if the e820 table is sorted and
- * not-overlapping, which is the case
- */
-int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
-{
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- if (type && ei->type != type)
- continue;
- /* is the region (part) in overlap with the current region ?*/
- if (ei->addr >= end || ei->addr + ei->size <= start)
- continue;
-
- /* if the region is at the beginning of <start,end> we move
- * start to the end of the region since it's ok until there
- */
- if (ei->addr <= start)
- start = ei->addr + ei->size;
- /* if start is now at or beyond end, we're done, full coverage */
- if (start >= end)
- return 1; /* we're done */
- }
- return 0;
-}
-
/*
* Find a free area in a specific range.
*/
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 6f810424df4..aa8d8939abc 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -973,6 +973,8 @@ ENTRY(kernel_thread)
ENDPROC(kernel_thread)
child_rip:
+ pushq $0 # fake return address
+ CFI_STARTPROC
/*
* Here we are in the child and the registers are set as they were
* at kernel_thread() invocation in the parent.
@@ -983,6 +985,7 @@ child_rip:
# exit
xorl %edi, %edi
call do_exit
+ CFI_ENDPROC
ENDPROC(child_rip)
/*
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 6df05e6034f..c9739ca81d0 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -191,6 +191,7 @@ startup_64:
* jump
*/
movq initial_code(%rip),%rax
+ pushq $0 # fake return address
jmp *%rax
/* SMP bootup changes these two */
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index ce31d904d60..3dc5854ba21 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -46,4 +46,9 @@ EXPORT_SYMBOL(init_task);
*/
DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
+/* Copies of the original ist values from the tss are only accessed during
+ * debugging, no special alignment required.
+ */
+DEFINE_PER_CPU(struct orig_ist, orig_ist);
+
#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 8a099ff1f8b..34afad70482 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -521,8 +521,6 @@ static void discover_ebda(void)
void __init setup_arch(char **cmdline_p)
{
- unsigned long kernel_end;
-
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
@@ -596,8 +594,8 @@ void __init setup_arch(char **cmdline_p)
(table_end - table_start) << PAGE_SHIFT);
/* reserve kernel */
- kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
- reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
+ reserve_bootmem_generic(__pa_symbol(&_text),
+ __pa_symbol(&_end) - __pa_symbol(&_text));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 6fe58a634b5..417de564456 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -189,6 +189,7 @@ void __cpuinit cpu_init (void)
{
int cpu = stack_smp_processor_id();
struct tss_struct *t = &per_cpu(init_tss, cpu);
+ struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
unsigned long v;
char *estacks = NULL;
struct task_struct *me;
@@ -256,7 +257,7 @@ void __cpuinit cpu_init (void)
estacks += EXCEPTION_STKSZ;
break;
}
- t->ist[v] = (unsigned long)estacks;
+ orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
}
t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 14052f08981..b1249774d1e 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -107,7 +107,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
}
static int kstack_depth_to_print = 12;
+#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
#ifdef CONFIG_KALLSYMS
# include <linux/kallsyms.h>
@@ -174,7 +178,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
break;
#endif
default:
- end = per_cpu(init_tss, cpu).ist[k];
+ end = per_cpu(orig_ist, cpu).ist[k];
break;
}
/*
@@ -274,21 +278,21 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
if (unwind_init_blocked(&info, tsk) == 0)
unw_ret = show_trace_unwind(&info, NULL);
}
- if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
-#ifdef CONFIG_STACK_UNWIND
- unsigned long rip = info.regs.rip;
- print_symbol("DWARF2 unwinder stuck at %s\n", rip);
- if (call_trace == 1) {
- printk("Leftover inexact backtrace:\n");
- stack = (unsigned long *)info.regs.rsp;
- } else if (call_trace > 1)
+ if (unw_ret > 0) {
+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+ print_symbol("DWARF2 unwinder stuck at %s\n",
+ UNW_PC(&info));
+ if ((long)UNW_SP(&info) < 0) {
+ printk("Leftover inexact backtrace:\n");
+ stack = (unsigned long *)UNW_SP(&info);
+ } else
+ printk("Full inexact backtrace again:\n");
+ } else if (call_trace >= 1)
return;
else
printk("Full inexact backtrace again:\n");
-#else
+ } else
printk("Inexact backtrace:\n");
-#endif
- }
}
/*
@@ -1120,6 +1124,7 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);
+#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
@@ -1133,3 +1138,4 @@ static int __init call_trace_setup(char *s)
return 1;
}
__setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 3c55c76c6fd..2d48a7941d4 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/bitmap.h>
+#include <linux/dmi.h>
#include <asm/e820.h>
#include "pci.h"
@@ -164,11 +165,33 @@ static __init void unreachable_devices(void)
}
}
+static int disable_mcfg(struct dmi_system_id *d)
+{
+ printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+ /* Has broken MCFG table that makes the system hang when used */
+ {
+ .callback = disable_mcfg,
+ .ident = "Intel D3C5105 SDV",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+ },
+ },
+ {}
+};
+
void __init pci_mmcfg_init(void)
{
int i;
- if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ dmi_check_system(dmi_bad_mcfg);
+
+ if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -177,15 +200,6 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
- pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
- E820_RESERVED)) {
- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
- pci_mmcfg_config[0].base_address);
- printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
- return;
- }
-
/* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 5064d938396..9aea23cc0dc 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -212,7 +212,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_KILL:
ret = 0;
- if (child->state == EXIT_ZOMBIE) /* already dead */
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
child->ptrace &= ~PT_SINGLESTEP;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 5109fa37c66..ad1d7065a1b 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4177,6 +4177,11 @@ static int __init floppy_init(void)
int i, unit, drive;
int err, dr;
+#if defined(CONFIG_PPC_MERGE)
+ if (check_legacy_ioport(FDC1))
+ return -ENODEV;
+#endif
+
raw_cmd = NULL;
for (dr = 0; dr < N_DRIVE; dr++) {
@@ -4234,13 +4239,6 @@ static int __init floppy_init(void)
}
use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC_MERGE)
- if (check_legacy_ioport(FDC1)) {
- del_timer(&fd_timeout);
- err = -ENODEV;
- goto out_unreg_region;
- }
-#endif
fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) {
del_timer(&fd_timeout);
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 5bb2234a909..39a7f685e3f 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -175,6 +175,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
}
break;
+ case R200_EMIT_VAP_CTL:{
+ RING_LOCALS;
+ BEGIN_RING(2);
+ OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+ ADVANCE_RING();
+ }
+ break;
+
case RADEON_EMIT_RB3D_COLORPITCH:
case RADEON_EMIT_RE_LINE_PATTERN:
case RADEON_EMIT_SE_LINE_WIDTH:
@@ -202,7 +210,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
case R200_EMIT_TFACTOR_0:
case R200_EMIT_VTX_FMT_0:
- case R200_EMIT_VAP_CTL:
case R200_EMIT_MATRIX_SELECT_0:
case R200_EMIT_TEX_PROC_CTL_2:
case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0aa5d608fe6..843d34c8627 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3428,6 +3428,7 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
if (rv) {
+ rv->user = NULL;
rv->done = free_recv_msg;
atomic_inc(&recv_msg_inuse_count);
}
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index b2dbbdb1bf8..2f07b085536 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -391,8 +391,8 @@ static MGSL_PARAMS default_params = {
#define DESC_LIST_SIZE 4096
#define MASK_PARITY BIT1
-#define MASK_FRAMING BIT2
-#define MASK_BREAK BIT3
+#define MASK_FRAMING BIT0
+#define MASK_BREAK BIT14
#define MASK_OVERRUN BIT4
#define GSR 0x00 /* global status */
@@ -1800,17 +1800,17 @@ static void rx_async(struct slgt_info *info)
stat = 0;
- if ((status = *(p+1) & (BIT9 + BIT8))) {
- if (status & BIT9)
+ if ((status = *(p+1) & (BIT1 + BIT0))) {
+ if (status & BIT1)
icount->parity++;
- else if (status & BIT8)
+ else if (status & BIT0)
icount->frame++;
/* discard char if tty control flags say so */
if (status & info->ignore_status_mask)
continue;
- if (status & BIT9)
+ if (status & BIT1)
stat = TTY_PARITY;
- else if (status & BIT8)
+ else if (status & BIT0)
stat = TTY_FRAME;
}
if (tty) {
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
index 1035be5b501..41fc6f80c49 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/char/watchdog/sbc8360.c
@@ -200,7 +200,7 @@ static int wd_margin = 0xB;
static int wd_multiplier = 2;
static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(timeout, int, 27);
+module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout,
@@ -407,7 +407,7 @@ module_exit(sbc8360_exit);
MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
MODULE_DESCRIPTION("SBC8360 watchdog driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("1.01");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
/* end of sbc8360.c */
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index e125032bb40..d8a0d87df73 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -367,12 +367,13 @@ sgiioc4_INB(unsigned long port)
static void __devinit
ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
{
+ void __iomem *virt_dma_base;
int num_ports = sizeof (ioc4_dma_regs_t);
printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
dma_base, dma_base + num_ports - 1);
- if (!request_region(dma_base, num_ports, hwif->name)) {
+ if (!request_mem_region(dma_base, num_ports, hwif->name)) {
printk(KERN_ERR
"%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
"ALREADY in use\n",
@@ -381,13 +382,21 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
goto dma_alloc_failure;
}
- hwif->dma_base = dma_base;
+ virt_dma_base = ioremap(dma_base, num_ports);
+ if (virt_dma_base == NULL) {
+ printk(KERN_ERR
+ "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
+ __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
+ goto dma_remap_failure;
+ }
+ hwif->dma_base = (unsigned long) virt_dma_base;
+
hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
&hwif->dmatable_dma);
if (!hwif->dmatable_cpu)
- goto dma_alloc_failure;
+ goto dma_pci_alloc_failure;
hwif->sg_max_nents = IOC4_PRD_ENTRIES;
@@ -411,6 +420,12 @@ dma_base2alloc_failure:
printk(KERN_INFO
"Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+dma_pci_alloc_failure:
+ iounmap(virt_dma_base);
+
+dma_remap_failure:
+ release_mem_region(dma_base, num_ports);
+
dma_alloc_failure:
/* Disable DMA because we couldnot allocate any DMA maps */
hwif->autodma = 0;
@@ -607,18 +622,15 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
- /*
- * The IOC4 uses MMIO rather than Port IO.
- * It also needs special workarounds for INB.
- */
- default_hwif_mmiops(hwif);
hwif->INB = &sgiioc4_INB;
}
static int __devinit
sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
{
- unsigned long base, ctl, dma_base, irqport;
+ unsigned long cmd_base, dma_base, irqport;
+ unsigned long bar0, cmd_phys_base, ctl;
+ void __iomem *virt_base;
ide_hwif_t *hwif;
int h;
@@ -636,23 +648,32 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
}
/* Get the CmdBlk and CtrlBlk Base Registers */
- base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
- ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
- irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
+ bar0 = pci_resource_start(dev, 0);
+ virt_base = ioremap(bar0, pci_resource_len(dev, 0));
+ if (virt_base == NULL) {
+ printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
+ d->name, bar0);
+ return -ENOMEM;
+ }
+ cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
+ ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
+ irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
- if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
+ cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
+ if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+ hwif->name)) {
printk(KERN_ERR
- "%s : %s -- ERROR, Port Addresses "
+ "%s : %s -- ERROR, Addresses "
"0x%p to 0x%p ALREADY in use\n",
- __FUNCTION__, hwif->name, (void *) base,
- (void *) base + IOC4_CMD_CTL_BLK_SIZE);
+ __FUNCTION__, hwif->name, (void *) cmd_phys_base,
+ (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
return -ENOMEM;
}
- if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
+ if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
/* Initialize the IO registers */
- sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
+ sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
memcpy(hwif->io_ports, hwif->hw.io_ports,
sizeof (hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
@@ -665,6 +686,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
hwif->cds = (struct ide_pci_device_s *) d;
hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
+ /* The IOC4 uses MMIO rather than Port IO. */
+ default_hwif_mmiops(hwif);
+
/* Initializing chipset IRQ Registers */
hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index afdaee3c15c..9b7589e8e93 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -6,7 +6,7 @@
*
* vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
* vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a,
- * vt8235, vt8237
+ * vt8235, vt8237, vt8237a
*
* Copyright (c) 2000-2002 Vojtech Pavlik
*
@@ -81,6 +81,7 @@ static struct via_isa_bridge {
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+ { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index 25157f57a6d..f930e55b58f 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -41,9 +41,11 @@
/* Trivial bitmap-based allocator */
u32 mthca_alloc(struct mthca_alloc *alloc)
{
+ unsigned long flags;
u32 obj;
- spin_lock(&alloc->lock);
+ spin_lock_irqsave(&alloc->lock, flags);
+
obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
if (obj >= alloc->max) {
alloc->top = (alloc->top + alloc->max) & alloc->mask;
@@ -56,19 +58,24 @@ u32 mthca_alloc(struct mthca_alloc *alloc)
} else
obj = -1;
- spin_unlock(&alloc->lock);
+ spin_unlock_irqrestore(&alloc->lock, flags);
return obj;
}
void mthca_free(struct mthca_alloc *alloc, u32 obj)
{
+ unsigned long flags;
+
obj &= alloc->max - 1;
- spin_lock(&alloc->lock);
+
+ spin_lock_irqsave(&alloc->lock, flags);
+
clear_bit(obj, alloc->table);
alloc->last = min(alloc->last, obj);
alloc->top = (alloc->top + alloc->max) & alloc->mask;
- spin_unlock(&alloc->lock);
+
+ spin_unlock_irqrestore(&alloc->lock, flags);
}
int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask,
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index d3f8d75bcbb..a82f313d9dc 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -18,17 +18,48 @@
static struct backlight_properties pmu_backlight_data;
static spinlock_t pmu_backlight_lock;
static int sleeping;
+static u8 bl_curve[FB_BACKLIGHT_LEVELS];
-static int pmu_backlight_get_level_brightness(struct fb_info *info,
- int level)
+static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
+{
+ unsigned int i, flat, count, range = (max - min);
+
+ bl_curve[0] = off;
+
+ for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+ bl_curve[flat] = min;
+
+ count = FB_BACKLIGHT_LEVELS * 15 / 16;
+ for (i = 0; i < count; ++i)
+ bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+
+static int pmu_backlight_curve_lookup(int value)
+{
+ int level = (FB_BACKLIGHT_LEVELS - 1);
+ int i, max = 0;
+
+ /* Look for biggest value */
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
+ max = max((int)bl_curve[i], max);
+
+ /* Look for nearest value */
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
+ int diff = abs(bl_curve[i] - value);
+ if (diff < max) {
+ max = diff;
+ level = i;
+ }
+ }
+ return level;
+}
+
+static int pmu_backlight_get_level_brightness(int level)
{
int pmulevel;
/* Get and convert the value */
- mutex_lock(&info->bl_mutex);
- pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
- mutex_unlock(&info->bl_mutex);
-
+ pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
if (pmulevel < 0)
pmulevel = 0;
else if (pmulevel > MAX_PMU_LEVEL)
@@ -39,7 +70,6 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info,
static int pmu_backlight_update_status(struct backlight_device *bd)
{
- struct fb_info *info = class_get_devdata(&bd->class_dev);
struct adb_request req;
unsigned long flags;
int level = bd->props->brightness;
@@ -55,7 +85,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
level = 0;
if (level > 0) {
- int pmulevel = pmu_backlight_get_level_brightness(info, level);
+ int pmulevel = pmu_backlight_get_level_brightness(level);
pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
pmu_wait_complete(&req);
@@ -88,35 +118,19 @@ static struct backlight_properties pmu_backlight_data = {
};
#ifdef CONFIG_PM
-static int pmu_backlight_sleep_call(struct pmu_sleep_notifier *self, int when)
+void pmu_backlight_set_sleep(int sleep)
{
unsigned long flags;
spin_lock_irqsave(&pmu_backlight_lock, flags);
-
- switch (when) {
- case PBOOK_SLEEP_REQUEST:
- sleeping = 1;
- break;
- case PBOOK_WAKE:
- sleeping = 0;
- break;
- }
-
+ sleeping = sleep;
spin_unlock_irqrestore(&pmu_backlight_lock, flags);
-
- return PBOOK_SLEEP_OK;
}
-
-static struct pmu_sleep_notifier pmu_backlight_sleep_notif = {
- .notifier_call = pmu_backlight_sleep_call,
-};
-#endif
+#endif /* CONFIG_PM */
void __init pmu_backlight_init()
{
struct backlight_device *bd;
- struct fb_info *info;
char name[10];
int level, autosave;
@@ -131,27 +145,14 @@ void __init pmu_backlight_init()
!machine_is_compatible("PowerBook1,1"))
return;
- /* Actually, this is a hack, but I don't know of a better way
- * to get the first framebuffer device.
- */
- info = registered_fb[0];
- if (!info) {
- printk("pmubl: No framebuffer found\n");
- goto error;
- }
-
- snprintf(name, sizeof(name), "pmubl%d", info->node);
+ snprintf(name, sizeof(name), "pmubl");
- bd = backlight_device_register(name, info, &pmu_backlight_data);
+ bd = backlight_device_register(name, NULL, &pmu_backlight_data);
if (IS_ERR(bd)) {
printk("pmubl: Backlight registration failed\n");
goto error;
}
-
- mutex_lock(&info->bl_mutex);
- info->bl_dev = bd;
- fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
- mutex_unlock(&info->bl_mutex);
+ pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
level = pmu_backlight_data.max_brightness;
@@ -161,28 +162,22 @@ void __init pmu_backlight_init()
pmu_request(&req, NULL, 2, 0xd9, 0);
pmu_wait_complete(&req);
- mutex_lock(&info->bl_mutex);
- level = pmac_backlight_curve_lookup(info,
+ level = pmu_backlight_curve_lookup(
(req.reply[0] >> 4) *
pmu_backlight_data.max_brightness / 15);
- mutex_unlock(&info->bl_mutex);
}
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = level;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
mutex_lock(&pmac_backlight_mutex);
if (!pmac_backlight)
pmac_backlight = bd;
mutex_unlock(&pmac_backlight_mutex);
-#ifdef CONFIG_PM
- pmu_register_sleep_notifier(&pmu_backlight_sleep_notif);
-#endif
-
printk("pmubl: Backlight initialized (%s)\n", name);
return;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index ea386801e21..14610a63f58 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -1995,6 +1995,8 @@ restore_via_state(void)
out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
}
+extern void pmu_backlight_set_sleep(int sleep);
+
static int
pmac_suspend_devices(void)
{
@@ -2032,6 +2034,11 @@ pmac_suspend_devices(void)
return -EBUSY;
}
+#ifdef CONFIG_PMAC_BACKLIGHT
+ /* Tell backlight code not to muck around with the chip anymore */
+ pmu_backlight_set_sleep(1);
+#endif
+
/* Call platform functions marked "on sleep" */
pmac_pfunc_i2c_suspend();
pmac_pfunc_base_suspend();
@@ -2090,6 +2097,11 @@ pmac_wakeup_devices(void)
{
mdelay(100);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ /* Tell backlight code it can use the chip again */
+ pmu_backlight_set_sleep(0);
+#endif
+
/* Power back up system devices (including the PIC) */
device_power_up();
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 87bfe9e7d8c..3b4d69c0562 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -930,10 +930,13 @@ static void status(struct seq_file *seq, mddev_t *mddev)
seq_printf(seq, " [%d/%d] [", conf->raid_disks,
conf->working_disks);
- for (i = 0; i < conf->raid_disks; i++)
+ rcu_read_lock();
+ for (i = 0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
seq_printf(seq, "%s",
- conf->mirrors[i].rdev &&
- test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_");
+ rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
+ }
+ rcu_read_unlock();
seq_printf(seq, "]");
}
@@ -975,7 +978,6 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
static void print_conf(conf_t *conf)
{
int i;
- mirror_info_t *tmp;
printk("RAID1 conf printout:\n");
if (!conf) {
@@ -985,14 +987,17 @@ static void print_conf(conf_t *conf)
printk(" --- wd:%d rd:%d\n", conf->working_disks,
conf->raid_disks);
+ rcu_read_lock();
for (i = 0; i < conf->raid_disks; i++) {
char b[BDEVNAME_SIZE];
- tmp = conf->mirrors + i;
- if (tmp->rdev)
+ mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (rdev)
printk(" disk %d, wo:%d, o:%d, dev:%s\n",
- i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags),
- bdevname(tmp->rdev->bdev,b));
+ i, !test_bit(In_sync, &rdev->flags),
+ !test_bit(Faulty, &rdev->flags),
+ bdevname(rdev->bdev,b));
}
+ rcu_read_unlock();
}
static void close_sync(conf_t *conf)
@@ -1008,20 +1013,20 @@ static int raid1_spare_active(mddev_t *mddev)
{
int i;
conf_t *conf = mddev->private;
- mirror_info_t *tmp;
/*
* Find all failed disks within the RAID1 configuration
- * and mark them readable
+ * and mark them readable.
+ * Called under mddev lock, so rcu protection not needed.
*/
for (i = 0; i < conf->raid_disks; i++) {
- tmp = conf->mirrors + i;
- if (tmp->rdev
- && !test_bit(Faulty, &tmp->rdev->flags)
- && !test_bit(In_sync, &tmp->rdev->flags)) {
+ mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+ if (rdev
+ && !test_bit(Faulty, &rdev->flags)
+ && !test_bit(In_sync, &rdev->flags)) {
conf->working_disks++;
mddev->degraded--;
- set_bit(In_sync, &tmp->rdev->flags);
+ set_bit(In_sync, &rdev->flags);
}
}
@@ -1237,7 +1242,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
/* ouch - failed to read all of that.
* Try some synchronous reads of other devices to get
* good data, much like with normal read errors. Only
- * read into the pages we already have so they we don't
+ * read into the pages we already have so we don't
* need to re-issue the read request.
* We don't need to freeze the array, because being in an
* active sync request, there is no normal IO, and
@@ -1257,6 +1262,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
s = PAGE_SIZE >> 9;
do {
if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+ /* No rcu protection needed here devices
+ * can only be removed when no resync is
+ * active, and resync is currently active
+ */
rdev = conf->mirrors[d].rdev;
if (sync_page_io(rdev->bdev,
sect + rdev->data_offset,
@@ -1463,6 +1472,11 @@ static void raid1d(mddev_t *mddev)
s = PAGE_SIZE >> 9;
do {
+ /* Note: no rcu protection needed here
+ * as this is synchronous in the raid1d thread
+ * which is the thread that might remove
+ * a device. If raid1d ever becomes multi-threaded....
+ */
rdev = conf->mirrors[d].rdev;
if (rdev &&
test_bit(In_sync, &rdev->flags) &&
@@ -1486,7 +1500,6 @@ static void raid1d(mddev_t *mddev)
d = conf->raid_disks;
d--;
rdev = conf->mirrors[d].rdev;
- atomic_add(s, &rdev->corrected_errors);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
if (sync_page_io(rdev->bdev,
@@ -1509,9 +1522,11 @@ static void raid1d(mddev_t *mddev)
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
- else
+ else {
+ atomic_add(s, &rdev->corrected_errors);
printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b));
+ }
}
}
} else {
@@ -1787,19 +1802,17 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0; i<conf->raid_disks; i++) {
bio = r1_bio->bios[i];
if (bio->bi_end_io == end_sync_read) {
- md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+ md_sync_acct(bio->bi_bdev, nr_sectors);
generic_make_request(bio);
}
}
} else {
atomic_set(&r1_bio->remaining, 1);
bio = r1_bio->bios[r1_bio->read_disk];
- md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
- nr_sectors);
+ md_sync_acct(bio->bi_bdev, nr_sectors);
generic_make_request(bio);
}
-
return nr_sectors;
}
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 3b0b95892d5..47d970896a5 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -173,8 +173,11 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
static int debug = 3;
+static int eeprom_bad_csum_allow = 0;
module_param(debug, int, 0);
+module_param(eeprom_bad_csum_allow, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
#define DPRINTK(nlevel, klevel, fmt, args...) \
(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
@@ -756,7 +759,8 @@ static int e100_eeprom_load(struct nic *nic)
checksum = le16_to_cpu(0xBABA - checksum);
if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
- return -EAGAIN;
+ if (!eeprom_bad_csum_allow)
+ return -EAGAIN;
}
return 0;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 0e3fdf7c6dd..ec0413609f3 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1566,20 +1566,21 @@ static int __exit sunlance_sun4_remove(void)
static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match)
{
struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
int err;
- if (!strcmp(dp->name, "le")) {
- err = sparc_lance_probe_one(sdev, NULL, NULL);
- } else if (!strcmp(dp->name, "ledma")) {
- struct sbus_dma *ledma = find_ledma(sdev);
+ if (sdev->parent) {
+ struct of_device *parent = &sdev->parent->ofdev;
- err = sparc_lance_probe_one(sdev->child, ledma, NULL);
- } else {
- BUG_ON(strcmp(dp->name, "lebuffer"));
+ if (!strcmp(parent->node->name, "ledma")) {
+ struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev));
- err = sparc_lance_probe_one(sdev->child, NULL, sdev);
- }
+ err = sparc_lance_probe_one(sdev, ledma, NULL);
+ } else if (!strcmp(parent->node->name, "lebuffer")) {
+ err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev));
+ } else
+ err = sparc_lance_probe_one(sdev, NULL, NULL);
+ } else
+ err = sparc_lance_probe_one(sdev, NULL, NULL);
return err;
}
@@ -1604,12 +1605,6 @@ static struct of_device_id sunlance_sbus_match[] = {
{
.name = "le",
},
- {
- .name = "ledma",
- },
- {
- .name = "lebuffer",
- },
{},
};
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index fd31885c684..ccaf28e8db0 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -467,6 +467,7 @@ static int arp_query(unsigned char *haddr, u32 paddr,
struct net_device *dev)
{
struct neighbour *neighbor_entry;
+ int ret = 0;
neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev);
@@ -474,10 +475,11 @@ static int arp_query(unsigned char *haddr, u32 paddr,
neighbor_entry->used = jiffies;
if (neighbor_entry->nud_state & NUD_VALID) {
memcpy(haddr, neighbor_entry->ha, dev->addr_len);
- return 1;
+ ret = 1;
}
+ neigh_release(neighbor_entry);
}
- return 0;
+ return ret;
}
static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr,
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 73177429fe7..17e709e7d72 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -667,6 +667,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_vi
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d8e9b95f0a1..25c1ef6dfd4 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -52,7 +52,7 @@ static void dasd_setup_queue(struct dasd_device * device);
static void dasd_free_queue(struct dasd_device * device);
static void dasd_flush_request_queue(struct dasd_device *);
static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
-static void dasd_flush_ccw_queue(struct dasd_device *, int);
+static int dasd_flush_ccw_queue(struct dasd_device *, int);
static void dasd_tasklet(struct dasd_device *);
static void do_kick_device(void *data);
@@ -60,6 +60,7 @@ static void do_kick_device(void *data);
* SECTION: Operations on the device structure.
*/
static wait_queue_head_t dasd_init_waitq;
+static wait_queue_head_t dasd_flush_wq;
/*
* Allocate memory for a new device structure.
@@ -121,7 +122,7 @@ dasd_free_device(struct dasd_device *device)
/*
* Make a new device known to the system.
*/
-static inline int
+static int
dasd_state_new_to_known(struct dasd_device *device)
{
int rc;
@@ -145,7 +146,7 @@ dasd_state_new_to_known(struct dasd_device *device)
/*
* Let the system forget about a device.
*/
-static inline void
+static int
dasd_state_known_to_new(struct dasd_device * device)
{
/* Disable extended error reporting for this device. */
@@ -163,12 +164,13 @@ dasd_state_known_to_new(struct dasd_device * device)
/* Give up reference we took in dasd_state_new_to_known. */
dasd_put_device(device);
+ return 0;
}
/*
* Request the irq line for the device.
*/
-static inline int
+static int
dasd_state_known_to_basic(struct dasd_device * device)
{
int rc;
@@ -192,17 +194,23 @@ dasd_state_known_to_basic(struct dasd_device * device)
/*
* Release the irq line for the device. Terminate any running i/o.
*/
-static inline void
+static int
dasd_state_basic_to_known(struct dasd_device * device)
{
+ int rc;
+
dasd_gendisk_free(device);
- dasd_flush_ccw_queue(device, 1);
+ rc = dasd_flush_ccw_queue(device, 1);
+ if (rc)
+ return rc;
+
DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
if (device->debug_area != NULL) {
debug_unregister(device->debug_area);
device->debug_area = NULL;
}
device->state = DASD_STATE_KNOWN;
+ return 0;
}
/*
@@ -219,7 +227,7 @@ dasd_state_basic_to_known(struct dasd_device * device)
* In case the analysis returns an error, the device setup is stopped
* (a fake disk was already added to allow formatting).
*/
-static inline int
+static int
dasd_state_basic_to_ready(struct dasd_device * device)
{
int rc;
@@ -247,25 +255,31 @@ dasd_state_basic_to_ready(struct dasd_device * device)
* Forget format information. Check if the target level is basic
* and if it is create fake disk for formatting.
*/
-static inline void
+static int
dasd_state_ready_to_basic(struct dasd_device * device)
{
- dasd_flush_ccw_queue(device, 0);
+ int rc;
+
+ rc = dasd_flush_ccw_queue(device, 0);
+ if (rc)
+ return rc;
dasd_destroy_partitions(device);
dasd_flush_request_queue(device);
device->blocks = 0;
device->bp_block = 0;
device->s2b_shift = 0;
device->state = DASD_STATE_BASIC;
+ return 0;
}
/*
* Back to basic.
*/
-static inline void
+static int
dasd_state_unfmt_to_basic(struct dasd_device * device)
{
device->state = DASD_STATE_BASIC;
+ return 0;
}
/*
@@ -273,7 +287,7 @@ dasd_state_unfmt_to_basic(struct dasd_device * device)
* the requeueing of requests from the linux request queue to the
* ccw queue.
*/
-static inline int
+static int
dasd_state_ready_to_online(struct dasd_device * device)
{
device->state = DASD_STATE_ONLINE;
@@ -284,16 +298,17 @@ dasd_state_ready_to_online(struct dasd_device * device)
/*
* Stop the requeueing of requests again.
*/
-static inline void
+static int
dasd_state_online_to_ready(struct dasd_device * device)
{
device->state = DASD_STATE_READY;
+ return 0;
}
/*
* Device startup state changes.
*/
-static inline int
+static int
dasd_increase_state(struct dasd_device *device)
{
int rc;
@@ -329,30 +344,37 @@ dasd_increase_state(struct dasd_device *device)
/*
* Device shutdown state changes.
*/
-static inline int
+static int
dasd_decrease_state(struct dasd_device *device)
{
+ int rc;
+
+ rc = 0;
if (device->state == DASD_STATE_ONLINE &&
device->target <= DASD_STATE_READY)
- dasd_state_online_to_ready(device);
+ rc = dasd_state_online_to_ready(device);
- if (device->state == DASD_STATE_READY &&
+ if (!rc &&
+ device->state == DASD_STATE_READY &&
device->target <= DASD_STATE_BASIC)
- dasd_state_ready_to_basic(device);
+ rc = dasd_state_ready_to_basic(device);
- if (device->state == DASD_STATE_UNFMT &&
+ if (!rc &&
+ device->state == DASD_STATE_UNFMT &&
device->target <= DASD_STATE_BASIC)
- dasd_state_unfmt_to_basic(device);
+ rc = dasd_state_unfmt_to_basic(device);
- if (device->state == DASD_STATE_BASIC &&
+ if (!rc &&
+ device->state == DASD_STATE_BASIC &&
device->target <= DASD_STATE_KNOWN)
- dasd_state_basic_to_known(device);
+ rc = dasd_state_basic_to_known(device);
- if (device->state == DASD_STATE_KNOWN &&
+ if (!rc &&
+ device->state == DASD_STATE_KNOWN &&
device->target <= DASD_STATE_NEW)
- dasd_state_known_to_new(device);
+ rc = dasd_state_known_to_new(device);
- return 0;
+ return rc;
}
/*
@@ -701,6 +723,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
cqr->retries--;
cqr->status = DASD_CQR_CLEAR;
cqr->stopclk = get_clock();
+ cqr->starttime = 0;
DBF_DEV_EVENT(DBF_DEBUG, device,
"terminate cqr %p successful",
cqr);
@@ -978,6 +1001,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
cqr->status = DASD_CQR_QUEUED;
dasd_clear_timer(device);
+ wake_up(&dasd_flush_wq);
dasd_schedule_bh(device);
return;
}
@@ -1241,6 +1265,10 @@ __dasd_check_expire(struct dasd_device * device)
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
+ DEV_MESSAGE(KERN_ERR, device,
+ "internal error - timeout (%is) expired "
+ "for cqr %p (%i retries left)",
+ (cqr->expires/HZ), cqr, cqr->retries);
if (device->discipline->term_IO(cqr) != 0)
/* Hmpf, try again in 1/10 sec */
dasd_set_timer(device, 10);
@@ -1285,46 +1313,100 @@ __dasd_start_head(struct dasd_device * device)
dasd_set_timer(device, 50);
}
+static inline int
+_wait_for_clear(struct dasd_ccw_req *cqr)
+{
+ return (cqr->status == DASD_CQR_QUEUED);
+}
+
/*
- * Remove requests from the ccw queue.
+ * Remove all requests from the ccw queue (all = '1') or only block device
+ * requests in case all = '0'.
+ * Take care of the erp-chain (chained via cqr->refers) and remove either
+ * the whole erp-chain or none of the erp-requests.
+ * If a request is currently running, term_IO is called and the request
+ * is re-queued. Prior to removing the terminated request we need to wait
+ * for the clear-interrupt.
+ * In case termination is not possible we stop processing and just finishing
+ * the already moved requests.
*/
-static void
+static int
dasd_flush_ccw_queue(struct dasd_device * device, int all)
{
+ struct dasd_ccw_req *cqr, *orig, *n;
+ int rc, i;
+
struct list_head flush_queue;
- struct list_head *l, *n;
- struct dasd_ccw_req *cqr;
INIT_LIST_HEAD(&flush_queue);
spin_lock_irq(get_ccwdev_lock(device->cdev));
- list_for_each_safe(l, n, &device->ccw_queue) {
- cqr = list_entry(l, struct dasd_ccw_req, list);
+ rc = 0;
+restart:
+ list_for_each_entry_safe(cqr, n, &device->ccw_queue, list) {
+ /* get original request of erp request-chain */
+ for (orig = cqr; orig->refers != NULL; orig = orig->refers);
+
/* Flush all request or only block device requests? */
- if (all == 0 && cqr->callback == dasd_end_request_cb)
+ if (all == 0 && cqr->callback != dasd_end_request_cb &&
+ orig->callback != dasd_end_request_cb) {
continue;
- if (cqr->status == DASD_CQR_IN_IO)
- device->discipline->term_IO(cqr);
- if (cqr->status != DASD_CQR_DONE ||
- cqr->status != DASD_CQR_FAILED) {
- cqr->status = DASD_CQR_FAILED;
+ }
+ /* Check status and move request to flush_queue */
+ switch (cqr->status) {
+ case DASD_CQR_IN_IO:
+ rc = device->discipline->term_IO(cqr);
+ if (rc) {
+ /* unable to terminate requeust */
+ DEV_MESSAGE(KERN_ERR, device,
+ "dasd flush ccw_queue is unable "
+ " to terminate request %p",
+ cqr);
+ /* stop flush processing */
+ goto finished;
+ }
+ break;
+ case DASD_CQR_QUEUED:
+ case DASD_CQR_ERROR:
+ /* set request to FAILED */
cqr->stopclk = get_clock();
+ cqr->status = DASD_CQR_FAILED;
+ break;
+ default: /* do not touch the others */
+ break;
+ }
+ /* Rechain request (including erp chain) */
+ for (i = 0; cqr != NULL; cqr = cqr->refers, i++) {
+ cqr->endclk = get_clock();
+ list_move_tail(&cqr->list, &flush_queue);
+ }
+ if (i > 1)
+ /* moved more than one request - need to restart */
+ goto restart;
+ }
+
+finished:
+ spin_unlock_irq(get_ccwdev_lock(device->cdev));
+ /* Now call the callback function of flushed requests */
+restart_cb:
+ list_for_each_entry_safe(cqr, n, &flush_queue, list) {
+ if (cqr->status == DASD_CQR_CLEAR) {
+ /* wait for clear interrupt! */
+ wait_event(dasd_flush_wq, _wait_for_clear(cqr));
+ cqr->status = DASD_CQR_FAILED;
}
/* Process finished ERP request. */
if (cqr->refers) {
__dasd_process_erp(device, cqr);
- continue;
+ /* restart list_for_xx loop since dasd_process_erp
+ * might remove multiple elements */
+ goto restart_cb;
}
- /* Rechain request on device request queue */
+ /* call the callback function */
cqr->endclk = get_clock();
- list_move_tail(&cqr->list, &flush_queue);
- }
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
- /* Now call the callback function of flushed requests */
- list_for_each_safe(l, n, &flush_queue) {
- cqr = list_entry(l, struct dasd_ccw_req, list);
if (cqr->callback != NULL)
(cqr->callback)(cqr, cqr->callback_data);
}
+ return rc;
}
/*
@@ -1510,10 +1592,8 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr)
if (device->discipline->term_IO) {
cqr->retries = -1;
device->discipline->term_IO(cqr);
- /*nished =
- * wait (non-interruptible) for final status
- * because signal ist still pending
- */
+ /* wait (non-interruptible) for final status
+ * because signal ist still pending */
spin_unlock_irq(get_ccwdev_lock(device->cdev));
wait_event(wait_q, _wait_for_wakeup(cqr));
spin_lock_irq(get_ccwdev_lock(device->cdev));
@@ -1546,19 +1626,11 @@ static inline int
_dasd_term_running_cqr(struct dasd_device *device)
{
struct dasd_ccw_req *cqr;
- int rc;
if (list_empty(&device->ccw_queue))
return 0;
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
- rc = device->discipline->term_IO(cqr);
- if (rc == 0) {
- /* termination successful */
- cqr->status = DASD_CQR_QUEUED;
- cqr->startclk = cqr->stopclk = 0;
- cqr->starttime = 0;
- }
- return rc;
+ return device->discipline->term_IO(cqr);
}
int
@@ -1726,10 +1798,7 @@ dasd_flush_request_queue(struct dasd_device * device)
return;
spin_lock_irq(&device->request_queue_lock);
- while (!list_empty(&device->request_queue->queue_head)) {
- req = elv_next_request(device->request_queue);
- if (req == NULL)
- break;
+ while ((req = elv_next_request(device->request_queue))) {
blkdev_dequeue_request(req);
dasd_end_request(req, 0);
}
@@ -2091,6 +2160,7 @@ dasd_init(void)
int rc;
init_waitqueue_head(&dasd_init_waitq);
+ init_waitqueue_head(&dasd_flush_wq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long));
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 4c272b70f41..d163632101d 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -83,10 +83,12 @@ dasd_gendisk_alloc(struct dasd_device *device)
void
dasd_gendisk_free(struct dasd_device *device)
{
- del_gendisk(device->gdp);
- device->gdp->queue = NULL;
- put_disk(device->gdp);
- device->gdp = NULL;
+ if (device->gdp) {
+ del_gendisk(device->gdp);
+ device->gdp->queue = NULL;
+ put_disk(device->gdp);
+ device->gdp = NULL;
+ }
}
/*
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 3cba6c9fab1..38954f5cd14 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -183,11 +183,9 @@ ccwgroup_create(struct device *root,
gdev->creator_id = creator_id;
gdev->count = argc;
- gdev->dev = (struct device ) {
- .bus = &ccwgroup_bus_type,
- .parent = root,
- .release = ccwgroup_release,
- };
+ gdev->dev.bus = &ccwgroup_bus_type;
+ gdev->dev.parent = root;
+ gdev->dev.release = ccwgroup_release;
snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
gdev->cdev[0]->dev.bus_id);
@@ -391,10 +389,8 @@ int
ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
{
/* register our new driver with the core */
- cdriver->driver = (struct device_driver) {
- .bus = &ccwgroup_bus_type,
- .name = cdriver->name,
- };
+ cdriver->driver.bus = &ccwgroup_bus_type;
+ cdriver->driver.name = cdriver->name;
return driver_register(&cdriver->driver);
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 61ce3f1d522..c28444af091 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -238,8 +238,6 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
/* Check for single path devices. */
if (sch->schib.pmcw.pim == 0x80)
goto out_unreg;
- if (sch->vpm == mask)
- goto out_unreg;
if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
(sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
@@ -258,6 +256,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
/* trigger path verification. */
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
+ else if (sch->vpm == mask)
+ goto out_unreg;
out_unlock:
spin_unlock_irq(&sch->lock);
return 0;
@@ -1391,10 +1391,8 @@ new_channel_path(int chpid)
/* fill in status, etc. */
chp->id = chpid;
chp->state = 1;
- chp->dev = (struct device) {
- .parent = &css[0]->device,
- .release = chp_release,
- };
+ chp->dev.parent = &css[0]->device;
+ chp->dev.release = chp_release;
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
/* Obtain channel path description and fill it in. */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 585fa04233c..646da564040 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -556,12 +556,11 @@ get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
struct ccw_device *sibling)
{
struct device *dev;
- struct match_data data = {
- .devno = devno,
- .ssid = ssid,
- .sibling = sibling,
- };
+ struct match_data data;
+ data.devno = devno;
+ data.ssid = ssid;
+ data.sibling = sibling;
dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
return dev ? to_ccwdev(dev) : NULL;
@@ -835,10 +834,8 @@ io_subchannel_probe (struct subchannel *sch)
return -ENOMEM;
}
atomic_set(&cdev->private->onoff, 0);
- cdev->dev = (struct device) {
- .parent = &sch->dev,
- .release = ccw_device_release,
- };
+ cdev->dev.parent = &sch->dev;
+ cdev->dev.release = ccw_device_release;
INIT_LIST_HEAD(&cdev->private->kick_work.entry);
/* Do first half of device_register. */
device_initialize(&cdev->dev);
@@ -977,9 +974,7 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
int rc;
/* Initialize the ccw_device structure. */
- cdev->dev = (struct device) {
- .parent = &sch->dev,
- };
+ cdev->dev.parent= &sch->dev;
rc = io_subchannel_recog(cdev, sch);
if (rc)
return rc;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 6d91c2eb205..35e162ba6d5 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -267,12 +267,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
notify = 1;
}
/* fill out sense information */
- cdev->id = (struct ccw_device_id) {
- .cu_type = cdev->private->senseid.cu_type,
- .cu_model = cdev->private->senseid.cu_model,
- .dev_type = cdev->private->senseid.dev_type,
- .dev_model = cdev->private->senseid.dev_model,
- };
+ cdev->id.cu_type = cdev->private->senseid.cu_type;
+ cdev->id.cu_model = cdev->private->senseid.cu_model;
+ cdev->id.dev_type = cdev->private->senseid.dev_type;
+ cdev->id.dev_model = cdev->private->senseid.dev_model;
if (notify) {
cdev->private->state = DEV_STATE_OFFLINE;
if (same_dev) {
@@ -566,12 +564,10 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
/* Deliver fake irb to device driver, if needed. */
if (cdev->private->flags.fake_irb) {
memset(&cdev->private->irb, 0, sizeof(struct irb));
- cdev->private->irb.scsw = (struct scsw) {
- .cc = 1,
- .fctl = SCSW_FCTL_START_FUNC,
- .actl = SCSW_ACTL_START_PEND,
- .stctl = SCSW_STCTL_STATUS_PEND,
- };
+ cdev->private->irb.scsw.cc = 1;
+ cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC;
+ cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND;
+ cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND;
cdev->private->flags.fake_irb = 0;
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 32610fd8868..1693a102dcf 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -24,6 +24,21 @@
#include "ioasm.h"
/*
+ * Helper function called from interrupt context to decide whether an
+ * operation should be tried again.
+ */
+static int __ccw_device_should_retry(struct scsw *scsw)
+{
+ /* CC is only valid if start function bit is set. */
+ if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1)
+ return 1;
+ /* No more activity. For sense and set PGID we stubbornly try again. */
+ if (!scsw->actl)
+ return 1;
+ return 0;
+}
+
+/*
* Start Sense Path Group ID helper function. Used in ccw_device_recog
* and ccw_device_sense_pgid.
*/
@@ -155,10 +170,10 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
int ret;
irb = (struct irb *) __LC_IRB;
- /* Retry sense pgid for cc=1. */
+
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (irb->scsw.cc == 1) {
+ if (__ccw_device_should_retry(&irb->scsw)) {
ret = __ccw_device_sense_pgid_start(cdev);
if (ret && ret != -EBUSY)
ccw_device_sense_pgid_done(cdev, ret);
@@ -391,10 +406,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
int ret;
irb = (struct irb *) __LC_IRB;
- /* Retry set pgid for cc=1. */
+
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (irb->scsw.cc == 1)
+ if (__ccw_device_should_retry(&irb->scsw))
__ccw_device_verify_start(cdev);
return;
}
@@ -494,10 +509,10 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
int ret;
irb = (struct irb *) __LC_IRB;
- /* Retry set pgid for cc=1. */
+
if (irb->scsw.stctl ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
- if (irb->scsw.cc == 1)
+ if (__ccw_device_should_retry(&irb->scsw))
__ccw_device_disband_start(cdev);
return;
}
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index a1d322f8a16..851e4839d6d 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -458,11 +458,11 @@ static int pci_siig_setup(struct serial_private *priv,
* growing *huge*, we use this function to collapse some 70 entries
* in the PCI table into one, for sanity's and compactness's sake.
*/
-static unsigned short timedia_single_port[] = {
+static const unsigned short timedia_single_port[] = {
0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
};
-static unsigned short timedia_dual_port[] = {
+static const unsigned short timedia_dual_port[] = {
0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
@@ -470,35 +470,34 @@ static unsigned short timedia_dual_port[] = {
0xD079, 0
};
-static unsigned short timedia_quad_port[] = {
+static const unsigned short timedia_quad_port[] = {
0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
0xB157, 0
};
-static unsigned short timedia_eight_port[] = {
+static const unsigned short timedia_eight_port[] = {
0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
};
static const struct timedia_struct {
int num;
- unsigned short *ids;
+ const unsigned short *ids;
} timedia_data[] = {
{ 1, timedia_single_port },
{ 2, timedia_dual_port },
{ 4, timedia_quad_port },
- { 8, timedia_eight_port },
- { 0, NULL }
+ { 8, timedia_eight_port }
};
static int pci_timedia_init(struct pci_dev *dev)
{
- unsigned short *ids;
+ const unsigned short *ids;
int i, j;
- for (i = 0; timedia_data[i].num; i++) {
+ for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
ids = timedia_data[i].ids;
for (j = 0; ids[j]; j++)
if (dev->subsystem_device == ids[j])
@@ -936,6 +935,7 @@ enum pci_board_num_t {
pbn_b1_8_1382400,
pbn_b2_1_115200,
+ pbn_b2_2_115200,
pbn_b2_8_115200,
pbn_b2_1_460800,
@@ -1243,6 +1243,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
+ [pbn_b2_2_115200] = {
+ .flags = FL_BASE2,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[pbn_b2_8_115200] = {
.flags = FL_BASE2,
.num_ports = 8,
@@ -2340,6 +2346,13 @@ static struct pci_device_id serial_pci_tbl[] = {
pbn_b0_1_115200 },
/*
+ * IntaShield IS-200
+ */
+ { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */
+ pbn_b2_2_115200 },
+
+ /*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
*/
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 80ef7d48275..372e47f7d59 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2377,6 +2377,9 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
return (port1->iobase == port2->iobase) &&
(port1->hub6 == port2->hub6);
case UPIO_MEM:
+ case UPIO_MEM32:
+ case UPIO_AU:
+ case UPIO_TSI:
return (port1->mapbase == port2->mapbase);
}
return 0;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 4fe1bec1c25..30299c620d9 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -117,6 +117,8 @@ struct eth_dev {
struct usb_ep *in_ep, *out_ep, *status_ep;
const struct usb_endpoint_descriptor
*in, *out, *status;
+
+ spinlock_t req_lock;
struct list_head tx_reqs, rx_reqs;
struct net_device *net;
@@ -1066,21 +1068,31 @@ static void eth_reset_config (struct eth_dev *dev)
*/
if (dev->in) {
usb_ep_disable (dev->in_ep);
+ spin_lock(&dev->req_lock);
while (likely (!list_empty (&dev->tx_reqs))) {
req = container_of (dev->tx_reqs.next,
struct usb_request, list);
list_del (&req->list);
+
+ spin_unlock(&dev->req_lock);
usb_ep_free_request (dev->in_ep, req);
+ spin_lock(&dev->req_lock);
}
+ spin_unlock(&dev->req_lock);
}
if (dev->out) {
usb_ep_disable (dev->out_ep);
+ spin_lock(&dev->req_lock);
while (likely (!list_empty (&dev->rx_reqs))) {
req = container_of (dev->rx_reqs.next,
struct usb_request, list);
list_del (&req->list);
+
+ spin_unlock(&dev->req_lock);
usb_ep_free_request (dev->out_ep, req);
+ spin_lock(&dev->req_lock);
}
+ spin_unlock(&dev->req_lock);
}
if (dev->status) {
@@ -1659,9 +1671,9 @@ enomem:
if (retval) {
DEBUG (dev, "rx submit --> %d\n", retval);
dev_kfree_skb_any (skb);
- spin_lock (&dev->lock);
+ spin_lock(&dev->req_lock);
list_add (&req->list, &dev->rx_reqs);
- spin_unlock (&dev->lock);
+ spin_unlock(&dev->req_lock);
}
return retval;
}
@@ -1730,8 +1742,9 @@ quiesce:
dev_kfree_skb_any (skb);
if (!netif_running (dev->net)) {
clean:
- /* nobody reading rx_reqs, so no dev->lock */
+ spin_lock(&dev->req_lock);
list_add (&req->list, &dev->rx_reqs);
+ spin_unlock(&dev->req_lock);
req = NULL;
}
if (req)
@@ -1782,15 +1795,18 @@ static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
{
int status;
+ spin_lock(&dev->req_lock);
status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
if (status < 0)
goto fail;
status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
if (status < 0)
goto fail;
- return 0;
+ goto done;
fail:
DEBUG (dev, "can't alloc requests\n");
+done:
+ spin_unlock(&dev->req_lock);
return status;
}
@@ -1800,21 +1816,21 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
unsigned long flags;
/* fill unused rxq slots with some skb */
- spin_lock_irqsave (&dev->lock, flags);
+ spin_lock_irqsave(&dev->req_lock, flags);
while (!list_empty (&dev->rx_reqs)) {
req = container_of (dev->rx_reqs.next,
struct usb_request, list);
list_del_init (&req->list);
- spin_unlock_irqrestore (&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
if (rx_submit (dev, req, gfp_flags) < 0) {
defer_kevent (dev, WORK_RX_MEMORY);
return;
}
- spin_lock_irqsave (&dev->lock, flags);
+ spin_lock_irqsave(&dev->req_lock, flags);
}
- spin_unlock_irqrestore (&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
}
static void eth_work (void *_dev)
@@ -1848,9 +1864,9 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
}
dev->stats.tx_packets++;
- spin_lock (&dev->lock);
+ spin_lock(&dev->req_lock);
list_add (&req->list, &dev->tx_reqs);
- spin_unlock (&dev->lock);
+ spin_unlock(&dev->req_lock);
dev_kfree_skb_any (skb);
atomic_dec (&dev->tx_qlen);
@@ -1896,12 +1912,12 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
}
- spin_lock_irqsave (&dev->lock, flags);
+ spin_lock_irqsave(&dev->req_lock, flags);
req = container_of (dev->tx_reqs.next, struct usb_request, list);
list_del (&req->list);
if (list_empty (&dev->tx_reqs))
netif_stop_queue (net);
- spin_unlock_irqrestore (&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
/* no buffer copies needed, unless the network stack did it
* or the hardware can't use skb buffers.
@@ -1955,11 +1971,11 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
drop:
dev->stats.tx_dropped++;
dev_kfree_skb_any (skb);
- spin_lock_irqsave (&dev->lock, flags);
+ spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty (&dev->tx_reqs))
netif_start_queue (net);
list_add (&req->list, &dev->tx_reqs);
- spin_unlock_irqrestore (&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
}
return 0;
}
@@ -2378,6 +2394,7 @@ autoconf_fail:
return status;
dev = netdev_priv(net);
spin_lock_init (&dev->lock);
+ spin_lock_init (&dev->req_lock);
INIT_WORK (&dev->work, eth_work, dev);
INIT_LIST_HEAD (&dev->tx_reqs);
INIT_LIST_HEAD (&dev->rx_reqs);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 66c3f61bc9d..431e8f31f1a 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -372,7 +372,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
* need to change any toggles in this URB */
td = list_entry(urbp->td_list.next, struct uhci_td, list);
if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
- td = list_entry(urbp->td_list.next, struct uhci_td,
+ td = list_entry(urbp->td_list.prev, struct uhci_td,
list);
toggle = uhci_toggle(td_token(td)) ^ 1;
@@ -1348,7 +1348,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
}
uhci_giveback_urb(uhci, qh, urb, regs);
- if (status < 0)
+ if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
break;
}
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 8ea9c915fbf..acb24c6219d 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1411,17 +1411,54 @@ void hid_init_reports(struct hid_device *hid)
warn("timeout initializing reports");
}
+#define USB_VENDOR_ID_GTCO 0x078c
+#define USB_DEVICE_ID_GTCO_90 0x0090
+#define USB_DEVICE_ID_GTCO_100 0x0100
+#define USB_DEVICE_ID_GTCO_101 0x0101
+#define USB_DEVICE_ID_GTCO_103 0x0103
+#define USB_DEVICE_ID_GTCO_104 0x0104
+#define USB_DEVICE_ID_GTCO_105 0x0105
+#define USB_DEVICE_ID_GTCO_106 0x0106
+#define USB_DEVICE_ID_GTCO_107 0x0107
+#define USB_DEVICE_ID_GTCO_108 0x0108
+#define USB_DEVICE_ID_GTCO_200 0x0200
+#define USB_DEVICE_ID_GTCO_201 0x0201
+#define USB_DEVICE_ID_GTCO_202 0x0202
+#define USB_DEVICE_ID_GTCO_203 0x0203
+#define USB_DEVICE_ID_GTCO_204 0x0204
+#define USB_DEVICE_ID_GTCO_205 0x0205
+#define USB_DEVICE_ID_GTCO_206 0x0206
+#define USB_DEVICE_ID_GTCO_207 0x0207
+#define USB_DEVICE_ID_GTCO_300 0x0300
+#define USB_DEVICE_ID_GTCO_301 0x0301
+#define USB_DEVICE_ID_GTCO_302 0x0302
+#define USB_DEVICE_ID_GTCO_303 0x0303
+#define USB_DEVICE_ID_GTCO_304 0x0304
+#define USB_DEVICE_ID_GTCO_305 0x0305
+#define USB_DEVICE_ID_GTCO_306 0x0306
+#define USB_DEVICE_ID_GTCO_307 0x0307
+#define USB_DEVICE_ID_GTCO_308 0x0308
+#define USB_DEVICE_ID_GTCO_309 0x0309
+#define USB_DEVICE_ID_GTCO_400 0x0400
+#define USB_DEVICE_ID_GTCO_401 0x0401
+#define USB_DEVICE_ID_GTCO_402 0x0402
+#define USB_DEVICE_ID_GTCO_403 0x0403
+#define USB_DEVICE_ID_GTCO_404 0x0404
+#define USB_DEVICE_ID_GTCO_404 0x0405
+#define USB_DEVICE_ID_GTCO_500 0x0500
+#define USB_DEVICE_ID_GTCO_501 0x0501
+#define USB_DEVICE_ID_GTCO_502 0x0502
+#define USB_DEVICE_ID_GTCO_503 0x0503
+#define USB_DEVICE_ID_GTCO_504 0x0504
+#define USB_DEVICE_ID_GTCO_1000 0x1000
+#define USB_DEVICE_ID_GTCO_1001 0x1001
+#define USB_DEVICE_ID_GTCO_1002 0x1002
+#define USB_DEVICE_ID_GTCO_1003 0x1003
+#define USB_DEVICE_ID_GTCO_1004 0x1004
+#define USB_DEVICE_ID_GTCO_1005 0x1005
+#define USB_DEVICE_ID_GTCO_1006 0x1006
+
#define USB_VENDOR_ID_WACOM 0x056a
-#define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000
-#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
-#define USB_DEVICE_ID_WACOM_PL 0x0030
-#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
-#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
-#define USB_DEVICE_ID_WACOM_PTU 0x0003
-#define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0
-#define USB_DEVICE_ID_WACOM_CINTIQ 0x003F
-#define USB_DEVICE_ID_WACOM_DTF 0x00C0
#define USB_VENDOR_ID_ACECAD 0x0460
#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004
@@ -1588,6 +1625,51 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
@@ -1617,49 +1699,6 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
@@ -1778,6 +1817,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
char *rdesc;
int n, len, insize = 0;
+ /* Ignore all Wacom devices */
+ if (dev->descriptor.idVendor == USB_VENDOR_ID_WACOM)
+ return NULL;
+
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
(hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index a54752ce149..006438069b6 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -131,6 +131,7 @@ struct usb_eth_dev {
#define VENDOR_COREGA 0x07aa
#define VENDOR_DLINK 0x2001
#define VENDOR_ELCON 0x0db7
+#define VENDOR_ELECOM 0x056e
#define VENDOR_ELSA 0x05cc
#define VENDOR_GIGABYTE 0x1044
#define VENDOR_HAWKING 0x0e66
@@ -233,6 +234,8 @@ PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
+PEGASUS_DEV( "ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM, 0x4010,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index bd09232ce13..a72685b9606 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -972,6 +972,7 @@ static void rtl8150_disconnect(struct usb_interface *intf)
if (dev) {
set_bit(RTL8150_UNPLUG, &dev->flags);
tasklet_disable(&dev->tl);
+ tasklet_kill(&dev->tl);
unregister_netdev(dev->netdev);
unlink_all_urbs(dev);
free_all_urbs(dev);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 4a803d69fa3..b130e170b4a 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -241,16 +241,6 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100,
"Finecam S5",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
-/* Patch for Kyocera Finecam L3
- * Submitted by Michael Krauth <michael.krauth@web.de>
- * and Alessandro Fracchetti <al.fracchetti@tin.it>
- */
-UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100,
- "Kyocera",
- "Finecam L3",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_FIX_INQUIRY),
-
/* Reported by Paul Stewart <stewart@wetlogic.net>
* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
@@ -599,6 +589,13 @@ UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* floppy reports multiple luns */
+UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210,
+ "SAMSUNG",
+ "SFD-321U [FW 0C]",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
"Y-E Data",
@@ -1257,6 +1254,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_NO_WP_DETECT ),
+/* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
+UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000,
+ "Sony Ericsson",
+ "M600i",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10.
* Entry is needed only for the initializer function override.
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 3e827e04a2a..276a21530b9 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1801,10 +1801,14 @@ static struct backlight_properties aty128_bl_data = {
static void aty128_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
- up(&info->bl_dev->sem);
- info->bl_dev->props->power = power;
- __aty128_bl_update_status(info->bl_dev);
- down(&info->bl_dev->sem);
+
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __aty128_bl_update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+
mutex_unlock(&info->bl_mutex);
}
@@ -1828,7 +1832,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
bd = backlight_device_register(name, par, &aty128_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
- printk("aty128: Backlight registration failed\n");
+ printk(KERN_WARNING "aty128: Backlight registration failed\n");
goto error;
}
@@ -1839,11 +1843,11 @@ static void aty128_bl_init(struct aty128fb_par *par)
219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = aty128_bl_data.max_brightness;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 053ff63365b..19a71f04578 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2200,10 +2200,14 @@ static struct backlight_properties aty_bl_data = {
static void aty_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
- up(&info->bl_dev->sem);
- info->bl_dev->props->power = power;
- __aty_bl_update_status(info->bl_dev);
- down(&info->bl_dev->sem);
+
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __aty_bl_update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+
mutex_unlock(&info->bl_mutex);
}
@@ -2223,7 +2227,7 @@ static void aty_bl_init(struct atyfb_par *par)
bd = backlight_device_register(name, par, &aty_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
- printk("aty: Backlight registration failed\n");
+ printk(KERN_WARNING "aty: Backlight registration failed\n");
goto error;
}
@@ -2234,11 +2238,11 @@ static void aty_bl_init(struct atyfb_par *par)
0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = aty_bl_data.max_brightness;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 1755dddf189..585eb7b9e63 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -195,11 +195,11 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
mutex_unlock(&rinfo->info->bl_mutex);
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = radeon_bl_data.max_brightness;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index b45f577094a..5b75ae4e945 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -113,10 +113,14 @@ static struct backlight_properties nvidia_bl_data = {
void nvidia_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
- up(&info->bl_dev->sem);
- info->bl_dev->props->power = power;
- __nvidia_bl_update_status(info->bl_dev);
- down(&info->bl_dev->sem);
+
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __nvidia_bl_update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+
mutex_unlock(&info->bl_mutex);
}
@@ -140,7 +144,7 @@ void nvidia_bl_init(struct nvidia_par *par)
bd = backlight_device_register(name, par, &nvidia_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
- printk("nvidia: Backlight registration failed\n");
+ printk(KERN_WARNING "nvidia: Backlight registration failed\n");
goto error;
}
@@ -151,11 +155,11 @@ void nvidia_bl_init(struct nvidia_par *par)
0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = nvidia_bl_data.max_brightness;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 76fc9d355eb..8ddb47a56b0 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -355,10 +355,14 @@ static struct backlight_properties riva_bl_data = {
static void riva_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
- up(&info->bl_dev->sem);
- info->bl_dev->props->power = power;
- __riva_bl_update_status(info->bl_dev);
- down(&info->bl_dev->sem);
+
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = power;
+ __riva_bl_update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+
mutex_unlock(&info->bl_mutex);
}
@@ -382,7 +386,7 @@ static void riva_bl_init(struct riva_par *par)
bd = backlight_device_register(name, par, &riva_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
- printk("riva: Backlight registration failed\n");
+ printk(KERN_WARNING "riva: Backlight registration failed\n");
goto error;
}
@@ -393,11 +397,11 @@ static void riva_bl_init(struct riva_par *par)
0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
- up(&bd->sem);
+ down(&bd->sem);
bd->props->brightness = riva_bl_data.max_brightness;
bd->props->power = FB_BLANK_UNBLANK;
bd->props->update_status(bd);
- down(&bd->sem);
+ up(&bd->sem);
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a61d17ed182..0feb3bd49cb 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
+Version 1.45
+------------
+Do not time out lockw calls when using posix extensions. Do not
+time out requests if server still responding reasonably fast
+on requests on other threads. Improve POSIX locking emulation,
+(lock cancel now works, and unlock of merged range works even
+to Windows servers now). Fix oops on mount to lanman servers
+(win9x, os/2 etc.) when null password. Do not send listxattr
+(SMB to query all EAs) if nouser_xattr specified.
+
Version 1.44
------------
Rewritten sessionsetup support, including support for legacy SMB
diff --git a/fs/cifs/README b/fs/cifs/README
index 7986d0d97ac..5f0e1bd64fe 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -408,7 +408,7 @@ A partial list of the supported mount options follows:
user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended
attributes) to the server (default) e.g. via setfattr
and getfattr utilities.
- nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
+ nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs
mapchars Translate six of the seven reserved characters (not backslash)
*?<>|:
to the remap range (above 0xF000), which also
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a89efaf78a2..4bc250b2d9f 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -277,7 +277,8 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
return;
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
- strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
+ if(ses->password)
+ strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
if(extended_security & CIFSSEC_MAY_PLNTXT) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c28ede59994..3cd750029be 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -402,7 +402,6 @@ static struct quotactl_ops cifs_quotactl_ops = {
};
#endif
-#ifdef CONFIG_CIFS_EXPERIMENTAL
static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
{
struct cifs_sb_info *cifs_sb;
@@ -422,7 +421,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
tcon->tidStatus = CifsExiting;
up(&tcon->tconSem);
- /* cancel_brl_requests(tcon); */
+ /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
if(tcon->ses && tcon->ses->server)
{
@@ -438,7 +437,6 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
return;
}
-#endif
static int cifs_remount(struct super_block *sb, int *flags, char *data)
{
@@ -457,9 +455,7 @@ struct super_operations cifs_super_ops = {
unless later we add lazy close of inodes or unless the kernel forgets to call
us with the same number of releases (closes) as opens */
.show_options = cifs_show_options,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.umount_begin = cifs_umount_begin,
-#endif
.remount_fs = cifs_remount,
};
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8f75c6f2470..39ee8ef3bde 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.44"
+#define CIFS_VERSION "1.45"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6d7cf5f3bc0..b24006c47df 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -3,6 +3,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
@@ -158,7 +159,8 @@ struct TCP_Server_Info {
/* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
__u32 sequence_number; /* needed for CIFS PDU signature */
- char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
+ char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
+ unsigned long lstrp; /* when we got last response from this server */
};
/*
@@ -266,14 +268,14 @@ struct cifsTconInfo {
};
/*
- * This info hangs off the cifsFileInfo structure. This is used to track
- * byte stream locks on the file
+ * This info hangs off the cifsFileInfo structure, pointed to by llist.
+ * This is used to track byte stream locks on the file
*/
struct cifsLockInfo {
- struct cifsLockInfo *next;
- int start;
- int length;
- int type;
+ struct list_head llist; /* pointer to next cifsLockInfo */
+ __u64 offset;
+ __u64 length;
+ __u8 type;
};
/*
@@ -304,6 +306,8 @@ struct cifsFileInfo {
/* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
+ struct semaphore lock_sem;
+ struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
atomic_t wrtPending; /* handle in use - defer close */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a5ddc62d6fe..b35c55c3c8b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op);
+extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
+ struct smb_hdr * /* input */ ,
+ struct smb_hdr * /* out */ ,
+ int * /* bytes returned */);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 19678c575df..075d8fb3d37 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
/* BB get server time for time conversions and add
code to use it and timezone since this is not UTC */
- if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+ if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
memcpy(server->cryptKey, rsp->EncryptionKey,
CIFS_CRYPTO_KEY_SIZE);
} else if (server->secMode & SECMODE_PW_ENCRYPT) {
@@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->hdr.smb_buf_length += count;
pSMB->ByteCount = cpu_to_le16(count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ if (waitFlag) {
+ rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned);
+ } else {
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+ }
cifs_stats_inc(&tcon->num_locks);
if (rc) {
cFYI(1, ("Send error in Lock = %d", rc));
@@ -1484,6 +1489,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
char *data_offset;
struct cifs_posix_lock *parm_data;
int rc = 0;
+ int timeout = 0;
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count, count;
@@ -1503,7 +1509,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
- pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
@@ -1529,8 +1534,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
(((char *) &pSMB->hdr.Protocol) + offset);
parm_data->lock_type = cpu_to_le16(lock_type);
- if(waitFlag)
+ if(waitFlag) {
+ timeout = 3; /* blocking operation, no timeout */
parm_data->lock_flags = cpu_to_le16(1);
+ pSMB->Timeout = cpu_to_le32(-1);
+ } else
+ pSMB->Timeout = 0;
+
parm_data->pid = cpu_to_le32(current->tgid);
parm_data->start = cpu_to_le64(pLockData->fl_start);
parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
@@ -1541,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (waitFlag) {
+ rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned);
+ } else {
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+ }
+
if (rc) {
cFYI(1, ("Send error in Posix Lock = %d", rc));
} else if (get_flag) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 876eb9ef85f..5d394c72686 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -182,6 +182,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
{
+ try_to_freeze();
if(server->protocolType == IPV6) {
rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
} else {
@@ -612,6 +613,10 @@ multi_t2_fnd:
#ifdef CONFIG_CIFS_STATS2
mid_entry->when_received = jiffies;
#endif
+ /* so we do not time out requests to server
+ which is still responding (since server could
+ be busy but not dead) */
+ server->lstrp = jiffies;
break;
}
}
@@ -1266,33 +1271,35 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
- cFYI(1, ("Next tcon - "));
+ cFYI(1, ("Next tcon"));
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->ses) {
if (tcon->ses->server) {
cFYI(1,
- (" old ip addr: %x == new ip %x ?",
+ ("old ip addr: %x == new ip %x ?",
tcon->ses->server->addr.sockAddr.sin_addr.
s_addr, new_target_ip_addr));
if (tcon->ses->server->addr.sockAddr.sin_addr.
s_addr == new_target_ip_addr) {
- /* BB lock tcon and server and tcp session and increment use count here? */
+ /* BB lock tcon, server and tcp session and increment use count here? */
/* found a match on the TCP session */
/* BB check if reconnection needed */
- cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
+ cFYI(1,("IP match, old UNC: %s new: %s",
tcon->treeName, uncName));
if (strncmp
(tcon->treeName, uncName,
MAX_TREE_SIZE) == 0) {
cFYI(1,
- ("Matched UNC, old user: %s == new: %s ?",
+ ("and old usr: %s new: %s",
tcon->treeName, uncName));
if (strncmp
(tcon->ses->userName,
userName,
MAX_USERNAME_SIZE) == 0) {
read_unlock(&GlobalSMBSeslock);
- return tcon;/* also matched user (smb session)*/
+ /* matched smb session
+ (user name */
+ return tcon;
}
}
}
@@ -1969,7 +1976,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
cFYI(1,("Negotiate caps 0x%x",(int)cap));
-
+#ifdef CONFIG_CIFS_DEBUG2
+ if(cap & CIFS_UNIX_FCNTL_CAP)
+ cFYI(1,("FCNTL cap"));
+ if(cap & CIFS_UNIX_EXTATTR_CAP)
+ cFYI(1,("EXTATTR cap"));
+ if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+ cFYI(1,("POSIX path cap"));
+ if(cap & CIFS_UNIX_XATTR_CAP)
+ cFYI(1,("XATTR cap"));
+ if(cap & CIFS_UNIX_POSIX_ACL_CAP)
+ cFYI(1,("POSIX ACL cap"));
+#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1,("setting capabilities failed"));
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index ba4cbe9b068..914239d5363 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -267,6 +267,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile->invalidHandle = FALSE;
pCifsFile->closePend = FALSE;
init_MUTEX(&pCifsFile->fh_sem);
+ init_MUTEX(&pCifsFile->lock_sem);
+ INIT_LIST_HEAD(&pCifsFile->llist);
+ atomic_set(&pCifsFile->wrtPending,0);
+
/* set the following in open now
pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 944d2b9e092..e9c5ba9084f 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -5,6 +5,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
@@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
private_data->netfid = netfid;
private_data->pid = current->tgid;
init_MUTEX(&private_data->fh_sem);
+ init_MUTEX(&private_data->lock_sem);
+ INIT_LIST_HEAD(&private_data->llist);
private_data->pfile = file; /* needed for writepage */
private_data->pInode = inode;
private_data->invalidHandle = FALSE;
@@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
+ struct cifsLockInfo *li, *tmp;
+
pSMBFile->closePend = TRUE;
if (pTcon) {
/* no sense reconnecting to close a file that is
@@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file)
pSMBFile->netfid);
}
}
+
+ /* Delete any outstanding lock records.
+ We'll lose them when the file is closed anyway. */
+ down(&pSMBFile->lock_sem);
+ list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
+ list_del(&li->llist);
+ kfree(li);
+ }
+ up(&pSMBFile->lock_sem);
+
write_lock(&GlobalSMBSeslock);
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
@@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
return rc;
}
+static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
+ __u64 offset, __u8 lockType)
+{
+ struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
+ if (li == NULL)
+ return -ENOMEM;
+ li->offset = offset;
+ li->length = len;
+ li->type = lockType;
+ down(&fid->lock_sem);
+ list_add(&li->llist, &fid->llist);
+ up(&fid->lock_sem);
+ return 0;
+}
+
int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
@@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
struct cifsTconInfo *pTcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
+ int posix_locking;
length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
@@ -639,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
}
netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
+ posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
/* BB add code here to normalize offset and length to
account for negative length which we can not accept over the
wire */
if (IS_GETLK(cmd)) {
- if(experimEnabled &&
- (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_FCNTL_CAP &
- le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+ if(posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
@@ -683,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid);
return rc;
}
- if (experimEnabled &&
- (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_FCNTL_CAP &
- le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+
+ if (!numLock && !numUnlock) {
+ /* if no lock or unlock then nothing
+ to do since we do not know what it is */
+ FreeXid(xid);
+ return -EOPNOTSUPP;
+ }
+
+ if (posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
@@ -695,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if(numUnlock == 1)
posix_lock_type = CIFS_UNLCK;
- else if(numLock == 0) {
- /* if no lock or unlock then nothing
- to do since we do not know what it is */
- FreeXid(xid);
- return -EOPNOTSUPP;
- }
+
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
length, pfLock,
posix_lock_type, wait_flag);
- } else
- rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
- numUnlock, numLock, lockType, wait_flag);
+ } else {
+ struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
+
+ if (numLock) {
+ rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+ 0, numLock, lockType, wait_flag);
+
+ if (rc == 0) {
+ /* For Windows locks we must store them. */
+ rc = store_file_lock(fid, length,
+ pfLock->fl_start, lockType);
+ }
+ } else if (numUnlock) {
+ /* For each stored lock that this unlock overlaps
+ completely, unlock it. */
+ int stored_rc = 0;
+ struct cifsLockInfo *li, *tmp;
+
+ down(&fid->lock_sem);
+ list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
+ if (pfLock->fl_start <= li->offset &&
+ length >= li->length) {
+ stored_rc = CIFSSMBLock(xid, pTcon, netfid,
+ li->length, li->offset,
+ 1, 0, li->type, FALSE);
+ if (stored_rc)
+ rc = stored_rc;
+
+ list_del(&li->llist);
+ kfree(li);
+ }
+ }
+ up(&fid->lock_sem);
+ }
+ }
+
if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock);
FreeXid(xid);
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index b66eff5dc62..ce87550e918 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRinvlevel,-EOPNOTSUPP},
{ERRdirnotempty, -ENOTEMPTY},
{ERRnotlocked, -ENOLCK},
+ {ERRcancelviolation, -ENOLCK},
{ERRalreadyexists, -EEXIST},
{ERRmoredata, -EOVERFLOW},
{ERReasnotsupported,-EOPNOTSUPP},
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 03bbcb37791..105761e3ba0 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -556,7 +556,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
FIND_FILE_STANDARD_INFO * pFindData =
(FIND_FILE_STANDARD_INFO *)current_entry;
filename = &pFindData->FileName[0];
- len = le32_to_cpu(pFindData->FileNameLength);
+ len = pFindData->FileNameLength;
} else {
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7202d534ef0..d1705ab8136 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -372,7 +372,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* no capabilities flags in old lanman negotiation */
- pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
+ pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
/* BB calculate hash with password */
/* and copy into bcc */
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index cd41c67ff8d..212c3c29640 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -95,6 +95,7 @@
#define ERRinvlevel 124
#define ERRdirnotempty 145
#define ERRnotlocked 158
+#define ERRcancelviolation 173
#define ERRalreadyexists 183
#define ERRbadpipe 230
#define ERRpipebusy 231
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 17ba329e2b3..48d47b46b1f 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -3,7 +3,8 @@
*
* Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
- *
+ * Jeremy Allison (jra@samba.org) 2006.
+ *
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
@@ -36,7 +37,7 @@ extern mempool_t *cifs_mid_poolp;
extern kmem_cache_t *cifs_oplock_cachep;
static struct mid_q_entry *
-AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
+AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
{
struct mid_q_entry *temp;
@@ -203,6 +204,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
rc = 0;
}
+ /* Don't want to modify the buffer as a
+ side effect of this call. */
+ smb_buffer->smb_buf_length = smb_buf_length;
+
return rc;
}
@@ -217,6 +222,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
unsigned int len = iov[0].iov_len;
unsigned int total_len;
int first_vec = 0;
+ unsigned int smb_buf_length = smb_buffer->smb_buf_length;
if(ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */
@@ -293,36 +299,15 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
} else
rc = 0;
+ /* Don't want to modify the buffer as a
+ side effect of this call. */
+ smb_buffer->smb_buf_length = smb_buf_length;
+
return rc;
}
-int
-SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
- struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
- const int long_op)
+static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
{
- int rc = 0;
- unsigned int receive_len;
- unsigned long timeout;
- struct mid_q_entry *midQ;
- struct smb_hdr *in_buf = iov[0].iov_base;
-
- *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
-
- if ((ses == NULL) || (ses->server == NULL)) {
- cifs_small_buf_release(in_buf);
- cERROR(1,("Null session"));
- return -EIO;
- }
-
- if(ses->server->tcpStatus == CifsExiting) {
- cifs_small_buf_release(in_buf);
- return -ENOENT;
- }
-
- /* Ensure that we do not send more than 50 overlapping requests
- to the same server. We may make this configurable later or
- use ses->maxReq */
if(long_op == -1) {
/* oplock breaks must not be held up */
atomic_inc(&ses->server->inFlight);
@@ -345,53 +330,140 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
} else {
if(ses->server->tcpStatus == CifsExiting) {
spin_unlock(&GlobalMid_Lock);
- cifs_small_buf_release(in_buf);
return -ENOENT;
}
- /* can not count locking commands against total since
- they are allowed to block on server */
+ /* can not count locking commands against total since
+ they are allowed to block on server */
- if(long_op < 3) {
/* update # of requests on the wire to server */
+ if (long_op < 3)
atomic_inc(&ses->server->inFlight);
- }
spin_unlock(&GlobalMid_Lock);
break;
}
}
}
- /* make sure that we sign in the same order that we send on this socket
- and avoid races inside tcp sendmsg code that could cause corruption
- of smb data */
-
- down(&ses->server->tcpSem);
+ return 0;
+}
+static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
+ struct mid_q_entry **ppmidQ)
+{
if (ses->server->tcpStatus == CifsExiting) {
- rc = -ENOENT;
- goto out_unlock2;
+ return -ENOENT;
} else if (ses->server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("tcp session dead - return to caller to retry"));
- rc = -EAGAIN;
- goto out_unlock2;
+ return -EAGAIN;
} else if (ses->status != CifsGood) {
/* check if SMB session is bad because we are setting it up */
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) {
- rc = -EAGAIN;
- goto out_unlock2;
+ return -EAGAIN;
} /* else ok - we are setting up session */
}
- midQ = AllocMidQEntry(in_buf, ses);
- if (midQ == NULL) {
+ *ppmidQ = AllocMidQEntry(in_buf, ses);
+ if (*ppmidQ == NULL) {
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int wait_for_response(struct cifsSesInfo *ses,
+ struct mid_q_entry *midQ,
+ unsigned long timeout,
+ unsigned long time_to_wait)
+{
+ unsigned long curr_timeout;
+
+ for (;;) {
+ curr_timeout = timeout + jiffies;
+ wait_event(ses->server->response_q,
+ (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
+ time_after(jiffies, curr_timeout) ||
+ ((ses->server->tcpStatus != CifsGood) &&
+ (ses->server->tcpStatus != CifsNew)));
+
+ if (time_after(jiffies, curr_timeout) &&
+ (midQ->midState == MID_REQUEST_SUBMITTED) &&
+ ((ses->server->tcpStatus == CifsGood) ||
+ (ses->server->tcpStatus == CifsNew))) {
+
+ unsigned long lrt;
+
+ /* We timed out. Is the server still
+ sending replies ? */
+ spin_lock(&GlobalMid_Lock);
+ lrt = ses->server->lstrp;
+ spin_unlock(&GlobalMid_Lock);
+
+ /* Calculate time_to_wait past last receive time.
+ Although we prefer not to time out if the
+ server is still responding - we will time
+ out if the server takes more than 15 (or 45
+ or 180) seconds to respond to this request
+ and has not responded to any request from
+ other threads on the client within 10 seconds */
+ lrt += time_to_wait;
+ if (time_after(jiffies, lrt)) {
+ /* No replies for time_to_wait. */
+ cERROR(1,("server not responding"));
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+ }
+}
+
+int
+SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
+ struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
+ const int long_op)
+{
+ int rc = 0;
+ unsigned int receive_len;
+ unsigned long timeout;
+ struct mid_q_entry *midQ;
+ struct smb_hdr *in_buf = iov[0].iov_base;
+
+ *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
+
+ if ((ses == NULL) || (ses->server == NULL)) {
+ cifs_small_buf_release(in_buf);
+ cERROR(1,("Null session"));
+ return -EIO;
+ }
+
+ if(ses->server->tcpStatus == CifsExiting) {
+ cifs_small_buf_release(in_buf);
+ return -ENOENT;
+ }
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+
+ rc = wait_for_free_request(ses, long_op);
+ if (rc) {
+ cifs_small_buf_release(in_buf);
+ return rc;
+ }
+
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ down(&ses->server->tcpSem);
+
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {
up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
- return -ENOMEM;
+ /* Update # of requests on wire to server */
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ return rc;
}
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
@@ -406,32 +478,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
atomic_dec(&ses->server->inSend);
midQ->when_sent = jiffies;
#endif
- if(rc < 0) {
- DeleteMidQEntry(midQ);
- up(&ses->server->tcpSem);
- cifs_small_buf_release(in_buf);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
- return rc;
- } else {
- up(&ses->server->tcpSem);
- cifs_small_buf_release(in_buf);
- }
+
+ up(&ses->server->tcpSem);
+ cifs_small_buf_release(in_buf);
+
+ if(rc < 0)
+ goto out;
if (long_op == -1)
- goto cifs_no_response_exit2;
+ goto out;
else if (long_op == 2) /* writes past end of file can take loong time */
timeout = 180 * HZ;
else if (long_op == 1)
timeout = 45 * HZ; /* should be greater than
servers oplock break timeout (about 43 seconds) */
- else if (long_op > 2) {
- timeout = MAX_SCHEDULE_TIMEOUT;
- } else
+ else
timeout = 15 * HZ;
+
/* wait for 15 seconds or until woken up due to response arriving or
due to last connection to this server being unmounted */
if (signal_pending(current)) {
@@ -441,19 +504,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
/* No user interrupts in wait - wreaks havoc with performance */
- if(timeout != MAX_SCHEDULE_TIMEOUT) {
- timeout += jiffies;
- wait_event(ses->server->response_q,
- (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
- time_after(jiffies, timeout) ||
- ((ses->server->tcpStatus != CifsGood) &&
- (ses->server->tcpStatus != CifsNew)));
- } else {
- wait_event(ses->server->response_q,
- (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
- ((ses->server->tcpStatus != CifsGood) &&
- (ses->server->tcpStatus != CifsNew)));
- }
+ wait_for_response(ses, midQ, timeout, 10 * HZ);
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
@@ -481,11 +532,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
+ /* Update # of requests on wire to server */
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
return rc;
}
@@ -536,24 +585,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
cFYI(1,("Bad MID state?"));
}
}
-cifs_no_response_exit2:
- DeleteMidQEntry(midQ);
-
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
- return rc;
+out:
-out_unlock2:
- up(&ses->server->tcpSem);
- cifs_small_buf_release(in_buf);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
+ DeleteMidQEntry(midQ);
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
return rc;
}
@@ -583,85 +620,34 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
/* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or
use ses->maxReq */
- if(long_op == -1) {
- /* oplock breaks must not be held up */
- atomic_inc(&ses->server->inFlight);
- } else {
- spin_lock(&GlobalMid_Lock);
- while(1) {
- if(atomic_read(&ses->server->inFlight) >=
- cifs_max_pending){
- spin_unlock(&GlobalMid_Lock);
-#ifdef CONFIG_CIFS_STATS2
- atomic_inc(&ses->server->num_waiters);
-#endif
- wait_event(ses->server->request_q,
- atomic_read(&ses->server->inFlight)
- < cifs_max_pending);
-#ifdef CONFIG_CIFS_STATS2
- atomic_dec(&ses->server->num_waiters);
-#endif
- spin_lock(&GlobalMid_Lock);
- } else {
- if(ses->server->tcpStatus == CifsExiting) {
- spin_unlock(&GlobalMid_Lock);
- return -ENOENT;
- }
- /* can not count locking commands against total since
- they are allowed to block on server */
-
- if(long_op < 3) {
- /* update # of requests on the wire to server */
- atomic_inc(&ses->server->inFlight);
- }
- spin_unlock(&GlobalMid_Lock);
- break;
- }
- }
- }
+ rc = wait_for_free_request(ses, long_op);
+ if (rc)
+ return rc;
+
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
- if (ses->server->tcpStatus == CifsExiting) {
- rc = -ENOENT;
- goto out_unlock;
- } else if (ses->server->tcpStatus == CifsNeedReconnect) {
- cFYI(1,("tcp session dead - return to caller to retry"));
- rc = -EAGAIN;
- goto out_unlock;
- } else if (ses->status != CifsGood) {
- /* check if SMB session is bad because we are setting it up */
- if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
- (in_buf->Command != SMB_COM_NEGOTIATE)) {
- rc = -EAGAIN;
- goto out_unlock;
- } /* else ok - we are setting up session */
- }
- midQ = AllocMidQEntry(in_buf, ses);
- if (midQ == NULL) {
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {
up(&ses->server->tcpSem);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
- return -ENOMEM;
+ /* Update # of requests on wire to server */
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ return rc;
}
if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- up(&ses->server->tcpSem);
cERROR(1, ("Illegal length, greater than maximum frame, %d",
in_buf->smb_buf_length));
DeleteMidQEntry(midQ);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
+ up(&ses->server->tcpSem);
+ /* Update # of requests on wire to server */
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
return -EIO;
}
@@ -677,27 +663,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
atomic_dec(&ses->server->inSend);
midQ->when_sent = jiffies;
#endif
- if(rc < 0) {
- DeleteMidQEntry(midQ);
- up(&ses->server->tcpSem);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
- return rc;
- } else
- up(&ses->server->tcpSem);
+ up(&ses->server->tcpSem);
+
+ if(rc < 0)
+ goto out;
+
if (long_op == -1)
- goto cifs_no_response_exit;
+ goto out;
else if (long_op == 2) /* writes past end of file can take loong time */
timeout = 180 * HZ;
else if (long_op == 1)
timeout = 45 * HZ; /* should be greater than
servers oplock break timeout (about 43 seconds) */
- else if (long_op > 2) {
- timeout = MAX_SCHEDULE_TIMEOUT;
- } else
+ else
timeout = 15 * HZ;
/* wait for 15 seconds or until woken up due to response arriving or
due to last connection to this server being unmounted */
@@ -708,19 +686,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
}
/* No user interrupts in wait - wreaks havoc with performance */
- if(timeout != MAX_SCHEDULE_TIMEOUT) {
- timeout += jiffies;
- wait_event(ses->server->response_q,
- (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
- time_after(jiffies, timeout) ||
- ((ses->server->tcpStatus != CifsGood) &&
- (ses->server->tcpStatus != CifsNew)));
- } else {
- wait_event(ses->server->response_q,
- (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
- ((ses->server->tcpStatus != CifsGood) &&
- (ses->server->tcpStatus != CifsNew)));
- }
+ wait_for_response(ses, midQ, timeout, 10 * HZ);
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
@@ -748,11 +714,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
}
spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
+ /* Update # of requests on wire to server */
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
return rc;
}
@@ -799,23 +763,253 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
cERROR(1,("Bad MID state?"));
}
}
-cifs_no_response_exit:
+
+out:
+
DeleteMidQEntry(midQ);
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
- }
+ return rc;
+}
+
+/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
+
+static int
+send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
+ struct mid_q_entry *midQ)
+{
+ int rc = 0;
+ struct cifsSesInfo *ses = tcon->ses;
+ __u16 mid = in_buf->Mid;
+ header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
+ in_buf->Mid = mid;
+ down(&ses->server->tcpSem);
+ rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+ if (rc) {
+ up(&ses->server->tcpSem);
+ return rc;
+ }
+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+ (struct sockaddr *) &(ses->server->addr.sockAddr));
+ up(&ses->server->tcpSem);
return rc;
+}
+
+/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
+ blocking lock to return. */
+
+static int
+send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
+ struct smb_hdr *in_buf,
+ struct smb_hdr *out_buf)
+{
+ int bytes_returned;
+ struct cifsSesInfo *ses = tcon->ses;
+ LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
+
+ /* We just modify the current in_buf to change
+ the type of lock from LOCKING_ANDX_SHARED_LOCK
+ or LOCKING_ANDX_EXCLUSIVE_LOCK to
+ LOCKING_ANDX_CANCEL_LOCK. */
+
+ pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
+ pSMB->Timeout = 0;
+ pSMB->hdr.Mid = GetNextMid(ses->server);
+
+ return SendReceive(xid, ses, in_buf, out_buf,
+ &bytes_returned, 0);
+}
-out_unlock:
+int
+SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
+ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+ int *pbytes_returned)
+{
+ int rc = 0;
+ int rstart = 0;
+ unsigned int receive_len;
+ struct mid_q_entry *midQ;
+ struct cifsSesInfo *ses;
+
+ if (tcon == NULL || tcon->ses == NULL) {
+ cERROR(1,("Null smb session"));
+ return -EIO;
+ }
+ ses = tcon->ses;
+
+ if(ses->server == NULL) {
+ cERROR(1,("Null tcp session"));
+ return -EIO;
+ }
+
+ if(ses->server->tcpStatus == CifsExiting)
+ return -ENOENT;
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+
+ rc = wait_for_free_request(ses, 3);
+ if (rc)
+ return rc;
+
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ down(&ses->server->tcpSem);
+
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {
+ up(&ses->server->tcpSem);
+ return rc;
+ }
+
+ if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ up(&ses->server->tcpSem);
+ cERROR(1, ("Illegal length, greater than maximum frame, %d",
+ in_buf->smb_buf_length));
+ DeleteMidQEntry(midQ);
+ return -EIO;
+ }
+
+ rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+
+ midQ->midState = MID_REQUEST_SUBMITTED;
+#ifdef CONFIG_CIFS_STATS2
+ atomic_inc(&ses->server->inSend);
+#endif
+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+ (struct sockaddr *) &(ses->server->addr.sockAddr));
+#ifdef CONFIG_CIFS_STATS2
+ atomic_dec(&ses->server->inSend);
+ midQ->when_sent = jiffies;
+#endif
up(&ses->server->tcpSem);
- /* If not lock req, update # of requests on wire to server */
- if(long_op < 3) {
- atomic_dec(&ses->server->inFlight);
- wake_up(&ses->server->request_q);
+
+ if(rc < 0) {
+ DeleteMidQEntry(midQ);
+ return rc;
+ }
+
+ /* Wait for a reply - allow signals to interrupt. */
+ rc = wait_event_interruptible(ses->server->response_q,
+ (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
+ ((ses->server->tcpStatus != CifsGood) &&
+ (ses->server->tcpStatus != CifsNew)));
+
+ /* Were we interrupted by a signal ? */
+ if ((rc == -ERESTARTSYS) &&
+ (midQ->midState == MID_REQUEST_SUBMITTED) &&
+ ((ses->server->tcpStatus == CifsGood) ||
+ (ses->server->tcpStatus == CifsNew))) {
+
+ if (in_buf->Command == SMB_COM_TRANSACTION2) {
+ /* POSIX lock. We send a NT_CANCEL SMB to cause the
+ blocking lock to return. */
+
+ rc = send_nt_cancel(tcon, in_buf, midQ);
+ if (rc) {
+ DeleteMidQEntry(midQ);
+ return rc;
+ }
+ } else {
+ /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
+ to cause the blocking lock to return. */
+
+ rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
+
+ /* If we get -ENOLCK back the lock may have
+ already been removed. Don't exit in this case. */
+ if (rc && rc != -ENOLCK) {
+ DeleteMidQEntry(midQ);
+ return rc;
+ }
+ }
+
+ /* Wait 5 seconds for the response. */
+ if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) {
+ /* We got the response - restart system call. */
+ rstart = 1;
+ }
+ }
+
+ spin_lock(&GlobalMid_Lock);
+ if (midQ->resp_buf) {
+ spin_unlock(&GlobalMid_Lock);
+ receive_len = midQ->resp_buf->smb_buf_length;
+ } else {
+ cERROR(1,("No response for cmd %d mid %d",
+ midQ->command, midQ->mid));
+ if(midQ->midState == MID_REQUEST_SUBMITTED) {
+ if(ses->server->tcpStatus == CifsExiting)
+ rc = -EHOSTDOWN;
+ else {
+ ses->server->tcpStatus = CifsNeedReconnect;
+ midQ->midState = MID_RETRY_NEEDED;
+ }
+ }
+
+ if (rc != -EHOSTDOWN) {
+ if(midQ->midState == MID_RETRY_NEEDED) {
+ rc = -EAGAIN;
+ cFYI(1,("marking request for retry"));
+ } else {
+ rc = -EIO;
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ DeleteMidQEntry(midQ);
+ return rc;
}
+
+ if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
+ cERROR(1, ("Frame too large received. Length: %d Xid: %d",
+ receive_len, xid));
+ rc = -EIO;
+ } else { /* rcvd frame is ok */
+
+ if (midQ->resp_buf && out_buf
+ && (midQ->midState == MID_RESPONSE_RECEIVED)) {
+ out_buf->smb_buf_length = receive_len;
+ memcpy((char *)out_buf + 4,
+ (char *)midQ->resp_buf + 4,
+ receive_len);
+
+ dump_smb(out_buf, 92);
+ /* convert the length into a more usable form */
+ if((receive_len > 24) &&
+ (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
+ SECMODE_SIGN_ENABLED))) {
+ rc = cifs_verify_signature(out_buf,
+ ses->server->mac_signing_key,
+ midQ->sequence_number+1);
+ if(rc) {
+ cERROR(1,("Unexpected SMB signature"));
+ /* BB FIXME add code to kill session */
+ }
+ }
+
+ *pbytes_returned = out_buf->smb_buf_length;
+
+ /* BB special case reconnect tid and uid here? */
+ rc = map_smb_to_linux_error(out_buf);
+ /* convert ByteCount if necessary */
+ if (receive_len >=
+ sizeof (struct smb_hdr) -
+ 4 /* do not count RFC1001 header */ +
+ (2 * out_buf->WordCount) + 2 /* bcc */ )
+ BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
+ } else {
+ rc = -EIO;
+ cERROR(1,("Bad MID state?"));
+ }
+ }
+ DeleteMidQEntry(midQ);
+ if (rstart && rc == -EACCES)
+ return -ERESTARTSYS;
return rc;
}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 7754d641775..067648b7179 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -330,11 +330,15 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
sb = direntry->d_inode->i_sb;
if(sb == NULL)
return -EIO;
- xid = GetXid();
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ return -EOPNOTSUPP;
+
+ xid = GetXid();
+
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index de2e4cbbf79..f5169a96260 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -727,7 +727,7 @@ done:
out:
if (unlikely(frozen_buffer)) /* It's usually NULL */
- kfree(frozen_buffer);
+ jbd_slab_free(frozen_buffer, bh->b_size);
JBUFFER_TRACE(jh, "exit");
return error;
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 3a613753906..bf46fae303a 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4993,7 +4993,7 @@ xfs_bmapi(
bma.firstblock = *firstblock;
bma.alen = alen;
bma.off = aoff;
- bma.conv = (flags & XFS_BMAPI_CONVERT);
+ bma.conv = !!(flags & XFS_BMAPI_CONVERT);
bma.wasdel = wasdelay;
bma.minlen = minlen;
bma.low = flist->xbf_low;
diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h
index 949878c0d90..ea200551a75 100644
--- a/include/asm-arm/arch-pxa/ssp.h
+++ b/include/asm-arm/arch-pxa/ssp.h
@@ -40,8 +40,8 @@ struct ssp_dev {
};
int ssp_write_word(struct ssp_dev *dev, u32 data);
-int ssp_read_word(struct ssp_dev *dev);
-void ssp_flush(struct ssp_dev *dev);
+int ssp_read_word(struct ssp_dev *dev, u32 *data);
+int ssp_flush(struct ssp_dev *dev);
void ssp_enable(struct ssp_dev *dev);
void ssp_disable(struct ssp_dev *dev);
void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 7463fd5252c..3661e465b0a 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -1,18 +1,13 @@
-/* linux/include/asm-arm/arch-bast/dma.h
+/* linux/include/asm-arm/arch-s3c2410/dma.h
*
- * Copyright (C) 2003,2004 Simtec Electronics
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * Samsung S3C2410X DMA support
+ * Samsung S3C241XX DMA support
*
* 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.
- *
- * Changelog:
- * ??-May-2003 BJD Created file
- * ??-Jun-2003 BJD Added more dma functionality to go with arch
- * 10-Nov-2004 BJD Added sys_device support
*/
#ifndef __ASM_ARCH_DMA_H
@@ -21,28 +16,26 @@
#include <linux/sysdev.h>
#include "hardware.h"
-
/*
* This is the maximum DMA address(physical address) that can be DMAd to.
*
*/
-#define MAX_DMA_ADDRESS 0x20000000
+#define MAX_DMA_ADDRESS 0x40000000
#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
-
/* we have 4 dma channels */
#define S3C2410_DMA_CHANNELS (4)
/* types */
-typedef enum {
+enum s3c2410_dma_state {
S3C2410_DMA_IDLE,
S3C2410_DMA_RUNNING,
S3C2410_DMA_PAUSED
-} s3c2410_dma_state_t;
+};
-/* s3c2410_dma_loadst_t
+/* enum s3c2410_dma_loadst
*
* This represents the state of the DMA engine, wrt to the loaded / running
* transfers. Since we don't have any way of knowing exactly the state of
@@ -70,45 +63,40 @@ typedef enum {
* currently running.
*/
-typedef enum {
+enum s3c2410_dma_loadst {
S3C2410_DMALOAD_NONE,
S3C2410_DMALOAD_1LOADED,
S3C2410_DMALOAD_1RUNNING,
S3C2410_DMALOAD_1LOADED_1RUNNING,
-} s3c2410_dma_loadst_t;
+};
-typedef enum {
+enum s3c2410_dma_buffresult {
S3C2410_RES_OK,
S3C2410_RES_ERR,
S3C2410_RES_ABORT
-} s3c2410_dma_buffresult_t;
-
-
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+};
-enum s3c2410_dmasrc_e {
- S3C2410_DMASRC_HW, /* source is memory */
- S3C2410_DMASRC_MEM /* source is hardware */
+enum s3c2410_dmasrc {
+ S3C2410_DMASRC_HW, /* source is memory */
+ S3C2410_DMASRC_MEM /* source is hardware */
};
-/* enum s3c2410_chan_op_e
+/* enum s3c2410_chan_op
*
* operation codes passed to the DMA code by the user, and also used
* to inform the current channel owner of any changes to the system state
*/
-enum s3c2410_chan_op_e {
+enum s3c2410_chan_op {
S3C2410_DMAOP_START,
S3C2410_DMAOP_STOP,
S3C2410_DMAOP_PAUSE,
S3C2410_DMAOP_RESUME,
S3C2410_DMAOP_FLUSH,
- S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
+ S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
S3C2410_DMAOP_STARTED, /* indicate channel started */
};
-typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
-
/* flags */
#define S3C2410_DMAF_SLOW (1<<0) /* slow, so don't worry about
@@ -117,104 +105,100 @@ typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
/* dma buffer */
-typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
-
struct s3c2410_dma_client {
char *name;
};
-typedef struct s3c2410_dma_client s3c2410_dma_client_t;
-
/* s3c2410_dma_buf_s
*
* internally used buffer structure to describe a queued or running
* buffer.
*/
-struct s3c2410_dma_buf_s {
- s3c2410_dma_buf_t *next;
- int magic; /* magic */
- int size; /* buffer size in bytes */
- dma_addr_t data; /* start of DMA data */
- dma_addr_t ptr; /* where the DMA got to [1] */
- void *id; /* client's id */
+struct s3c2410_dma_buf;
+struct s3c2410_dma_buf {
+ struct s3c2410_dma_buf *next;
+ int magic; /* magic */
+ int size; /* buffer size in bytes */
+ dma_addr_t data; /* start of DMA data */
+ dma_addr_t ptr; /* where the DMA got to [1] */
+ void *id; /* client's id */
};
/* [1] is this updated for both recv/send modes? */
-typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
+struct s3c2410_dma_chan;
/* s3c2410_dma_cbfn_t
*
* buffer callback routine type
*/
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
- s3c2410_dma_buffresult_t result);
+typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
+ void *buf, int size,
+ enum s3c2410_dma_buffresult result);
-typedef int (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
- s3c2410_chan_op_t );
+typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
+ enum s3c2410_chan_op );
-struct s3c2410_dma_stats_s {
- unsigned long loads;
- unsigned long timeout_longest;
- unsigned long timeout_shortest;
- unsigned long timeout_avg;
- unsigned long timeout_failed;
+struct s3c2410_dma_stats {
+ unsigned long loads;
+ unsigned long timeout_longest;
+ unsigned long timeout_shortest;
+ unsigned long timeout_avg;
+ unsigned long timeout_failed;
};
-typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
-
-/* struct s3c2410_dma_chan_s
+/* struct s3c2410_dma_chan
*
* full state information for each DMA channel
*/
-struct s3c2410_dma_chan_s {
+struct s3c2410_dma_chan {
/* channel state flags and information */
- unsigned char number; /* number of this dma channel */
- unsigned char in_use; /* channel allocated */
- unsigned char irq_claimed; /* irq claimed for channel */
- unsigned char irq_enabled; /* irq enabled for channel */
- unsigned char xfer_unit; /* size of an transfer */
+ unsigned char number; /* number of this dma channel */
+ unsigned char in_use; /* channel allocated */
+ unsigned char irq_claimed; /* irq claimed for channel */
+ unsigned char irq_enabled; /* irq enabled for channel */
+ unsigned char xfer_unit; /* size of an transfer */
/* channel state */
- s3c2410_dma_state_t state;
- s3c2410_dma_loadst_t load_state;
- s3c2410_dma_client_t *client;
+ enum s3c2410_dma_state state;
+ enum s3c2410_dma_loadst load_state;
+ struct s3c2410_dma_client *client;
/* channel configuration */
- s3c2410_dmasrc_t source;
- unsigned long dev_addr;
- unsigned long load_timeout;
- unsigned int flags; /* channel flags */
+ enum s3c2410_dmasrc source;
+ unsigned long dev_addr;
+ unsigned long load_timeout;
+ unsigned int flags; /* channel flags */
/* channel's hardware position and configuration */
- void __iomem *regs; /* channels registers */
- void __iomem *addr_reg; /* data address register */
- unsigned int irq; /* channel irq */
- unsigned long dcon; /* default value of DCON */
+ void __iomem *regs; /* channels registers */
+ void __iomem *addr_reg; /* data address register */
+ unsigned int irq; /* channel irq */
+ unsigned long dcon; /* default value of DCON */
/* driver handles */
- s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
- s3c2410_dma_opfn_t op_fn; /* channel operation callback */
+ s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
+ s3c2410_dma_opfn_t op_fn; /* channel op callback */
/* stats gathering */
- s3c2410_dma_stats_t *stats;
- s3c2410_dma_stats_t stats_store;
+ struct s3c2410_dma_stats *stats;
+ struct s3c2410_dma_stats stats_store;
/* buffer list and information */
- s3c2410_dma_buf_t *curr; /* current dma buffer */
- s3c2410_dma_buf_t *next; /* next buffer to load */
- s3c2410_dma_buf_t *end; /* end of queue */
+ struct s3c2410_dma_buf *curr; /* current dma buffer */
+ struct s3c2410_dma_buf *next; /* next buffer to load */
+ struct s3c2410_dma_buf *end; /* end of queue */
/* system device */
struct sys_device dev;
};
/* the currently allocated channel information */
-extern s3c2410_dma_chan_t s3c2410_chans[];
+extern struct s3c2410_dma_chan s3c2410_chans[];
/* note, we don't really use dma_device_t at the moment */
typedef unsigned long dma_device_t;
@@ -227,7 +211,7 @@ typedef unsigned long dma_device_t;
*/
extern int s3c2410_dma_request(dmach_t channel,
- s3c2410_dma_client_t *, void *dev);
+ struct s3c2410_dma_client *, void *dev);
/* s3c2410_dma_ctrl
@@ -235,7 +219,7 @@ extern int s3c2410_dma_request(dmach_t channel,
* change the state of the dma channel
*/
-extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
+extern int s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op);
/* s3c2410_dma_setflags
*
@@ -250,7 +234,7 @@ extern int s3c2410_dma_setflags(dmach_t channel,
* free the dma channel (will also abort any outstanding operations)
*/
-extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
+extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *);
/* s3c2410_dma_enqueue
*
@@ -274,7 +258,7 @@ extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon);
* configure the device we're talking to
*/
-extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
+extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
int hwcfg, unsigned long devaddr);
/* s3c2410_dma_getposition
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index fe0c744e026..e4a2569c636 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -247,14 +247,12 @@ extern void dmac_flush_range(unsigned long, unsigned long);
*/
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
- flush_dcache_page(page); \
+ flush_ptrace_access(vma, page, vaddr, dst, len, 1);\
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
} while (0)
@@ -285,10 +283,24 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l
__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
}
}
+
+static inline void
+flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+ unsigned long uaddr, void *kaddr,
+ unsigned long len, int write)
+{
+ if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
+ unsigned long addr = (unsigned long)kaddr;
+ __cpuc_coherent_kern_range(addr, addr + len);
+ }
+}
#else
extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
+extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+ unsigned long uaddr, void *kaddr,
+ unsigned long len, int write);
#endif
/*
diff --git a/include/asm-arm/hardware/ssp.h b/include/asm-arm/hardware/ssp.h
index 28aa11b769c..3b42e181997 100644
--- a/include/asm-arm/hardware/ssp.h
+++ b/include/asm-arm/hardware/ssp.h
@@ -16,8 +16,8 @@ struct ssp_state {
};
int ssp_write_word(u16 data);
-int ssp_read_word(void);
-void ssp_flush(void);
+int ssp_read_word(u16 *data);
+int ssp_flush(void);
void ssp_enable(void);
void ssp_disable(void);
void ssp_save_state(struct ssp_state *ssp);
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index b3479fc1cc8..bf7b9dea30f 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -291,5 +291,12 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
*/
#define xlate_dev_kmem_ptr(p) p
+/*
+ * Register ISA memory and port locations for glibc iopl/inb/outb
+ * emulation.
+ */
+extern void register_isa_ports(unsigned int mmio, unsigned int io,
+ unsigned int io_shift);
+
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_IO_H */
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 406ca97a8ab..e2f1d75171d 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -199,7 +199,21 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
: "cc");
}
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+ unsigned long tmp tmp2 = 1;
+
+ __asm__ __volatile__(
+"1: ldrex %0, [%2]\n"
+" adds %0, %0, #1\n"
+" strexpl %1, %0, [%2]\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ : "r" (&rw->lock)
+ : "cc");
+
+ smp_mb();
+ return tmp2 == 0;
+}
/* read_can_lock - would read_trylock() succeed? */
#define __raw_read_can_lock(x) ((x)->lock < 0x80000000)
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h
index 96adbabec74..b01a7ec409c 100644
--- a/include/asm-i386/alternative.h
+++ b/include/asm-i386/alternative.h
@@ -88,9 +88,6 @@ static inline void alternatives_smp_switch(int smp) {}
/*
* Alternative inline assembly for SMP.
*
- * alternative_smp() takes two versions (SMP first, UP second) and is
- * for more complex stuff such as spinlocks.
- *
* The LOCK_PREFIX macro defined here replaces the LOCK and
* LOCK_PREFIX macros used everywhere in the source tree.
*
@@ -110,21 +107,6 @@ static inline void alternatives_smp_switch(int smp) {}
*/
#ifdef CONFIG_SMP
-#define alternative_smp(smpinstr, upinstr, args...) \
- asm volatile ("661:\n\t" smpinstr "\n662:\n" \
- ".section .smp_altinstructions,\"a\"\n" \
- " .align 4\n" \
- " .long 661b\n" /* label */ \
- " .long 663f\n" /* new instruction */ \
- " .byte 0x68\n" /* X86_FEATURE_UP */ \
- " .byte 662b-661b\n" /* sourcelen */ \
- " .byte 664f-663f\n" /* replacementlen */ \
- ".previous\n" \
- ".section .smp_altinstr_replacement,\"awx\"\n" \
- "663:\n\t" upinstr "\n" /* replacement */ \
- "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
- ".previous" : args)
-
#define LOCK_PREFIX \
".section .smp_locks,\"a\"\n" \
" .align 4\n" \
@@ -133,8 +115,6 @@ static inline void alternatives_smp_switch(int smp) {}
"661:\n\tlock; "
#else /* ! CONFIG_SMP */
-#define alternative_smp(smpinstr, upinstr, args...) \
- asm volatile (upinstr : args)
#define LOCK_PREFIX ""
#endif
diff --git a/include/asm-i386/mach-default/mach_mpspec.h b/include/asm-i386/mach-default/mach_mpspec.h
index 6b5dadcf1d0..51c9a977593 100644
--- a/include/asm-i386/mach-default/mach_mpspec.h
+++ b/include/asm-i386/mach-default/mach_mpspec.h
@@ -3,6 +3,10 @@
#define MAX_IRQ_SOURCES 256
+#if CONFIG_BASE_SMALL == 0
+#define MAX_MP_BUSSES 256
+#else
#define MAX_MP_BUSSES 32
+#endif
#endif /* __ASM_MACH_MPSPEC_H */
diff --git a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h
index 96b0bef2ea5..87c069ccba0 100644
--- a/include/asm-i386/rwlock.h
+++ b/include/asm-i386/rwlock.h
@@ -21,23 +21,21 @@
#define RW_LOCK_BIAS_STR "0x01000000"
#define __build_read_lock_ptr(rw, helper) \
- alternative_smp("lock; subl $1,(%0)\n\t" \
+ asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" \
"jns 1f\n" \
"call " helper "\n\t" \
- "1:\n", \
- "subl $1,(%0)\n\t", \
- :"a" (rw) : "memory")
+ "1:\n" \
+ ::"a" (rw) : "memory")
#define __build_read_lock_const(rw, helper) \
- alternative_smp("lock; subl $1,%0\n\t" \
+ asm volatile(LOCK_PREFIX " subl $1,%0\n\t" \
"jns 1f\n" \
"pushl %%eax\n\t" \
"leal %0,%%eax\n\t" \
"call " helper "\n\t" \
"popl %%eax\n\t" \
- "1:\n", \
- "subl $1,%0\n\t", \
- "+m" (*(volatile int *)rw) : : "memory")
+ "1:\n" \
+ :"+m" (*(volatile int *)rw) : : "memory")
#define __build_read_lock(rw, helper) do { \
if (__builtin_constant_p(rw)) \
@@ -47,23 +45,21 @@
} while (0)
#define __build_write_lock_ptr(rw, helper) \
- alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+ asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
"jz 1f\n" \
"call " helper "\n\t" \
- "1:\n", \
- "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t", \
- :"a" (rw) : "memory")
+ "1:\n" \
+ ::"a" (rw) : "memory")
#define __build_write_lock_const(rw, helper) \
- alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+ asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
"jz 1f\n" \
"pushl %%eax\n\t" \
"leal %0,%%eax\n\t" \
"call " helper "\n\t" \
"popl %%eax\n\t" \
- "1:\n", \
- "subl $" RW_LOCK_BIAS_STR ",%0\n\t", \
- "+m" (*(volatile int *)rw) : : "memory")
+ "1:\n" \
+ :"+m" (*(volatile int *)rw) : : "memory")
#define __build_write_lock(rw, helper) do { \
if (__builtin_constant_p(rw)) \
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index d816c62a7a1..d1020363c41 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -22,7 +22,7 @@
#define __raw_spin_lock_string \
"\n1:\t" \
- "lock ; decb %0\n\t" \
+ LOCK_PREFIX " ; decb %0\n\t" \
"jns 3f\n" \
"2:\t" \
"rep;nop\n\t" \
@@ -38,7 +38,7 @@
*/
#define __raw_spin_lock_string_flags \
"\n1:\t" \
- "lock ; decb %0\n\t" \
+ LOCK_PREFIX " ; decb %0\n\t" \
"jns 5f\n" \
"2:\t" \
"testl $0x200, %1\n\t" \
@@ -57,15 +57,9 @@
"jmp 4b\n" \
"5:\n\t"
-#define __raw_spin_lock_string_up \
- "\n\tdecb %0"
-
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
- alternative_smp(
- __raw_spin_lock_string,
- __raw_spin_lock_string_up,
- "+m" (lock->slock) : : "memory");
+ asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory");
}
/*
@@ -76,10 +70,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
#ifndef CONFIG_PROVE_LOCKING
static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
{
- alternative_smp(
- __raw_spin_lock_string_flags,
- __raw_spin_lock_string_up,
- "+m" (lock->slock) : "r" (flags) : "memory");
+ asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory");
}
#endif
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index fc1c8ddae14..d983b74e4d9 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -324,8 +324,6 @@
#define __NR_vmsplice 316
#define __NR_move_pages 317
-#ifdef __KERNEL__
-
#define NR_syscalls 318
/*
@@ -425,6 +423,8 @@ __asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \
__syscall_return(type,__res); \
}
+#ifdef __KERNEL__
+
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_OLD_STAT
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
index 69f0f1df672..4c1a0b96856 100644
--- a/include/asm-i386/unwind.h
+++ b/include/asm-i386/unwind.h
@@ -87,6 +87,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
#else
#define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
static inline int arch_unw_user_mode(const void *info)
{
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index bd4452bda35..ba826b3f75b 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -706,12 +706,9 @@ static inline int
sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
{
struct ia64_sal_retval ret_stuff;
- unsigned long irq_flags;
- local_irq_save(irq_flags);
ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
(u64)nasid_array, perms, 0, 0, 0);
- local_irq_restore(irq_flags);
return ret_stuff.status;
}
#define SN_MEMPROT_ACCESS_CLASS_0 0x14a080
@@ -1143,12 +1140,9 @@ static inline int
sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
{
struct ia64_sal_retval ret_stuff;
- unsigned long irq_flags;
- local_irq_save(irq_flags);
ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
(u64)ecc, 0, 0, 0, 0);
- local_irq_restore(irq_flags);
return ret_stuff.status;
}
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 9bd2f9bf329..6f807e0193b 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -60,23 +60,37 @@
* the bte_copy() once in the hope that the failure was due to a temporary
* aberration (i.e., the link going down temporarily).
*
- * See bte_copy for definition of the input parameters.
+ * src - physical address of the source of the transfer.
+ * vdst - virtual address of the destination of the transfer.
+ * len - number of bytes to transfer from source to destination.
+ * mode - see bte_copy() for definition.
+ * notification - see bte_copy() for definition.
*
* Note: xp_bte_copy() should never be called while holding a spinlock.
*/
static inline bte_result_t
-xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
+xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
{
bte_result_t ret;
+ u64 pdst = ia64_tpa(vdst);
- ret = bte_copy(src, dest, len, mode, notification);
+ /*
+ * Ensure that the physically mapped memory is contiguous.
+ *
+ * We do this by ensuring that the memory is from region 7 only.
+ * If the need should arise to use memory from one of the other
+ * regions, then modify the BUG_ON() statement to ensure that the
+ * memory from that region is always physically contiguous.
+ */
+ BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
+ ret = bte_copy(src, pdst, len, mode, notification);
if (ret != BTE_SUCCESS) {
if (!in_interrupt()) {
cond_resched();
}
- ret = bte_copy(src, dest, len, mode, notification);
+ ret = bte_copy(src, pdst, len, mode, notification);
}
return ret;
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index b72af597878..35e1386f37a 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -683,7 +683,9 @@ extern struct xpc_vars *xpc_vars;
extern struct xpc_rsvd_page *xpc_rsvd_page;
extern struct xpc_vars_part *xpc_vars_part;
extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
-extern char xpc_remote_copy_buffer[];
+extern char *xpc_remote_copy_buffer;
+extern void *xpc_remote_copy_buffer_base;
+extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
extern void xpc_allow_IPI_ops(void);
extern void xpc_restrict_IPI_ops(void);
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index a9496f34b04..36c4c34bf56 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -72,6 +72,9 @@ extern unsigned long pci_io_base;
* Neither do the standard versions now, these are just here
* for older code.
*/
+#define insb(port, buf, ns) _insb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u8 __iomem *)((port)+pci_io_base), (buf), (nl))
#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
#else
@@ -137,12 +140,12 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
+#endif
+
#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
-#endif
-
#define readb_relaxed(addr) readb(addr)
#define readw_relaxed(addr) readw(addr)
#define readl_relaxed(addr) readl(addr)
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
index 0fe396a2b66..53079ec3a51 100644
--- a/include/asm-powerpc/ipic.h
+++ b/include/asm-powerpc/ipic.h
@@ -69,9 +69,6 @@ enum ipic_mcp_irq {
IPIC_MCP_MU = 7,
};
-extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
- unsigned int irq_offset,
- unsigned char *senses, unsigned int senses_count);
extern int ipic_set_priority(unsigned int irq, unsigned int priority);
extern void ipic_set_highest_priority(unsigned int irq);
extern void ipic_set_default_priority(void);
@@ -79,7 +76,16 @@ extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq);
extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
extern u32 ipic_get_mcp_status(void);
extern void ipic_clear_mcp_status(u32 mask);
+
+#ifdef CONFIG_PPC_MERGE
+extern void ipic_init(struct device_node *node, unsigned int flags);
+extern unsigned int ipic_get_irq(struct pt_regs *regs);
+#else
+extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses, unsigned int senses_count);
extern int ipic_get_irq(struct pt_regs *regs);
+#endif
#endif /* __ASM_IPIC_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index f260382739f..b85df45b1a8 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -23,8 +23,6 @@
#define _ISA_MEM_BASE isa_mem_base
#ifdef CONFIG_PCI
#define PCI_DRAM_OFFSET pci_dram_offset
-#else
-#define PCI_DRAM_OFFSET 0
#endif
#define CPU0_BOOT_RELEASE 0x01000000
@@ -33,7 +31,6 @@
#define MCM_PORT_CONFIG_OFFSET 0x1010
/* Offset from CCSRBAR */
-#define MPC86xx_OPENPIC_OFFSET (0x40000)
#define MPC86xx_MCM_OFFSET (0x00000)
#define MPC86xx_MCM_SIZE (0x02000)
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index eb241c99c45..a9f9604b9ef 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -41,6 +41,7 @@
#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
+#define MPIC_GREG_IPI_STRIDE 0x10
#define MPIC_GREG_SPURIOUS 0x000e0
#define MPIC_GREG_TIMER_FREQ 0x000f0
@@ -68,6 +69,7 @@
#define MPIC_CPU_IPI_DISPATCH_1 0x00050
#define MPIC_CPU_IPI_DISPATCH_2 0x00060
#define MPIC_CPU_IPI_DISPATCH_3 0x00070
+#define MPIC_CPU_IPI_DISPATCH_STRIDE 0x00010
#define MPIC_CPU_CURRENT_TASK_PRI 0x00080
#define MPIC_CPU_TASKPRI_MASK 0x0000000f
#define MPIC_CPU_WHOAMI 0x00090
@@ -114,6 +116,103 @@
#define MPIC_VEC_TIMER_1 248
#define MPIC_VEC_TIMER_0 247
+/*
+ * Tsi108 implementation of MPIC has many differences from the original one
+ */
+
+/*
+ * Global registers
+ */
+
+#define TSI108_GREG_BASE 0x00000
+#define TSI108_GREG_FEATURE_0 0x00000
+#define TSI108_GREG_GLOBAL_CONF_0 0x00004
+#define TSI108_GREG_VENDOR_ID 0x0000c
+#define TSI108_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */
+#define TSI108_GREG_IPI_STRIDE 0x0c
+#define TSI108_GREG_SPURIOUS 0x00010
+#define TSI108_GREG_TIMER_FREQ 0x00014
+
+/*
+ * Timer registers
+ */
+#define TSI108_TIMER_BASE 0x0030
+#define TSI108_TIMER_STRIDE 0x10
+#define TSI108_TIMER_CURRENT_CNT 0x00000
+#define TSI108_TIMER_BASE_CNT 0x00004
+#define TSI108_TIMER_VECTOR_PRI 0x00008
+#define TSI108_TIMER_DESTINATION 0x0000c
+
+/*
+ * Per-Processor registers
+ */
+#define TSI108_CPU_BASE 0x00300
+#define TSI108_CPU_STRIDE 0x00040
+#define TSI108_CPU_IPI_DISPATCH_0 0x00200
+#define TSI108_CPU_IPI_DISPATCH_STRIDE 0x00000
+#define TSI108_CPU_CURRENT_TASK_PRI 0x00000
+#define TSI108_CPU_WHOAMI 0xffffffff
+#define TSI108_CPU_INTACK 0x00004
+#define TSI108_CPU_EOI 0x00008
+
+/*
+ * Per-source registers
+ */
+#define TSI108_IRQ_BASE 0x00100
+#define TSI108_IRQ_STRIDE 0x00008
+#define TSI108_IRQ_VECTOR_PRI 0x00000
+#define TSI108_VECPRI_VECTOR_MASK 0x000000ff
+#define TSI108_VECPRI_POLARITY_POSITIVE 0x01000000
+#define TSI108_VECPRI_POLARITY_NEGATIVE 0x00000000
+#define TSI108_VECPRI_SENSE_LEVEL 0x02000000
+#define TSI108_VECPRI_SENSE_EDGE 0x00000000
+#define TSI108_VECPRI_POLARITY_MASK 0x01000000
+#define TSI108_VECPRI_SENSE_MASK 0x02000000
+#define TSI108_IRQ_DESTINATION 0x00004
+
+/* weird mpic register indices and mask bits in the HW info array */
+enum {
+ MPIC_IDX_GREG_BASE = 0,
+ MPIC_IDX_GREG_FEATURE_0,
+ MPIC_IDX_GREG_GLOBAL_CONF_0,
+ MPIC_IDX_GREG_VENDOR_ID,
+ MPIC_IDX_GREG_IPI_VECTOR_PRI_0,
+ MPIC_IDX_GREG_IPI_STRIDE,
+ MPIC_IDX_GREG_SPURIOUS,
+ MPIC_IDX_GREG_TIMER_FREQ,
+
+ MPIC_IDX_TIMER_BASE,
+ MPIC_IDX_TIMER_STRIDE,
+ MPIC_IDX_TIMER_CURRENT_CNT,
+ MPIC_IDX_TIMER_BASE_CNT,
+ MPIC_IDX_TIMER_VECTOR_PRI,
+ MPIC_IDX_TIMER_DESTINATION,
+
+ MPIC_IDX_CPU_BASE,
+ MPIC_IDX_CPU_STRIDE,
+ MPIC_IDX_CPU_IPI_DISPATCH_0,
+ MPIC_IDX_CPU_IPI_DISPATCH_STRIDE,
+ MPIC_IDX_CPU_CURRENT_TASK_PRI,
+ MPIC_IDX_CPU_WHOAMI,
+ MPIC_IDX_CPU_INTACK,
+ MPIC_IDX_CPU_EOI,
+
+ MPIC_IDX_IRQ_BASE,
+ MPIC_IDX_IRQ_STRIDE,
+ MPIC_IDX_IRQ_VECTOR_PRI,
+
+ MPIC_IDX_VECPRI_VECTOR_MASK,
+ MPIC_IDX_VECPRI_POLARITY_POSITIVE,
+ MPIC_IDX_VECPRI_POLARITY_NEGATIVE,
+ MPIC_IDX_VECPRI_SENSE_LEVEL,
+ MPIC_IDX_VECPRI_SENSE_EDGE,
+ MPIC_IDX_VECPRI_POLARITY_MASK,
+ MPIC_IDX_VECPRI_SENSE_MASK,
+ MPIC_IDX_IRQ_DESTINATION,
+ MPIC_IDX_END
+};
+
+
#ifdef CONFIG_MPIC_BROKEN_U3
/* Fixup table entry */
struct mpic_irq_fixup
@@ -171,15 +270,29 @@ struct mpic
volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
volatile u32 __iomem *isus[MPIC_MAX_ISU];
+#ifdef CONFIG_MPIC_WEIRD
+ /* Pointer to HW info array */
+ u32 *hw_set;
+#endif
+
/* link */
struct mpic *next;
};
+/*
+ * MPIC flags (passed to mpic_alloc)
+ *
+ * The top 4 bits contain an MPIC bhw id that is used to index the
+ * register offsets and some masks when CONFIG_MPIC_WEIRD is set.
+ * Note setting any ID (leaving those bits to 0) means standard MPIC
+ */
+
/* This is the primary controller, only that one has IPIs and
* has afinity control. A non-primary MPIC always uses CPU0
* registers only
*/
#define MPIC_PRIMARY 0x00000001
+
/* Set this for a big-endian MPIC */
#define MPIC_BIG_ENDIAN 0x00000002
/* Broken U3 MPIC */
@@ -188,6 +301,18 @@ struct mpic
#define MPIC_BROKEN_IPI 0x00000008
/* MPIC wants a reset */
#define MPIC_WANTS_RESET 0x00000010
+/* Spurious vector requires EOI */
+#define MPIC_SPV_EOI 0x00000020
+/* No passthrough disable */
+#define MPIC_NO_PTHROU_DIS 0x00000040
+
+/* MPIC HW modification ID */
+#define MPIC_REGSET_MASK 0xf0000000
+#define MPIC_REGSET(val) (((val) & 0xf ) << 28)
+#define MPIC_GET_REGSET(flags) (((flags) >> 28) & 0xf)
+
+#define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */
+#define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */
/* Allocate the controller structure and setup the linux irq descs
* for the range if interrupts passed in. No HW initialization is
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index b095a285c84..d0fa1b9aed3 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -276,6 +276,7 @@ extern void of_irq_map_init(unsigned int flags);
* of_irq_map_raw - Low level interrupt tree parsing
* @parent: the device interrupt parent
* @intspec: interrupt specifier ("interrupts" property of the device)
+ * @ointsize: size of the passed in interrupt specifier
* @addr: address specifier (start of "reg" property of the device)
* @out_irq: structure of_irq filled by this function
*
@@ -288,7 +289,8 @@ extern void of_irq_map_init(unsigned int flags);
*
*/
-extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
+extern int of_irq_map_raw(struct device_node *parent, u32 *intspec,
+ u32 ointsize, u32 *addr,
struct of_irq *out_irq);
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index dcde4410348..5785ac4737b 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -30,10 +30,6 @@ extern unsigned long tb_ticks_per_usec;
extern unsigned long tb_ticks_per_sec;
extern u64 tb_to_xs;
extern unsigned tb_to_us;
-extern unsigned long tb_last_stamp;
-extern u64 tb_last_jiffy;
-
-DECLARE_PER_CPU(unsigned long, last_jiffy);
struct rtc_time;
extern void to_tm(int tim, struct rtc_time * tm);
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index aa67bfd1b3c..a584826cc57 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -4,6 +4,7 @@
#ifdef __KERNEL__
#include <linux/types.h>
+#include <asm/cpufeature.h>
struct alt_instr {
u8 *instr; /* original instruction */
@@ -102,9 +103,6 @@ static inline void alternatives_smp_switch(int smp) {}
/*
* Alternative inline assembly for SMP.
*
- * alternative_smp() takes two versions (SMP first, UP second) and is
- * for more complex stuff such as spinlocks.
- *
* The LOCK_PREFIX macro defined here replaces the LOCK and
* LOCK_PREFIX macros used everywhere in the source tree.
*
@@ -124,21 +122,6 @@ static inline void alternatives_smp_switch(int smp) {}
*/
#ifdef CONFIG_SMP
-#define alternative_smp(smpinstr, upinstr, args...) \
- asm volatile ("661:\n\t" smpinstr "\n662:\n" \
- ".section .smp_altinstructions,\"a\"\n" \
- " .align 8\n" \
- " .quad 661b\n" /* label */ \
- " .quad 663f\n" /* new instruction */ \
- " .byte 0x66\n" /* X86_FEATURE_UP */ \
- " .byte 662b-661b\n" /* sourcelen */ \
- " .byte 664f-663f\n" /* replacementlen */ \
- ".previous\n" \
- ".section .smp_altinstr_replacement,\"awx\"\n" \
- "663:\n\t" upinstr "\n" /* replacement */ \
- "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
- ".previous" : args)
-
#define LOCK_PREFIX \
".section .smp_locks,\"a\"\n" \
" .align 8\n" \
@@ -147,8 +130,6 @@ static inline void alternatives_smp_switch(int smp) {}
"661:\n\tlock; "
#else /* ! CONFIG_SMP */
-#define alternative_smp(smpinstr, upinstr, args...) \
- asm volatile (upinstr : args)
#define LOCK_PREFIX ""
#endif
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 3b3c1217fe6..de9c3147ee4 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -232,8 +232,14 @@ struct tss_struct {
unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
} __attribute__((packed)) ____cacheline_aligned;
+
extern struct cpuinfo_x86 boot_cpu_data;
DECLARE_PER_CPU(struct tss_struct,init_tss);
+/* Save the original ist values for checking stack pointers during debugging */
+struct orig_ist {
+ unsigned long ist[7];
+};
+DECLARE_PER_CPU(struct orig_ist, orig_ist);
#ifdef CONFIG_X86_VSMP
#define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT)
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 8d3421996f9..248a79f0eaf 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -21,7 +21,7 @@
#define __raw_spin_lock_string \
"\n1:\t" \
- "lock ; decl %0\n\t" \
+ LOCK_PREFIX " ; decl %0\n\t" \
"js 2f\n" \
LOCK_SECTION_START("") \
"2:\t" \
@@ -40,10 +40,7 @@
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
- alternative_smp(
- __raw_spin_lock_string,
- __raw_spin_lock_string_up,
- "=m" (lock->slock) : : "memory");
+ asm volatile(__raw_spin_lock_string : "=m" (lock->slock) : : "memory");
}
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
@@ -125,12 +122,12 @@ static inline int __raw_write_trylock(raw_rwlock_t *lock)
static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
- asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+ asm volatile(LOCK_PREFIX " ; incl %0" :"=m" (rw->lock) : : "memory");
}
static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
- asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0"
+ asm volatile(LOCK_PREFIX " ; addl $" RW_LOCK_BIAS_STR ",%0"
: "=m" (rw->lock) : : "memory");
}
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 94387c915e5..2d89d309a2a 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -620,8 +620,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)
#define __NR_move_pages 279
__SYSCALL(__NR_move_pages, sys_move_pages)
-#ifdef __KERNEL__
-
#define __NR_syscall_max __NR_move_pages
#ifndef __NO_STUBS
@@ -746,6 +744,8 @@ __syscall_return(type,__res); \
#else /* __KERNEL_SYSCALLS__ */
+#ifdef __KERNEL__
+
#include <linux/syscalls.h>
#include <asm/ptrace.h>
@@ -838,9 +838,9 @@ asmlinkage long sys_rt_sigaction(int sig,
struct sigaction __user *oact,
size_t sigsetsize);
-#endif /* __ASSEMBLY__ */
+#endif
-#endif /* __NO_STUBS */
+#endif
/*
* "Conditional" syscalls
@@ -850,5 +850,6 @@ asmlinkage long sys_rt_sigaction(int sig,
*/
#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-#endif /* __KERNEL__ */
+#endif
+
#endif
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
index f3e7124effe..1f6e9bfb569 100644
--- a/include/asm-x86_64/unwind.h
+++ b/include/asm-x86_64/unwind.h
@@ -95,6 +95,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
#else
#define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
static inline int arch_unw_user_mode(const void *info)
{
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 11487b6e712..561e2a77805 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -59,10 +59,14 @@ static inline void delayacct_tsk_init(struct task_struct *tsk)
__delayacct_tsk_init(tsk);
}
-static inline void delayacct_tsk_exit(struct task_struct *tsk)
+/* Free tsk->delays. Called from bad fork and __put_task_struct
+ * where there's no risk of tsk->delays being accessed elsewhere
+ */
+static inline void delayacct_tsk_free(struct task_struct *tsk)
{
if (tsk->delays)
- __delayacct_tsk_exit(tsk);
+ kmem_cache_free(delayacct_cache, tsk->delays);
+ tsk->delays = NULL;
}
static inline void delayacct_blkio_start(void)
@@ -101,7 +105,7 @@ static inline void delayacct_init(void)
{}
static inline void delayacct_tsk_init(struct task_struct *tsk)
{}
-static inline void delayacct_tsk_exit(struct task_struct *tsk)
+static inline void delayacct_tsk_free(struct task_struct *tsk)
{}
static inline void delayacct_blkio_start(void)
{}
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 656b588a9f9..f45163c528e 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -77,6 +77,7 @@ struct per_cpu_pages {
struct per_cpu_pageset {
struct per_cpu_pages pcp[2]; /* 0: hot. 1: cold */
#ifdef CONFIG_SMP
+ s8 stat_threshold;
s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];
#endif
} ____cacheline_aligned_in_smp;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4eae06b08cf..c91164ea3de 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1292,6 +1292,7 @@
#define PCI_DEVICE_ID_VIA_8367_0 0x3099
#define PCI_DEVICE_ID_VIA_8653_0 0x3101
#define PCI_DEVICE_ID_VIA_8622 0x3102
+#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104
#define PCI_DEVICE_ID_VIA_8233C_0 0x3109
#define PCI_DEVICE_ID_VIA_8361 0x3112
#define PCI_DEVICE_ID_VIA_XM266 0x3116
@@ -1726,6 +1727,9 @@
#define PCI_VENDOR_ID_DOMEX 0x134a
#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001
+#define PCI_VENDOR_ID_INTASHIELD 0x135a
+#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80
+
#define PCI_VENDOR_ID_QUATECH 0x135C
#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010
#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6674fc1e51b..34ed0d99b1b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -994,7 +994,6 @@ struct task_struct {
*/
struct pipe_inode_info *splice_pipe;
#ifdef CONFIG_TASK_DELAY_ACCT
- spinlock_t delays_lock;
struct task_delay_info *delays;
#endif
};
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 57ca3730205..36752f124c6 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -41,24 +41,11 @@ void delayacct_init(void)
void __delayacct_tsk_init(struct task_struct *tsk)
{
- spin_lock_init(&tsk->delays_lock);
- /* No need to acquire tsk->delays_lock for allocation here unless
- __delayacct_tsk_init called after tsk is attached to tasklist
- */
tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL);
if (tsk->delays)
spin_lock_init(&tsk->delays->lock);
}
-void __delayacct_tsk_exit(struct task_struct *tsk)
-{
- struct task_delay_info *delays = tsk->delays;
- spin_lock(&tsk->delays_lock);
- tsk->delays = NULL;
- spin_unlock(&tsk->delays_lock);
- kmem_cache_free(delayacct_cache, delays);
-}
-
/*
* Start accounting for a delay statistic using
* its starting timestamp (@start)
@@ -118,8 +105,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
struct timespec ts;
unsigned long t1,t2,t3;
- spin_lock(&tsk->delays_lock);
-
/* Though tsk->delays accessed later, early exit avoids
* unnecessary returning of other data
*/
@@ -161,7 +146,6 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
spin_unlock(&tsk->delays->lock);
done:
- spin_unlock(&tsk->delays_lock);
return 0;
}
diff --git a/kernel/exit.c b/kernel/exit.c
index dba194a8d41..d891883420f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -908,7 +908,6 @@ fastcall NORET_TYPE void do_exit(long code)
audit_free(tsk);
taskstats_exit_send(tsk, tidstats, group_dead, mycpu);
taskstats_exit_free(tidstats);
- delayacct_tsk_exit(tsk);
exit_mm(tsk);
@@ -1054,7 +1053,7 @@ static int eligible_child(pid_t pid, int options, struct task_struct *p)
* Do not consider thread group leaders that are
* in a non-empty thread group:
*/
- if (current->tgid != p->tgid && delay_group_leader(p))
+ if (delay_group_leader(p))
return 2;
if (security_task_wait(p))
diff --git a/kernel/fork.c b/kernel/fork.c
index aa36c43783c..f9b014e3e70 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -117,6 +117,7 @@ void __put_task_struct(struct task_struct *tsk)
security_task_free(tsk);
free_uid(tsk->user);
put_group_info(tsk->group_info);
+ delayacct_tsk_free(tsk);
if (!profile_handoff_task(tsk))
free_task(tsk);
@@ -1011,7 +1012,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
retval = -EFAULT;
if (clone_flags & CLONE_PARENT_SETTID)
if (put_user(p->pid, parent_tidptr))
- goto bad_fork_cleanup;
+ goto bad_fork_cleanup_delays_binfmt;
INIT_LIST_HEAD(&p->children);
INIT_LIST_HEAD(&p->sibling);
@@ -1277,7 +1278,8 @@ bad_fork_cleanup_policy:
bad_fork_cleanup_cpuset:
#endif
cpuset_exit(p);
-bad_fork_cleanup:
+bad_fork_cleanup_delays_binfmt:
+ delayacct_tsk_free(p);
if (p->binfmt)
module_put(p->binfmt->module);
bad_fork_cleanup_put_domain:
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index fc4e906aedb..48a53f68af9 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -20,6 +20,11 @@
/**
* handle_bad_irq - handle spurious and unhandled irqs
+ * @irq: the interrupt number
+ * @desc: description of the interrupt
+ * @regs: pointer to a register structure
+ *
+ * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
*/
void fastcall
handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e07e27e846a..a9963ceddd6 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1176,7 +1176,15 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
if (vma) {
unsigned long off;
- off = vma->vm_pgoff;
+ /*
+ * for small pages, there is no difference between
+ * shift and PAGE_SHIFT, so the bit-shift is safe.
+ * for huge pages, since vm_pgoff is in units of small
+ * pages, we need to shift off the always 0 bits to get
+ * a useful offset.
+ */
+ BUG_ON(shift < PAGE_SHIFT);
+ off = vma->vm_pgoff >> (shift - PAGE_SHIFT);
off += (addr - vma->vm_start) >> shift;
return offset_il_node(pol, vma, off);
} else
diff --git a/mm/mempool.c b/mm/mempool.c
index fe6e05289cc..ccd8cb8cd41 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -238,8 +238,13 @@ repeat_alloc:
init_wait(&wait);
prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
smp_mb();
- if (!pool->curr_nr)
- io_schedule();
+ if (!pool->curr_nr) {
+ /*
+ * FIXME: this should be io_schedule(). The timeout is there
+ * as a workaround for some DM problems in 2.6.18.
+ */
+ io_schedule_timeout(5*HZ);
+ }
finish_wait(&pool->wait, &wait);
goto repeat_alloc;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index dfdf2413390..c1b5f4106b3 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/cpu.h>
void __get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free, struct pglist_data *pgdat)
@@ -114,17 +115,72 @@ EXPORT_SYMBOL(vm_stat);
#ifdef CONFIG_SMP
-#define STAT_THRESHOLD 32
+static int calculate_threshold(struct zone *zone)
+{
+ int threshold;
+ int mem; /* memory in 128 MB units */
+
+ /*
+ * The threshold scales with the number of processors and the amount
+ * of memory per zone. More memory means that we can defer updates for
+ * longer, more processors could lead to more contention.
+ * fls() is used to have a cheap way of logarithmic scaling.
+ *
+ * Some sample thresholds:
+ *
+ * Threshold Processors (fls) Zonesize fls(mem+1)
+ * ------------------------------------------------------------------
+ * 8 1 1 0.9-1 GB 4
+ * 16 2 2 0.9-1 GB 4
+ * 20 2 2 1-2 GB 5
+ * 24 2 2 2-4 GB 6
+ * 28 2 2 4-8 GB 7
+ * 32 2 2 8-16 GB 8
+ * 4 2 2 <128M 1
+ * 30 4 3 2-4 GB 5
+ * 48 4 3 8-16 GB 8
+ * 32 8 4 1-2 GB 4
+ * 32 8 4 0.9-1GB 4
+ * 10 16 5 <128M 1
+ * 40 16 5 900M 4
+ * 70 64 7 2-4 GB 5
+ * 84 64 7 4-8 GB 6
+ * 108 512 9 4-8 GB 6
+ * 125 1024 10 8-16 GB 8
+ * 125 1024 10 16-32 GB 9
+ */
+
+ mem = zone->present_pages >> (27 - PAGE_SHIFT);
+
+ threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem));
+
+ /*
+ * Maximum threshold is 125
+ */
+ threshold = min(125, threshold);
+
+ return threshold;
+}
/*
- * Determine pointer to currently valid differential byte given a zone and
- * the item number.
- *
- * Preemption must be off
+ * Refresh the thresholds for each zone.
*/
-static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item)
+static void refresh_zone_stat_thresholds(void)
{
- return &zone_pcp(zone, smp_processor_id())->vm_stat_diff[item];
+ struct zone *zone;
+ int cpu;
+ int threshold;
+
+ for_each_zone(zone) {
+
+ if (!zone->present_pages)
+ continue;
+
+ threshold = calculate_threshold(zone);
+
+ for_each_online_cpu(cpu)
+ zone_pcp(zone, cpu)->stat_threshold = threshold;
+ }
}
/*
@@ -133,17 +189,16 @@ static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item)
void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
int delta)
{
- s8 *p;
+ struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+ s8 *p = pcp->vm_stat_diff + item;
long x;
- p = diff_pointer(zone, item);
x = delta + *p;
- if (unlikely(x > STAT_THRESHOLD || x < -STAT_THRESHOLD)) {
+ if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) {
zone_page_state_add(x, zone, item);
x = 0;
}
-
*p = x;
}
EXPORT_SYMBOL(__mod_zone_page_state);
@@ -172,10 +227,12 @@ EXPORT_SYMBOL(mod_zone_page_state);
* No overflow check is necessary and therefore the differential can be
* incremented or decremented in place which may allow the compilers to
* generate better code.
- *
* The increment or decrement is known and therefore one boundary check can
* be omitted.
*
+ * NOTE: These functions are very performance sensitive. Change only
+ * with care.
+ *
* Some processors have inc/dec instructions that are atomic vs an interrupt.
* However, the code must first determine the differential location in a zone
* based on the processor number and then inc/dec the counter. There is no
@@ -185,13 +242,16 @@ EXPORT_SYMBOL(mod_zone_page_state);
*/
static void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
{
- s8 *p = diff_pointer(zone, item);
+ struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+ s8 *p = pcp->vm_stat_diff + item;
(*p)++;
- if (unlikely(*p > STAT_THRESHOLD)) {
- zone_page_state_add(*p, zone, item);
- *p = 0;
+ if (unlikely(*p > pcp->stat_threshold)) {
+ int overstep = pcp->stat_threshold / 2;
+
+ zone_page_state_add(*p + overstep, zone, item);
+ *p = -overstep;
}
}
@@ -204,13 +264,16 @@ EXPORT_SYMBOL(__inc_zone_page_state);
void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
{
struct zone *zone = page_zone(page);
- s8 *p = diff_pointer(zone, item);
+ struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+ s8 *p = pcp->vm_stat_diff + item;
(*p)--;
- if (unlikely(*p < -STAT_THRESHOLD)) {
- zone_page_state_add(*p, zone, item);
- *p = 0;
+ if (unlikely(*p < - pcp->stat_threshold)) {
+ int overstep = pcp->stat_threshold / 2;
+
+ zone_page_state_add(*p - overstep, zone, item);
+ *p = overstep;
}
}
EXPORT_SYMBOL(__dec_zone_page_state);
@@ -239,19 +302,9 @@ EXPORT_SYMBOL(inc_zone_page_state);
void dec_zone_page_state(struct page *page, enum zone_stat_item item)
{
unsigned long flags;
- struct zone *zone;
- s8 *p;
- zone = page_zone(page);
local_irq_save(flags);
- p = diff_pointer(zone, item);
-
- (*p)--;
-
- if (unlikely(*p < -STAT_THRESHOLD)) {
- zone_page_state_add(*p, zone, item);
- *p = 0;
- }
+ __dec_zone_page_state(page, item);
local_irq_restore(flags);
}
EXPORT_SYMBOL(dec_zone_page_state);
@@ -525,6 +578,10 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
pageset->pcp[j].high,
pageset->pcp[j].batch);
}
+#ifdef CONFIG_SMP
+ seq_printf(m, "\n vm stats threshold: %d",
+ pageset->stat_threshold);
+#endif
}
seq_printf(m,
"\n all_unreclaimable: %u"
@@ -613,3 +670,35 @@ struct seq_operations vmstat_op = {
#endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_SMP
+/*
+ * Use the cpu notifier to insure that the thresholds are recalculated
+ * when necessary.
+ */
+static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
+{
+ switch (action) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_CANCELED:
+ case CPU_DEAD:
+ refresh_zone_stat_thresholds();
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata vmstat_notifier =
+ { &vmstat_cpuup_callback, NULL, 0 };
+
+int __init setup_vmstat(void)
+{
+ refresh_zone_stat_thresholds();
+ register_cpu_notifier(&vmstat_notifier);
+ return 0;
+}
+module_init(setup_vmstat)
+#endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 4c20f554689..a2ede167e04 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -440,6 +440,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
iph = skb->nh.iph;
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
+ IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(dst_mtu(&rt->u.dst)));
kfree_skb(skb);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 5765f9d0317..7ff2e4273a7 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -189,7 +189,7 @@ void tcp_slow_start(struct tcp_sock *tp)
return;
/* We MAY increase by 2 if discovered delayed ack */
- if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) {
+ if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) {
if (tp->snd_cwnd < tp->snd_cwnd_clamp)
tp->snd_cwnd++;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 104af5d5bcb..111ff39a08c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2505,8 +2505,13 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
if (before(ack, prior_snd_una))
goto old_ack;
- if (sysctl_tcp_abc && icsk->icsk_ca_state < TCP_CA_CWR)
- tp->bytes_acked += ack - prior_snd_una;
+ if (sysctl_tcp_abc) {
+ if (icsk->icsk_ca_state < TCP_CA_CWR)
+ tp->bytes_acked += ack - prior_snd_una;
+ else if (icsk->icsk_ca_state == TCP_CA_Loss)
+ /* we assume just one segment left network */
+ tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache);
+ }
if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
/* Window is constant, pure forward advance.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0c5042e7380..c7852b38e03 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -578,6 +578,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ifa->flags = flags | IFA_F_TENTATIVE;
ifa->cstamp = ifa->tstamp = jiffies;
+ ifa->rt = rt;
+
ifa->idev = idev;
in6_dev_hold(idev);
/* For caller */
@@ -603,8 +605,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
}
#endif
- ifa->rt = rt;
-
in6_ifa_hold(ifa);
write_unlock(&idev->lock);
out2:
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 9d0ee7f0eeb..86dac106873 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -635,14 +635,17 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
struct ipv6_txoptions *opt2;
int err;
- if (newtype != IPV6_HOPOPTS && opt->hopopt)
- tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
- if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
- tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
- if (newtype != IPV6_RTHDR && opt->srcrt)
- tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
- if (newtype != IPV6_DSTOPTS && opt->dst1opt)
- tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
+ if (opt) {
+ if (newtype != IPV6_HOPOPTS && opt->hopopt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
+ if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
+ if (newtype != IPV6_RTHDR && opt->srcrt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
+ if (newtype != IPV6_DSTOPTS && opt->dst1opt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
+ }
+
if (newopt && newoptlen)
tot_len += CMSG_ALIGN(newoptlen);
@@ -659,25 +662,25 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
opt2->tot_len = tot_len;
p = (char *)(opt2 + 1);
- err = ipv6_renew_option(opt->hopopt, newopt, newoptlen,
+ err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
newtype != IPV6_HOPOPTS,
&opt2->hopopt, &p);
if (err)
goto out;
- err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen,
+ err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
newtype != IPV6_RTHDRDSTOPTS,
&opt2->dst0opt, &p);
if (err)
goto out;
- err = ipv6_renew_option(opt->srcrt, newopt, newoptlen,
+ err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
newtype != IPV6_RTHDR,
- (struct ipv6_opt_hdr **)opt2->srcrt, &p);
+ (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
if (err)
goto out;
- err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen,
+ err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
newtype != IPV6_DSTOPTS,
&opt2->dst1opt, &p);
if (err)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4b163711f3a..d9baca062d2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1532,6 +1532,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
static int ip6_pkt_discard(struct sk_buff *skb)
{
+ int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
+ if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
+ IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
+
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
kfree_skb(skb);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b85c1f9f128..8b85036ba8e 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1273,8 +1273,7 @@ netlink_kernel_create(int unit, unsigned int groups,
struct netlink_sock *nlk;
unsigned long *listeners = NULL;
- if (!nl_table)
- return NULL;
+ BUG_ON(!nl_table);
if (unit<0 || unit>=MAX_LINKS)
return NULL;
@@ -1745,11 +1744,8 @@ static int __init netlink_proto_init(void)
netlink_skb_parms_too_large();
nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
- if (!nl_table) {
-enomem:
- printk(KERN_CRIT "netlink_init: Cannot allocate nl_table\n");
- return -ENOMEM;
- }
+ if (!nl_table)
+ goto panic;
if (num_physpages >= (128 * 1024))
max = num_physpages >> (21 - PAGE_SHIFT);
@@ -1769,7 +1765,7 @@ enomem:
nl_pid_hash_free(nl_table[i].hash.table,
1 * sizeof(*hash->table));
kfree(nl_table);
- goto enomem;
+ goto panic;
}
memset(hash->table, 0, 1 * sizeof(*hash->table));
hash->max_shift = order;
@@ -1786,6 +1782,8 @@ enomem:
rtnetlink_init();
out:
return err;
+panic:
+ panic("netlink_init: Cannot allocate nl_table\n");
}
core_initcall(netlink_proto_init);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index fde3f55bfd4..dab15949958 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1289,9 +1289,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
}
}
- if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)
- sctp_primitive_ABORT(asoc, NULL);
- else
+ if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
+ struct sctp_chunk *chunk;
+
+ chunk = sctp_make_abort_user(asoc, NULL, 0);
+ if (chunk)
+ sctp_primitive_ABORT(asoc, chunk);
+ } else
sctp_primitive_SHUTDOWN(asoc, NULL);
}
diff --git a/net/socket.c b/net/socket.c
index b4848ce0d6a..6d261bf206f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1178,7 +1178,8 @@ static int __sock_create(int family, int type, int protocol, struct socket **res
*/
if (!(sock = sock_alloc())) {
- printk(KERN_WARNING "socket: no more sockets\n");
+ if (net_ratelimit())
+ printk(KERN_WARNING "socket: no more sockets\n");
err = -ENFILE; /* Not exactly a match, but its the
closest posix thing */
goto out;
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 1b7c3dfc2b4..97e38b66558 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,6 +5,20 @@
#
# Prompt user for primary drivers.
+config OSS_OBSOLETE_DRIVER
+ bool "Obsolete OSS drivers"
+ depends on SOUND_PRIME
+ help
+ This option enables support for obsolete OSS drivers that
+ are scheduled for removal in the near future since there
+ are ALSA drivers for the same hardware.
+
+ Please contact Adrian Bunk <bunk@stusta.de> if you had to
+ say Y here because your soundcard is not properly supported
+ by ALSA.
+
+ If unsure, say N.
+
config SOUND_BT878
tristate "BT878 audio dma"
depends on SOUND_PRIME && PCI
@@ -23,7 +37,7 @@ config SOUND_BT878
config SOUND_EMU10K1
tristate "Creative SBLive! (EMU10K1)"
- depends on SOUND_PRIME && PCI
+ depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
---help---
Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -49,7 +63,7 @@ config MIDI_EMU10K1
config SOUND_FUSION
tristate "Crystal SoundFusion (CS4280/461x)"
- depends on SOUND_PRIME && PCI
+ depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
help
This module drives the Crystal SoundFusion devices (CS4280/46xx
series) when wired as native sound drivers with AC97 codecs. If
@@ -440,7 +454,7 @@ config SOUND_DMAP
config SOUND_AD1816
tristate "AD1816(A) based cards (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SOUND_OSS
+ depends on EXPERIMENTAL && SOUND_OSS && OSS_OBSOLETE_DRIVER
help
Say M here if you have a sound card based on the Analog Devices
AD1816(A) chip.
@@ -450,21 +464,21 @@ config SOUND_AD1816
config SOUND_AD1889
tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SOUND_OSS && PCI
+ depends on EXPERIMENTAL && SOUND_OSS && PCI && OSS_OBSOLETE_DRIVER
help
Say M here if you have a sound card based on the Analog Devices
AD1889 chip.
config SOUND_ADLIB
tristate "Adlib Cards"
- depends on SOUND_OSS
+ depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
help
Includes ASB 64 4D. Information on programming AdLib cards is
available at <http://www.itsnet.com/home/ldragon/Specs/adlib.html>.
config SOUND_ACI_MIXER
tristate "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)"
- depends on SOUND_OSS
+ depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
---help---
ACI (Audio Command Interface) is a protocol used to communicate with
the microcontroller on some sound cards produced by miro and
@@ -586,7 +600,7 @@ config SOUND_MPU401
config SOUND_NM256
tristate "NM256AV/NM256ZX audio support"
- depends on SOUND_OSS
+ depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
help
Say M here to include audio support for the NeoMagic 256AV/256ZX
chipsets. These are the audio chipsets found in the Sony
@@ -706,7 +720,7 @@ config SOUND_YM3812
config SOUND_OPL3SA2
tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
- depends on SOUND_OSS
+ depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
help
Say Y or M if you have a card based on one of these Yamaha sound
chipsets or the "SAx", which is actually a SA3. Read
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 0abf2808d59..51e83d7a839 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -573,7 +573,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1)
};
static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
- AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0);
+ AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
@@ -615,7 +615,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),
AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
AC97_ENUM("Mono Output Select", std_enum[2]),
-AC97_ENUM("Mic Select Capture Switch", std_enum[3]),
+AC97_ENUM("Mic Select", std_enum[3]),
AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
};