aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/SubmittingPatches26
-rw-r--r--Documentation/atomic_ops.txt2
-rw-r--r--Documentation/driver-model/platform.txt40
-rw-r--r--Documentation/feature-removal-schedule.txt1
-rw-r--r--Documentation/filesystems/tmpfs.txt10
-rw-r--r--Documentation/firmware_class/README2
-rw-r--r--Documentation/firmware_class/firmware_sample_driver.c2
-rw-r--r--Documentation/firmware_class/firmware_sample_firmware_class.c4
-rw-r--r--Documentation/networking/00-INDEX2
-rw-r--r--Documentation/networking/cxacru.txt84
-rw-r--r--MAINTAINERS19
-rw-r--r--arch/arm/boot/compressed/head.S5
-rw-r--r--arch/arm/mach-at91/clock.c5
-rw-r--r--arch/arm/mach-at91/pm.c11
-rw-r--r--arch/arm/oprofile/op_model_mpcore.c2
-rw-r--r--arch/i386/math-emu/fpu_entry.c2
-rw-r--r--arch/i386/mm/fault.c5
-rw-r--r--arch/m68knommu/platform/5307/timers.c10
-rw-r--r--arch/mips/Kconfig6
-rw-r--r--arch/mips/emma2rh/markeins/setup.c24
-rw-r--r--arch/mips/kernel/linux32.c10
-rw-r--r--arch/mips/kernel/r4k_switch.S2
-rw-r--r--arch/mips/kernel/scall32-o32.S6
-rw-r--r--arch/mips/kernel/scall64-64.S4
-rw-r--r--arch/mips/kernel/scall64-n32.S6
-rw-r--r--arch/mips/kernel/scall64-o32.S6
-rw-r--r--arch/mips/kernel/smp.c2
-rw-r--r--arch/mips/kernel/smtc-asm.S3
-rw-r--r--arch/mips/kernel/smtc.c4
-rw-r--r--arch/mips/kernel/traps.c27
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c5
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c2
-rw-r--r--arch/mips/mips-boards/generic/display.c24
-rw-r--r--arch/mips/mips-boards/generic/time.c47
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c6
-rw-r--r--arch/mips/mips-boards/sead/sead_setup.c2
-rw-r--r--arch/mips/mm/dma-default.c5
-rw-r--r--arch/mips/qemu/q-irq.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c2
-rw-r--r--arch/mips/sni/pcimt.c18
-rw-r--r--arch/mips/sni/setup.c33
-rw-r--r--arch/ppc/syslib/qspan_pci.c4
-rw-r--r--arch/sh/boards/se/73180/setup.c4
-rw-r--r--arch/sh/boards/superh/microdev/irq.c1
-rw-r--r--arch/sh/cchips/voyagergx/irq.c13
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S2
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c2
-rw-r--r--arch/sh/mm/ioremap.c1
-rw-r--r--arch/sh64/kernel/pci_sh5.c8
-rw-r--r--arch/sparc64/kernel/of_device.c19
-rw-r--r--arch/sparc64/kernel/pci.c97
-rw-r--r--arch/sparc64/kernel/pci_sabre.c17
-rw-r--r--arch/sparc64/kernel/prom.c54
-rw-r--r--arch/sparc64/kernel/sbus.c54
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/um/Kconfig1
-rw-r--r--arch/um/drivers/line.c1
-rw-r--r--arch/um/drivers/stderr_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c1
-rw-r--r--arch/um/kernel/exitcode.c39
-rw-r--r--arch/x86_64/kernel/traps.c3
-rw-r--r--arch/x86_64/mm/fault.c6
-rw-r--r--arch/x86_64/mm/init.c2
-rw-r--r--arch/xtensa/kernel/asm-offsets.c1
-rw-r--r--arch/xtensa/kernel/entry.S36
-rw-r--r--arch/xtensa/kernel/head.S19
-rw-r--r--arch/xtensa/kernel/pci.c2
-rw-r--r--arch/xtensa/kernel/setup.c1
-rw-r--r--arch/xtensa/kernel/signal.c795
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S78
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c11
-rw-r--r--arch/xtensa/lib/strncpy_user.S33
-rw-r--r--arch/xtensa/lib/strnlen_user.S33
-rw-r--r--arch/xtensa/mm/init.c2
-rw-r--r--arch/xtensa/platform-iss/network.c2
-rw-r--r--drivers/ata/ahci.c24
-rw-r--r--drivers/ata/libata-core.c62
-rw-r--r--drivers/ata/libata-scsi.c67
-rw-r--r--drivers/ata/libata-sff.c37
-rw-r--r--drivers/ata/pata_isapnp.c1
-rw-r--r--drivers/ata/sata_promise.c9
-rw-r--r--drivers/base/class.c59
-rw-r--r--drivers/base/core.c10
-rw-r--r--drivers/base/dd.c13
-rw-r--r--drivers/base/firmware_class.c4
-rw-r--r--drivers/block/loop.c100
-rw-r--r--drivers/cdrom/mcdx.c2
-rw-r--r--drivers/char/agp/agp.h6
-rw-r--r--drivers/char/agp/intel-agp.c576
-rw-r--r--drivers/char/stallion.c81
-rw-r--r--drivers/ide/ide-disk.c12
-rw-r--r--drivers/ide/ide-probe.c12
-rw-r--r--drivers/ide/ide.c9
-rw-r--r--drivers/ide/pci/amd74xx.c12
-rw-r--r--drivers/ide/pci/generic.c37
-rw-r--r--drivers/ide/pci/hpt366.c8
-rw-r--r--drivers/ide/pci/it821x.c34
-rw-r--r--drivers/ide/pci/serverworks.c51
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c2
-rw-r--r--drivers/input/keyboard/pxa27x_keyboard.c6
-rw-r--r--drivers/isdn/hardware/eicon/divasfunc.c2
-rw-r--r--drivers/media/common/Kconfig1
-rw-r--r--drivers/media/dvb/b2c2/Makefile7
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c3
-rw-r--r--drivers/media/dvb/frontends/tda10086.c21
-rw-r--r--drivers/media/dvb/frontends/tda826x.c4
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h16
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c16
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c45
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c204
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.c31
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.h39
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.h2
-rw-r--r--drivers/media/video/saa7111.c49
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c82
-rw-r--r--drivers/media/video/usbvision/usbvision.h1
-rw-r--r--drivers/mmc/core/sd.c26
-rw-r--r--drivers/mmc/host/at91_mci.c5
-rw-r--r--drivers/mmc/host/au1xmmc.c3
-rw-r--r--drivers/net/bnx2.c61
-rw-r--r--drivers/net/bnx2.h1
-rw-r--r--drivers/serial/amba-pl010.c4
-rw-r--r--drivers/tc/zs.c2
-rw-r--r--drivers/usb/atm/cxacru.c52
-rw-r--r--drivers/usb/class/usblp.c5
-rw-r--r--drivers/usb/core/Kconfig22
-rw-r--r--drivers/usb/core/config.c42
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/inode.c8
-rw-r--r--drivers/usb/gadget/net2280.c6
-rw-r--r--drivers/usb/gadget/omap_udc.c6
-rw-r--r--drivers/usb/gadget/rndis.c35
-rw-r--r--drivers/usb/host/ohci-hub.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h21
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/cifs/cifs_debug.c252
-rw-r--r--fs/cifs/cifs_unicode.c12
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/connect.c16
-rw-r--r--fs/cifs/dir.c184
-rw-r--r--fs/cifs/fcntl.c46
-rw-r--r--fs/cifs/inode.c5
-rw-r--r--fs/cifs/ioctl.c29
-rw-r--r--fs/cifs/rfc1002pdu.h2
-rw-r--r--fs/ocfs2/aops.c20
-rw-r--r--fs/ocfs2/cluster/masklog.c3
-rw-r--r--fs/ramfs/file-nommu.c5
-rw-r--r--fs/splice.c70
-rw-r--r--include/asm-arm/arch-at91/at91_shdwc.h4
-rw-r--r--include/asm-arm/arch-at91/at91_wdt.h2
-rw-r--r--include/asm-arm/arch-pxa/gpio.h3
-rw-r--r--include/asm-frv/system.h1
-rw-r--r--include/asm-mips/asmmacro.h15
-rw-r--r--include/asm-mips/bitops.h51
-rw-r--r--include/asm-mips/mips-boards/prom.h1
-rw-r--r--include/asm-mips/stackframe.h52
-rw-r--r--include/asm-mips/unistd.h25
-rw-r--r--include/asm-sh/se73180.h11
-rw-r--r--include/asm-xtensa/bitops.h69
-rw-r--r--include/asm-xtensa/byteorder.h3
-rw-r--r--include/asm-xtensa/coprocessor.h8
-rw-r--r--include/asm-xtensa/div64.h15
-rw-r--r--include/asm-xtensa/elf.h3
-rw-r--r--include/asm-xtensa/fcntl.h100
-rw-r--r--include/asm-xtensa/mmu_context.h1
-rw-r--r--include/asm-xtensa/page.h2
-rw-r--r--include/asm-xtensa/param.h4
-rw-r--r--include/asm-xtensa/ptrace.h8
-rw-r--r--include/asm-xtensa/shmparam.h2
-rw-r--r--include/asm-xtensa/sigcontext.h24
-rw-r--r--include/asm-xtensa/thread_info.h2
-rw-r--r--include/asm-xtensa/unistd.h4
-rw-r--r--include/linux/ata.h3
-rw-r--r--include/linux/console_struct.h5
-rw-r--r--include/linux/ide.h1
-rw-r--r--include/linux/inetdevice.h103
-rw-r--r--include/linux/kernel.h12
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h20
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/pipe_fs_i.h30
-rw-r--r--include/linux/rfkill.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/slub_def.h25
-rw-r--r--include/linux/videodev2.h7
-rw-r--r--include/net/cipso_ipv4.h20
-rw-r--r--include/net/fib_rules.h2
-rw-r--r--include/net/genetlink.h2
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/ip_fib.h2
-rw-r--r--include/net/netlabel.h14
-rw-r--r--include/net/netlink.h12
-rw-r--r--include/net/udp.h9
-rw-r--r--include/net/udplite.h2
-rw-r--r--include/net/xfrm.h6
-rw-r--r--kernel/exit.c24
-rw-r--r--kernel/futex.c269
-rw-r--r--kernel/rtmutex.c24
-rw-r--r--lib/hexdump.c149
-rw-r--r--lib/kobject.c10
-rw-r--r--mm/shmem.c2
-rw-r--r--mm/slab.c2
-rw-r--r--mm/slub.c26
-rw-r--r--mm/sparse.c42
-rw-r--r--net/core/dev.c8
-rw-r--r--net/core/dst.c17
-rw-r--r--net/core/neighbour.c4
-rw-r--r--net/core/rtnetlink.c8
-rw-r--r--net/decnet/dn_dev.c2
-rw-r--r--net/decnet/dn_rules.c2
-rw-r--r--net/ipv4/arp.c11
-rw-r--r--net/ipv4/cipso_ipv4.c64
-rw-r--r--net/ipv4/devinet.c415
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_rules.c2
-rw-r--r--net/ipv4/igmp.c18
-rw-r--r--net/ipv4/ip_output.c4
-rw-r--r--net/ipv4/ipmr.c23
-rw-r--r--net/ipv4/netfilter/ip_tables.c81
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c13
-rw-r--r--net/ipv4/proc.c2
-rw-r--r--net/ipv4/route.c14
-rw-r--r--net/ipv4/sysctl_net_ipv4.c6
-rw-r--r--net/ipv4/tcp_ipv4.c2
-rw-r--r--net/ipv4/tcp_probe.c6
-rw-r--r--net/ipv4/tcp_timer.c4
-rw-r--r--net/ipv4/udp.c241
-rw-r--r--net/ipv4/udp_impl.h6
-rw-r--r--net/ipv4/udplite.c7
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/fib6_rules.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c9
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/udp.c21
-rw-r--r--net/ipv6/udp_impl.h2
-rw-r--r--net/ipv6/udplite.c2
-rw-r--r--net/key/af_key.c10
-rw-r--r--net/netfilter/nf_conntrack_amanda.c12
-rw-r--r--net/netfilter/nf_conntrack_core.c26
-rw-r--r--net/netfilter/nf_conntrack_expect.c4
-rw-r--r--net/netfilter/nf_conntrack_helper.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c34
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c2
-rw-r--r--net/netlabel/netlabel_cipso_v4.c2
-rw-r--r--net/netlabel/netlabel_kapi.c43
-rw-r--r--net/netlabel/netlabel_mgmt.c2
-rw-r--r--net/netlabel/netlabel_unlabeled.c2
-rw-r--r--net/netlink/attr.c8
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/sched/sch_atm.c1
-rw-r--r--net/sched/sch_cbq.c8
-rw-r--r--net/unix/af_unix.c13
-rw-r--r--net/xfrm/xfrm_policy.c63
-rw-r--r--net/xfrm/xfrm_state.c46
-rw-r--r--net/xfrm/xfrm_user.c9
-rwxr-xr-xscripts/checkpatch.pl501
-rw-r--r--security/selinux/netlabel.c36
263 files changed, 4281 insertions, 3331 deletions
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index d91125ab6f4..0958e97d4bf 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -340,8 +340,32 @@ now, but you can do this to mark internal company procedures or just
point out some special detail about the sign-off.
+13) When to use Acked-by:
-13) The canonical patch format
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+arrange to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:. It is a record that the acker
+has at least reviewed the patch and has indicated acceptance. Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by:.
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code. Judgement should be used here.
+ When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+
+14) The canonical patch format
The canonical patch subject line is:
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 2a63d5662a9..05851e9982e 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -149,7 +149,7 @@ defined which accomplish this:
void smp_mb__before_atomic_dec(void);
void smp_mb__after_atomic_dec(void);
void smp_mb__before_atomic_inc(void);
- void smp_mb__after_atomic_dec(void);
+ void smp_mb__after_atomic_inc(void);
For example, smp_mb__before_atomic_dec() can be used like so:
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 19c4a6e1367..2a97320ee17 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -96,6 +96,46 @@ System setup also associates those clocks with the device, so that that
calls to clk_get(&pdev->dev, clock_name) return them as needed.
+Legacy Drivers: Device Probing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers are not fully converted to the driver model, because they take
+on a non-driver role: the driver registers its platform device, rather than
+leaving that for system infrastructure. Such drivers can't be hotplugged
+or coldplugged, since those mechanisms require device creation to be in a
+different system component than the driver.
+
+The only "good" reason for this is to handle older system designs which, like
+original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
+configuration. Newer systems have largely abandoned that model, in favor of
+bus-level support for dynamic configuration (PCI, USB), or device tables
+provided by the boot firmware (e.g. PNPACPI on x86). There are too many
+conflicting options about what might be where, and even educated guesses by
+an operating system will be wrong often enough to make trouble.
+
+This style of driver is discouraged. If you're updating such a driver,
+please try to move the device enumeration to a more appropriate location,
+outside the driver. This will usually be cleanup, since such drivers
+tend to already have "normal" modes, such as ones using device nodes that
+were created by PNP or by platform device setup.
+
+None the less, there are some APIs to support such legacy drivers. Avoid
+using these calls except with such hotplug-deficient drivers.
+
+ struct platform_device *platform_device_alloc(
+ char *name, unsigned id);
+
+You can use platform_device_alloc() to dynamically allocate a device, which
+you will then initialize with resources and platform_device_register().
+A better solution is usually:
+
+ struct platform_device *platform_device_register_simple(
+ char *name, unsigned id,
+ struct resource *res, unsigned nres);
+
+You can use platform_device_register_simple() as a one-step call to allocate
+and register a device.
+
+
Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 49ae1ea9e86..7d3f205b0ba 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -104,6 +104,7 @@ Who: Dominik Brodowski <linux@brodo.de>
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
+Funcs: kernel_thread
Why: kernel_thread is a low-level implementation detail. Drivers should
use the <linux/kthread.h> API instead which shields them from
implementation details and provides a higherlevel interface that
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 6dd050878a2..145e4408635 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -94,10 +94,10 @@ largest node numbers in the range. For example, mpol=bind:0-3,5,7,9-15
Note that trying to mount a tmpfs with an mpol option will fail if the
running kernel does not support NUMA; and will fail if its nodelist
-specifies a node >= MAX_NUMNODES. If your system relies on that tmpfs
-being mounted, but from time to time runs a kernel built without NUMA
-capability (perhaps a safe recovery kernel), or configured to support
-fewer nodes, then it is advisable to omit the mpol option from automatic
+specifies a node which is not online. If your system relies on that
+tmpfs being mounted, but from time to time runs a kernel built without
+NUMA capability (perhaps a safe recovery kernel), or with fewer nodes
+online, then it is advisable to omit the mpol option from automatic
mount options. It can be added later, when the tmpfs is already mounted
on MountPoint, by 'mount -o remount,mpol=Policy:NodeList MountPoint'.
@@ -121,4 +121,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
- Hugh Dickins <hugh@veritas.com>, 19 February 2006
+ Hugh Dickins <hugh@veritas.com>, 4 June 2007
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index e9cc8bb26f7..c3480aa66ba 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -1,7 +1,7 @@
request_firmware() hotplug interface:
------------------------------------
- Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ Copyright (C) 2003 Manuel Estrada Sainz
Why:
---
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index 87feccdb5c9..6865cbe075e 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_driver.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Sample code on how to use request_firmware() from drivers.
*
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 9e1b0e4051c..4994f1f28f8 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_firmware_class.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* NOTE: This is just a probe of concept, if you think that your driver would
* be well served by this mechanism please contact me first.
@@ -19,7 +19,7 @@
#include <linux/firmware.h>
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
MODULE_LICENSE("GPL");
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index e06b6e3c1db..153d84d281e 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -32,6 +32,8 @@ cops.txt
- info on the COPS LocalTalk Linux driver
cs89x0.txt
- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
+cxacru.txt
+ - Conexant AccessRunner USB ADSL Modem
de4x5.txt
- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
decnet.txt
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt
new file mode 100644
index 00000000000..b074681a963
--- /dev/null
+++ b/Documentation/networking/cxacru.txt
@@ -0,0 +1,84 @@
+Firmware is required for this device: http://accessrunner.sourceforge.net/
+
+While it is capable of managing/maintaining the ADSL connection without the
+module loaded, the device will sometimes stop responding after unloading the
+driver and it is necessary to unplug/remove power to the device to fix this.
+
+Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/
+these are directories named cxacruN where N is the device number. A symlink
+named device points to the USB interface device's directory which contains
+several sysfs attribute files for retrieving device statistics:
+
+* adsl_controller_version
+
+* adsl_headend
+* adsl_headend_environment
+ Information about the remote headend.
+
+* downstream_attenuation (dB)
+* downstream_bits_per_frame
+* downstream_rate (kbps)
+* downstream_snr_margin (dB)
+ Downstream stats.
+
+* upstream_attenuation (dB)
+* upstream_bits_per_frame
+* upstream_rate (kbps)
+* upstream_snr_margin (dB)
+* transmitter_power (dBm/Hz)
+ Upstream stats.
+
+* downstream_crc_errors
+* downstream_fec_errors
+* downstream_hec_errors
+* upstream_crc_errors
+* upstream_fec_errors
+* upstream_hec_errors
+ Error counts.
+
+* line_startable
+ Indicates that ADSL support on the device
+ is/can be enabled, see adsl_start.
+
+* line_status
+ "initialising"
+ "down"
+ "attempting to activate"
+ "training"
+ "channel analysis"
+ "exchange"
+ "waiting"
+ "up"
+
+ Changes between "down" and "attempting to activate"
+ if there is no signal.
+
+* link_status
+ "not connected"
+ "connected"
+ "lost"
+
+* mac_address
+
+* modulation
+ "ANSI T1.413"
+ "ITU-T G.992.1 (G.DMT)"
+ "ITU-T G.992.2 (G.LITE)"
+
+* startup_attempts
+ Count of total attempts to initialise ADSL.
+
+To enable/disable ADSL, the following can be written to the adsl_state file:
+ "start"
+ "stop
+ "restart" (stops, waits 1.5s, then starts)
+ "poll" (used to resume status polling if it was disabled due to failure)
+
+Changes in adsl/line state are reported via kernel log messages:
+ [4942145.150704] ATM dev 0: ADSL state: running
+ [4942243.663766] ATM dev 0: ADSL line: down
+ [4942249.665075] ATM dev 0: ADSL line: attempting to activate
+ [4942253.654954] ATM dev 0: ADSL line: training
+ [4942255.666387] ATM dev 0: ADSL line: channel analysis
+ [4942259.656262] ATM dev 0: ADSL line: exchange
+ [2635357.696901] ATM dev 0: ADSL line: up (8128 kb/s down | 832 kb/s up)
diff --git a/MAINTAINERS b/MAINTAINERS
index f3b5a391e07..4c715a7e059 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -782,11 +782,6 @@ M: rathamahata@php4.ru
L: linux-kernel@vger.kernel.org
S: Maintained
-BERKSHIRE PRODUCTS PC WATCHDOG DRIVER
-P: Kenji Hollis
-W: http://ftp.bitgate.com/pcwd/
-S: Maintained
-
BFS FILE SYSTEM
P: Tigran A. Aivazian
M: tigran@aivazian.fsnet.co.uk
@@ -3025,7 +3020,7 @@ S: Maintained
REISERFS FILE SYSTEM
P: Hans Reiser
M: reiserfs-dev@namesys.com
-L: reiserfs-list@namesys.com
+L: reiserfs-devel@vger.kernel.org
W: http://www.namesys.com
S: Supported
@@ -3904,10 +3899,6 @@ S: Maintained
UCLINUX FOR NEC V850
P: Miles Bader
-M: uclinux-v850@lsi.nec.co.jp
-W: http://www.ic.nec.co.jp/micro/uclinux/eng/
-W: http://www.ee.nec.de/uclinux/
-S: Supported
UCLINUX FOR RENESAS H8/300
P: Yoshinori Sato
@@ -3916,10 +3907,10 @@ W: http://uclinux-h8.sourceforge.jp/
S: Supported
UFS FILESYSTEM
-P: Evgeniy Dushistov
-M: dushistov@mail.ru
-L: linux-kernel@vger.kernel.org
-S: Maintained
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
USB DIAMOND RIO500 DRIVER
P: Cesar Miquel
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 2568d311be2..23348e9561b 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -247,7 +247,7 @@ not_relocated: mov r0, #0
mov r3, r7
bl decompress_kernel
- add r0, r0, #127
+ add r0, r0, #127 + 128 @ alignment + stack
bic r0, r0, #127 @ align the kernel length
/*
* r0 = decompressed kernel length
@@ -269,6 +269,7 @@ not_relocated: mov r0, #0
stmia r1!, {r9 - r14}
cmp r2, r3
blo 1b
+ add sp, r1, #128 @ relocate the stack
bl cache_clean_flush
add pc, r5, r0 @ call relocation code
@@ -476,6 +477,7 @@ __common_mmu_cache_on:
*/
.align 5
reloc_start: add r9, r5, r0
+ sub r9, r9, #128 @ do not copy the stack
debug_reloc_start
mov r1, r4
1:
@@ -486,6 +488,7 @@ reloc_start: add r9, r5, r0
cmp r5, r9
blo 1b
+ add sp, r1, #128 @ relocate the stack
debug_reloc_end
call_kernel: bl cache_clean_flush
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 06c9a0507d0..848efb2a4eb 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -364,19 +364,14 @@ static int at91_clk_show(struct seq_file *s, void *unused)
{
u32 scsr, pcsr, sr;
struct clk *clk;
- unsigned i;
seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
-
seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
-
seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
- for (i = 0; i < 4; i++)
- seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
seq_printf(s, "\n");
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ff8db29e989..47ff676aca5 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -76,12 +76,11 @@ static int at91_pm_verify_clocks(void)
pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
return 0;
}
- } else if (cpu_is_at91sam9260()) {
-#warning "Check SAM9260 USB clocks"
- } else if (cpu_is_at91sam9261()) {
-#warning "Check SAM9261 USB clocks"
- } else if (cpu_is_at91sam9263()) {
-#warning "Check SAM9263 USB clocks"
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
+ if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
+ pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+ return 0;
+ }
}
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
index 7791da791f5..75bae067922 100644
--- a/arch/arm/oprofile/op_model_mpcore.c
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -200,8 +200,10 @@ static int em_call_function(int (*fn)(void))
data.fn = fn;
data.ret = 0;
+ preempt_disable();
smp_call_function(em_func, &data, 1, 1);
em_func(&data);
+ preempt_enable();
return data.ret;
}
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index ddf8fa3bbd0..1853524c8b5 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -754,7 +754,7 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
return -1;
if ( offset )
if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
- return -1
+ return -1;
RE_ENTRANT_CHECK_ON;
return 1;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 29d7d61543a..1ecb3e43b52 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -458,6 +458,11 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (error_code & 4) {
+ /*
+ * It's possible to have interrupts off here.
+ */
+ local_irq_enable();
+
/*
* Valid to do another page fault here because this one came
* from user space.
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 92e58070b01..fb66eadd589 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -62,10 +62,13 @@ void coldfire_tick(void)
/***************************************************************************/
+static int ticks_per_intr;
+
void coldfire_timer_init(irq_handler_t handler)
{
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
- __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+ ticks_per_intr = (MCF_BUSCLK / 16) / HZ;
+ __raw_writetrr(ticks_per_intr - 1, TA(MCFTIMER_TRR));
__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
@@ -81,11 +84,10 @@ void coldfire_timer_init(irq_handler_t handler)
unsigned long coldfire_timer_offset(void)
{
- unsigned long trr, tcn, offset;
+ unsigned long tcn, offset;
tcn = __raw_readw(TA(MCFTIMER_TCN));
- trr = __raw_readtrr(TA(MCFTIMER_TRR));
- offset = (tcn * (1000000 / HZ)) / trr;
+ offset = ((tcn + 1) * (1000000 / HZ)) / ticks_per_intr;
/* Check if we just wrapped the counters and maybe missed a tick */
if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0f09412e1b7..9528ee90640 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -747,9 +747,9 @@ config EARLY_PRINTK
to print messages very early in the bootup process.
This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized. For normal operation
- it is not recommended because it looks on some machines ugly and
- oesn't cooperate with an X server. You should normally N here,
+ early before the console code is initialized. For normal operation,
+ it is not recommended because it looks ugly on some machines and
+ doesn't cooperate with an X server. You should normally say N here,
unless you want to debug such a crash.
config SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
index b29a4473923..2f060e1ed36 100644
--- a/arch/mips/emma2rh/markeins/setup.c
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -115,30 +115,6 @@ extern void markeins_irq_setup(void);
static void inline __init markeins_sio_setup(void)
{
-#ifdef CONFIG_KGDB_8250
- struct uart_port emma_port;
-
- memset(&emma_port, 0, sizeof(emma_port));
-
- emma_port.flags =
- UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- emma_port.iotype = UPIO_MEM;
- emma_port.regshift = 4; /* I/O addresses are every 8 bytes */
- emma_port.uartclk = 18544000; /* Clock rate of the chip */
-
- emma_port.line = 0;
- emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
- emma_port.membase = (u8*)emma_port.mapbase;
- early_serial_setup(&emma_port);
-
- emma_port.line = 1;
- emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
- emma_port.membase = (u8*)emma_port.mapbase;
- early_serial_setup(&emma_port);
-
- emma_port.irq = EMMA2RH_IRQ_PFUR1;
- kgdb8250_add_port(1, &emma_port);
-#endif
}
void __init plat_mem_setup(void)
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 37849edd064..06e04da211d 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -556,6 +556,16 @@ asmlinkage long sys32_sync_file_range(int fd, int __pad,
flags);
}
+asmlinkage long sys32_fadvise64_64(int fd, int __pad,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ int flags)
+{
+ return sys_fadvise64_64(fd,
+ merge_64(a2, a3), merge_64(a4, a5),
+ flags);
+}
+
save_static_function(sys32_clone);
__attribute_used__ noinline static int
_sys32_clone(nabi_no_regargs struct pt_regs regs)
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index cc566cf1224..06729596812 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -174,7 +174,7 @@ LEAF(_init_fpu)
or t0, t1
mtc0 t0, CP0_STATUS
#endif /* CONFIG_MIPS_MT_SMTC */
- fpu_enable_hazard
+ enable_fpu_hazard
li t1, FPU_DEFAULT
ctc1 t1, fcr31
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 0c9a9ff8cd2..ae985d1fcca 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -657,7 +657,11 @@ einval: li v0, -EINVAL
sys sys_getcpu 3
sys sys_epoll_pwait 6
sys sys_ioprio_set 3
- sys sys_ioprio_get 2
+ sys sys_ioprio_get 2 /* 4315 */
+ sys sys_utimensat 4
+ sys sys_signalfd 3
+ sys sys_timerfd 4
+ sys sys_eventfd 1
.endm
/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 23f3b118f71..7bcd5a1a85f 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -473,4 +473,8 @@ sys_call_table:
PTR sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get
+ PTR sys_utimensat /* 5275 */
+ PTR sys_signalfd
+ PTR sys_timerfd
+ PTR sys_eventfd
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6eac2833742..532a2f3b42f 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -299,7 +299,7 @@ EXPORT(sysn32_call_table)
PTR sys_ni_syscall /* res. for afs_syscall */
PTR sys_ni_syscall /* res. for security */
PTR sys_gettid
- PTR sys32_readahead
+ PTR sys_readahead
PTR sys_setxattr /* 6180 */
PTR sys_lsetxattr
PTR sys_fsetxattr
@@ -399,4 +399,8 @@ EXPORT(sysn32_call_table)
PTR compat_sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get
+ PTR compat_sys_utimensat
+ PTR compat_sys_signalfd /* 5280 */
+ PTR compat_sys_timerfd
+ PTR sys_eventfd
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 7e74b412a78..6bbe0f4ed8b 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -459,7 +459,7 @@ sys_call_table:
PTR sys_remap_file_pages
PTR sys_set_tid_address
PTR sys_restart_syscall
- PTR sys_fadvise64_64
+ PTR sys32_fadvise64_64
PTR compat_sys_statfs64 /* 4255 */
PTR compat_sys_fstatfs64
PTR compat_sys_timer_create
@@ -521,4 +521,8 @@ sys_call_table:
PTR compat_sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get /* 4315 */
+ PTR compat_sys_utimensat
+ PTR compat_sys_signalfd
+ PTR compat_sys_timerfd
+ PTR sys_eventfd
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index c46e479c992..67edfa7ed93 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -68,7 +68,7 @@ extern ATTRIB_NORET void cpu_idle(void);
* First C code run on the secondary CPUs after being started up by
* the master.
*/
-asmlinkage void start_secondary(void)
+asmlinkage __cpuinit void start_secondary(void)
{
unsigned int cpu;
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 921207c4a83..20938a4cb52 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -121,10 +121,7 @@ LEAF(self_ipi)
subu t1,sp,PT_SIZE
sw ra,PT_EPC(t1)
sw a0,PT_PADSLOT4(t1)
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
la t2,ipi_decode
- LONG_S s0, TI_REGS($28)
sw t2,PT_PADSLOT5(t1)
/* Save pre-disable value of TCStatus */
sw t0,PT_TCSTATUS(t1)
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index b361edb83dc..21eb5993a19 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -611,12 +611,12 @@ void smtc_cpus_done(void)
int setup_irq_smtc(unsigned int irq, struct irqaction * new,
unsigned long hwmask)
{
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
unsigned int vpe = current_cpu_data.vpe_id;
- irq_hwmask[irq] = hwmask;
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1;
#endif
+ irq_hwmask[irq] = hwmask;
return setup_irq(irq, new);
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 200de027f35..a7a17eb9bfc 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -11,6 +11,7 @@
* Copyright (C) 2000, 01 MIPS Technologies, Inc.
* Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
*/
+#include <linux/bug.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -927,12 +928,6 @@ asmlinkage void do_reserved(struct pt_regs *regs)
(regs->cp0_cause & 0x7f) >> 2);
}
-static asmlinkage void do_default_vi(void)
-{
- show_regs(get_irq_regs());
- panic("Caught unexpected vectored interrupt.");
-}
-
/*
* Some MIPS CPUs can enable/disable for cache parity detection, but do
* it different ways.
@@ -1128,6 +1123,12 @@ void mips_srs_free(int set)
clear_bit(set, &sr->sr_allocated);
}
+static asmlinkage void do_default_vi(void)
+{
+ show_regs(get_irq_regs());
+ panic("Caught unexpected vectored interrupt.");
+}
+
static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
{
unsigned long handler;
@@ -1190,8 +1191,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
memcpy (b, &except_vec_vi, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC
- if (n > 7)
- printk("Vector index %d exceeds SMTC maximum\n", n);
+ BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
+
w = (u32 *)(b + mori_offset);
*w = (*w & 0xffff0000) | (0x100 << n);
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -1383,6 +1384,13 @@ void __init per_cpu_trap_init(void)
cpu_cache_init();
tlb_init();
#ifdef CONFIG_MIPS_MT_SMTC
+ } else if (!secondaryTC) {
+ /*
+ * First TC in non-boot VPE must do subset of tlb_init()
+ * for MMU countrol registers.
+ */
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
}
#endif /* CONFIG_MIPS_MT_SMTC */
}
@@ -1531,8 +1539,7 @@ void __init trap_init(void)
if (cpu_has_mipsmt)
set_except_vector(25, handle_mt);
- if (cpu_has_dsp)
- set_except_vector(26, handle_dsp);
+ set_except_vector(26, handle_dsp);
if (cpu_has_vce)
/* Special exception: R4[04]00 uses also the divec space. */
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index dfa0acbd7fc..9f49da95aac 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -248,14 +248,13 @@ void __init arch_init_irq(void)
case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
if (cpu_has_veic)
- init_msc_irqs (MSC01E_INT_BASE,
+ init_msc_irqs (MSC01E_INT_BASE, MSC01E_INT_BASE,
msc_eicirqmap, msc_nr_eicirqs);
else
- init_msc_irqs (MSC01C_INT_BASE,
+ init_msc_irqs (MSC01E_INT_BASE, MSC01C_INT_BASE,
msc_irqmap, msc_nr_irqs);
}
-
if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 0c6b0ce1502..1cc6ebbedfd 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -48,6 +48,8 @@ const char *get_system_type(void)
return "MIPS Atlas";
}
+const char display_string[] = " LINUX ON ATLAS ";
+
void __init plat_mem_setup(void)
{
mips_pcibios_init();
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
index 548dbe5ce7c..5d600054090 100644
--- a/arch/mips/mips-boards/generic/display.c
+++ b/arch/mips/mips-boards/generic/display.c
@@ -19,9 +19,14 @@
*/
#include <linux/compiler.h>
+#include <linux/timer.h>
#include <asm/io.h>
#include <asm/mips-boards/generic.h>
+extern const char display_string[];
+static unsigned int display_count;
+static unsigned int max_display_count;
+
void mips_display_message(const char *str)
{
static unsigned int __iomem *display = NULL;
@@ -37,3 +42,22 @@ void mips_display_message(const char *str)
writel(' ', display + i);
}
}
+
+static void scroll_display_message(unsigned long data);
+static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
+
+static void scroll_display_message(unsigned long data)
+{
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == max_display_count)
+ display_count = 0;
+
+ mod_timer(&mips_scroll_timer, jiffies + HZ);
+}
+
+void mips_scroll_message(void)
+{
+ del_timer_sync(&mips_scroll_timer);
+ max_display_count = strlen(display_string) + 1 - 8;
+ mod_timer(&mips_scroll_timer, jiffies + 1);
+}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index df2a2bd3aa5..b41db9e7ab1 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -53,37 +53,11 @@
unsigned long cpu_khz;
-#if defined(CONFIG_MIPS_ATLAS)
-static char display_string[] = " LINUX ON ATLAS ";
-#endif
-#if defined(CONFIG_MIPS_MALTA)
-#if defined(CONFIG_MIPS_MT_SMTC)
-static char display_string[] = " SMTC LINUX ON MALTA ";
-#else
-static char display_string[] = " LINUX ON MALTA ";
-#endif /* CONFIG_MIPS_MT_SMTC */
-#endif
-#if defined(CONFIG_MIPS_SEAD)
-static char display_string[] = " LINUX ON SEAD ";
-#endif
-static unsigned int display_count;
-#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-
#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
-static unsigned int timer_tick_count;
static int mips_cpu_timer_irq;
extern void smtc_timer_broadcast(int);
-static inline void scroll_display_message(void)
-{
- if ((timer_tick_count++ % HZ) == 0) {
- mips_display_message(&display_string[display_count++]);
- if (display_count == MAX_DISPLAY_COUNT)
- display_count = 0;
- }
-}
-
static void mips_timer_dispatch(void)
{
do_IRQ(mips_cpu_timer_irq);
@@ -114,8 +88,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the general MIPS timer_interrupt routine.
*/
- int vpflags;
-
/*
* We could be here due to timer interrupt,
* perf counter overflow, or both.
@@ -124,15 +96,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
perf_irq();
if (read_c0_cause() & (1 << 30)) {
- /* If timer interrupt, make it de-assert */
- write_c0_compare (read_c0_count() - 1);
- /*
- * DVPE is necessary so long as cross-VPE interrupts
- * are done via read-modify-write of Cause register.
- */
- vpflags = dvpe();
- clear_c0_cause(CPUCTR_IMASKBIT);
- evpe(vpflags);
/*
* There are things we only want to do once per tick
* in an "MP" system. One TC of each VPE will take
@@ -141,15 +104,13 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the tick on VPE 0 to run the full timer_interrupt().
*/
if (cpu_data[cpu].vpe_id == 0) {
- timer_interrupt(irq, NULL);
- smtc_timer_broadcast(cpu_data[cpu].vpe_id);
- scroll_display_message();
+ timer_interrupt(irq, NULL);
} else {
write_c0_compare(read_c0_count() +
(mips_hpt_frequency/HZ));
local_timer_interrupt(irq, dev_id);
- smtc_timer_broadcast(cpu_data[cpu].vpe_id);
}
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
}
#else /* CONFIG_MIPS_MT_SMTC */
int r2 = cpu_has_mips_r2;
@@ -167,8 +128,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
/* we keep interrupt disabled all the time */
if (!r2 || (read_c0_cause() & (1 << 30)))
timer_interrupt(irq, NULL);
-
- scroll_display_message();
} else {
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
@@ -262,6 +221,8 @@ void __init mips_time_init(void)
(est_freq%1000000)*100/1000000);
cpu_khz = est_freq / 1000;
+
+ mips_scroll_message();
}
void __init plat_timer_setup(struct irqaction *irq)
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 7873932532a..c14b7bf8995 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -56,6 +56,12 @@ const char *get_system_type(void)
return "MIPS Malta";
}
+#if defined(CONFIG_MIPS_MT_SMTC)
+const char display_string[] = " SMTC LINUX ON MALTA ";
+#else
+const char display_string[] = " LINUX ON MALTA ";
+#endif /* CONFIG_MIPS_MT_SMTC */
+
#ifdef CONFIG_BLK_DEV_FD
void __init fd_activate(void)
{
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index a189dec7c7b..811aba10060 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -43,6 +43,8 @@ const char *get_system_type(void)
return "MIPS SEAD";
}
+const char display_string[] = " LINUX ON SEAD ";
+
void __init plat_mem_setup(void)
{
ioport_resource.end = 0x7fffffff;
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index f0eb29917d9..76903c72764 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -168,8 +168,9 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
addr = (unsigned long) page_address(sg->page);
if (!plat_device_is_coherent(dev) && addr)
__dma_sync(addr + sg->offset, sg->length, direction);
- sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
- sg->offset;
+ sg->dma_address = plat_map_dma_mem(dev,
+ (void *)(addr + sg->offset),
+ sg->length);
}
return nents;
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index f5ea2fe10f1..89891e984b3 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -7,8 +7,6 @@
#include <asm/system.h>
#include <asm/time.h>
-extern asmlinkage void qemu_handle_int(void);
-
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause();
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index fe8a1066aec..e5e023f50a0 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -517,7 +517,7 @@ void __init paging_init(void)
pfn_t start_pfn = slot_getbasepfn(node, 0);
pfn_t end_pfn = node_getmaxclick(node) + 1;
- zones_size[ZONE_DMA] = end_pfn - start_pfn;
+ zones_size[ZONE_NORMAL] = end_pfn - start_pfn;
free_area_init_node(node, NODE_DATA(node),
zones_size, start_pfn, NULL);
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 9ee208daa8b..97b234361b4 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -6,7 +6,7 @@
* for more details.
*
* Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/init.h>
@@ -131,6 +131,19 @@ static struct resource pcimt_io_resources[] = {
}
};
+static struct resource pcimt_mem_resources[] = {
+ {
+ /*
+ * this region should only be 4 bytes long,
+ * but it's 16MB on all RM300C I've checked
+ */
+ .start = 0x1a000000,
+ .end = 0x1affffff,
+ .name = "PCI INT ACK",
+ .flags = IORESOURCE_BUSY
+ }
+};
+
static struct resource sni_mem_resource = {
.start = 0x18000000UL,
.end = 0x1fbfffffUL,
@@ -145,6 +158,9 @@ static void __init sni_pcimt_resource_init(void)
/* request I/O space for devices used on all i[345]86 PCs */
for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
request_resource(&sni_io_resource, pcimt_io_resources + i);
+ /* request MEM space for devices used on all i[345]86 PCs */
+ for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+ request_resource(&sni_mem_resource, pcimt_mem_resources + i);
}
extern struct pci_ops sni_pcimt_ops;
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 68d7cf609b4..4fedfbda0c7 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -6,7 +6,7 @@
* for more details.
*
* Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/eisa.h>
#include <linux/init.h>
@@ -92,3 +92,34 @@ void __init plat_mem_setup(void)
sni_display_setup();
}
+
+#if CONFIG_PCI
+
+#include <linux/pci.h>
+#include <video/vga.h>
+#include <video/cirrus.h>
+
+static void __devinit quirk_cirrus_ram_size(struct pci_dev *dev)
+{
+ u16 cmd;
+
+ /*
+ * firmware doesn't set the ram size correct, so we
+ * need to do it here, otherwise we get screen corruption
+ * on older Cirrus chips
+ */
+ pci_read_config_word (dev, PCI_COMMAND, &cmd);
+ if ((cmd & (PCI_COMMAND_IO|PCI_COMMAND_MEMORY))
+ == (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
+ vga_wseq (NULL, CL_SEQR6, 0x12); /* unlock all extension registers */
+ vga_wseq (NULL, CL_SEQRF, 0x18);
+ }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434_8,
+ quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5436,
+ quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
+ quirk_cirrus_ram_size);
+#endif
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
index 85053b2816a..7a97c7440b3 100644
--- a/arch/ppc/syslib/qspan_pci.c
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -365,13 +365,13 @@ int qspan_pcibios_find_class(unsigned int class_code, unsigned short index,
}
void __init
-m8xx_pcibios_fixup(void))
+m8xx_pcibios_fixup(void)
{
/* Lots to do here, all board and configuration specific. */
}
void __init
-m8xx_setup_pci_ptrs(void))
+m8xx_setup_pci_ptrs(void)
{
set_config_access_method(qspan);
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index 911ce1cdbd7..e143017c897 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -38,8 +38,8 @@ static struct platform_device *se73180_devices[] __initdata = {
static int __init se73180_devices_setup(void)
{
- return platform_add_devices(sh7343se_platform_devices,
- ARRAY_SIZE(sh7343se_platform_devices));
+ return platform_add_devices(se73180_devices,
+ ARRAY_SIZE(se73180_devices));
}
__initcall(se73180_devices_setup);
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index cc1cb04fa61..4d335077a3f 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/microdev.h>
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 70f12907647..d70e5c8461b 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -28,7 +28,7 @@ static void disable_voyagergx_irq(unsigned int irq)
unsigned long val;
unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
- pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
val = readl((void __iomem *)VOYAGER_INT_MASK);
val &= ~mask;
writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -39,7 +39,7 @@ static void enable_voyagergx_irq(unsigned int irq)
unsigned long val;
unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
- pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
val = readl((void __iomem *)VOYAGER_INT_MASK);
val |= mask;
writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -125,11 +125,12 @@ int voyagergx_irq_demux(int irq)
i = 17;
else
printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
- pr_debug("voyagergx_irq_demux %d \n", i);
- if (i < VOYAGER_IRQ_NUM) {
+ pr_debug("voyagergx_irq_demux %ld \n", i);
+ if (i < VOYAGER_IRQ_NUM) {
irq = VOYAGER_IRQ_BASE + i;
- if (voyagergx_demux[i].func != 0)
- irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
+ if (voyagergx_demux[i].func != 0)
+ irq = voyagergx_demux[i].func(irq,
+ voyagergx_demux[i].dev);
}
}
return irq;
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 659cc081e5e..b0b59d4a33c 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -320,7 +320,9 @@ skip_restore:
.align 2
5: .long 0x00001000 ! DSP
+#ifdef CONFIG_KGDB_NMI
6: .long in_nmi
+#endif
7: .long 0x30000000
! common exception handler
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index fcb2c41bc34..a33429463e9 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -111,7 +111,7 @@ static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
{
unsigned long frqcr3;
unsigned int tmp;
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index be03d74e99c..0c7b7e33abd 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -22,6 +22,7 @@
#include <asm/addrspace.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#include <asm/mmu.h>
/*
* Remap an arbitrary physical address space into the kernel virtual
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index fb51660847c..3334f99b583 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -521,10 +521,10 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
bus->resource[0]->start = PCIBIOS_MIN_IO;
bus->resource[1]->start = PCIBIOS_MIN_MEM;
#else
- bus->resource[0]->end = 0
- bus->resource[1]->end = 0
- bus->resource[0]->start =0
- bus->resource[1]->start = 0;
+ bus->resource[0]->end = 0;
+ bus->resource[1]->end = 0;
+ bus->resource[0]->start =0;
+ bus->resource[1]->start = 0;
#endif
/* Turn off downstream PF memory address range by default */
bus->resource[2]->start = 1024*1024;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 16cc46a7187..6676b93219d 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -343,6 +343,15 @@ static int of_bus_simba_match(struct device_node *np)
if (model && !strcmp(model, "SUNW,simba"))
return 1;
+
+ /* Treat PCI busses lacking ranges property just like
+ * simba.
+ */
+ if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+ if (!of_find_property(np, "ranges", NULL))
+ return 1;
+ }
+
return 0;
}
@@ -549,8 +558,6 @@ static int __init build_one_resource(struct device_node *parent,
static int __init use_1to1_mapping(struct device_node *pp)
{
- const char *model;
-
/* If this is on the PMU bus, don't try to translate it even
* if a ranges property exists.
*/
@@ -567,9 +574,11 @@ static int __init use_1to1_mapping(struct device_node *pp)
if (!strcmp(pp->name, "dma"))
return 0;
- /* Similarly for Simba PCI bridges. */
- model = of_get_property(pp, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba"))
+ /* Similarly for all PCI bridges, if we get this far
+ * it lacks a ranges property, and this will include
+ * cases like Simba.
+ */
+ if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex"))
return 0;
return 1;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 38a32bc95d2..81f4a5ea05f 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -522,6 +522,89 @@ static void pci_resource_adjust(struct resource *res,
res->end += root->start;
}
+/* For PCI bus devices which lack a 'ranges' property we interrogate
+ * the config space values to set the resources, just like the generic
+ * Linux PCI probing code does.
+ */
+static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
+ struct pci_bus *bus,
+ struct pci_pbm_info *pbm)
+{
+ struct resource *res;
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base_lo, mem_limit_lo;
+ unsigned long base, limit;
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+ pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+ base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+ limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ u16 io_base_hi, io_limit_hi;
+
+ pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+ pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+ base |= (io_base_hi << 16);
+ limit |= (io_limit_hi << 16);
+ }
+
+ res = bus->resource[0];
+ if (base <= limit) {
+ res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+ if (!res->start)
+ res->start = base;
+ if (!res->end)
+ res->end = limit + 0xfff;
+ pci_resource_adjust(res, &pbm->io_space);
+ }
+
+ pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+
+ res = bus->resource[1];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+
+ pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+ if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+ u32 mem_base_hi, mem_limit_hi;
+
+ pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+ pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+
+ /*
+ * Some bridges set the base > limit by default, and some
+ * (broken) BIOSes do not initialize them. If we find
+ * this, just assume they are not being used.
+ */
+ if (mem_base_hi <= mem_limit_hi) {
+ base |= ((long) mem_base_hi) << 32;
+ limit |= ((long) mem_limit_hi) << 32;
+ }
+ }
+
+ res = bus->resource[2];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM | IORESOURCE_PREFETCH);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+}
+
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
* a proper 'ranges' property.
*/
@@ -581,13 +664,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
simba = 0;
if (ranges == NULL) {
const char *model = of_get_property(node, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba")) {
+ if (model && !strcmp(model, "SUNW,simba"))
simba = 1;
- } else {
- printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
- node->full_name);
- return;
- }
}
bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
@@ -611,7 +689,10 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
if (simba) {
apb_fake_ranges(dev, bus, pbm);
- goto simba_cont;
+ goto after_ranges;
+ } else if (ranges == NULL) {
+ pci_cfg_fake_ranges(dev, bus, pbm);
+ goto after_ranges;
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
@@ -650,7 +731,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
*/
pci_resource_adjust(res, root);
}
-simba_cont:
+after_ranges:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
if (ofpci_verbose)
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 323d6c27851..22e1be5c748 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -636,13 +636,18 @@ static void apb_init(struct pci_bus *sabre_bus)
static void sabre_scan_bus(struct pci_pbm_info *pbm)
{
static int once;
- struct pci_bus *pbus;
/* The APB bridge speaks to the Sabre host PCI bridge
* at 66Mhz, but the front side of APB runs at 33Mhz
* for both segments.
+ *
+ * Hummingbird systems do not use APB, so they run
+ * at 66MHZ.
*/
- pbm->is_66mhz_capable = 0;
+ if (hummingbird_p)
+ pbm->is_66mhz_capable = 1;
+ else
+ pbm->is_66mhz_capable = 0;
/* This driver has not been verified to handle
* multiple SABREs yet, so trap this.
@@ -656,13 +661,13 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm)
}
once++;
- pbus = pci_scan_one_pbm(pbm);
- if (!pbus)
+ pbm->pci_bus = pci_scan_one_pbm(pbm);
+ if (!pbm->pci_bus)
return;
- sabre_root_bus = pbus;
+ sabre_root_bus = pbm->pci_bus;
- apb_init(pbus);
+ apb_init(pbm->pci_bus);
sabre_register_error_handlers(pbm);
}
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 6f4a5284b0e..61036b34666 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -933,29 +933,29 @@ static void __init fire_irq_trans_init(struct device_node *dp)
* This should conform to both Sunfire/Wildfire server and Fusion
* desktop designs.
*/
-#define SYSIO_IMAP_SLOT0 0x2c04UL
-#define SYSIO_IMAP_SLOT1 0x2c0cUL
-#define SYSIO_IMAP_SLOT2 0x2c14UL
-#define SYSIO_IMAP_SLOT3 0x2c1cUL
-#define SYSIO_IMAP_SCSI 0x3004UL
-#define SYSIO_IMAP_ETH 0x300cUL
-#define SYSIO_IMAP_BPP 0x3014UL
-#define SYSIO_IMAP_AUDIO 0x301cUL
-#define SYSIO_IMAP_PFAIL 0x3024UL
-#define SYSIO_IMAP_KMS 0x302cUL
-#define SYSIO_IMAP_FLPY 0x3034UL
-#define SYSIO_IMAP_SHW 0x303cUL
-#define SYSIO_IMAP_KBD 0x3044UL
-#define SYSIO_IMAP_MS 0x304cUL
-#define SYSIO_IMAP_SER 0x3054UL
-#define SYSIO_IMAP_TIM0 0x3064UL
-#define SYSIO_IMAP_TIM1 0x306cUL
-#define SYSIO_IMAP_UE 0x3074UL
-#define SYSIO_IMAP_CE 0x307cUL
-#define SYSIO_IMAP_SBERR 0x3084UL
-#define SYSIO_IMAP_PMGMT 0x308cUL
-#define SYSIO_IMAP_GFX 0x3094UL
-#define SYSIO_IMAP_EUPA 0x309cUL
+#define SYSIO_IMAP_SLOT0 0x2c00UL
+#define SYSIO_IMAP_SLOT1 0x2c08UL
+#define SYSIO_IMAP_SLOT2 0x2c10UL
+#define SYSIO_IMAP_SLOT3 0x2c18UL
+#define SYSIO_IMAP_SCSI 0x3000UL
+#define SYSIO_IMAP_ETH 0x3008UL
+#define SYSIO_IMAP_BPP 0x3010UL
+#define SYSIO_IMAP_AUDIO 0x3018UL
+#define SYSIO_IMAP_PFAIL 0x3020UL
+#define SYSIO_IMAP_KMS 0x3028UL
+#define SYSIO_IMAP_FLPY 0x3030UL
+#define SYSIO_IMAP_SHW 0x3038UL
+#define SYSIO_IMAP_KBD 0x3040UL
+#define SYSIO_IMAP_MS 0x3048UL
+#define SYSIO_IMAP_SER 0x3050UL
+#define SYSIO_IMAP_TIM0 0x3060UL
+#define SYSIO_IMAP_TIM1 0x3068UL
+#define SYSIO_IMAP_UE 0x3070UL
+#define SYSIO_IMAP_CE 0x3078UL
+#define SYSIO_IMAP_SBERR 0x3080UL
+#define SYSIO_IMAP_PMGMT 0x3088UL
+#define SYSIO_IMAP_GFX 0x3090UL
+#define SYSIO_IMAP_EUPA 0x3098UL
#define bogon ((unsigned long) -1)
static unsigned long sysio_irq_offsets[] = {
@@ -1006,10 +1006,10 @@ static unsigned long sysio_irq_offsets[] = {
* Interrupt Clear register pointer, SYSIO specific version.
*/
#define SYSIO_ICLR_UNUSED0 0x3400UL
-#define SYSIO_ICLR_SLOT0 0x340cUL
-#define SYSIO_ICLR_SLOT1 0x344cUL
-#define SYSIO_ICLR_SLOT2 0x348cUL
-#define SYSIO_ICLR_SLOT3 0x34ccUL
+#define SYSIO_ICLR_SLOT0 0x3408UL
+#define SYSIO_ICLR_SLOT1 0x3448UL
+#define SYSIO_ICLR_SLOT2 0x3488UL
+#define SYSIO_ICLR_SLOT3 0x34c8UL
static unsigned long sysio_imap_to_iclr(unsigned long imap)
{
unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 91f6e2a74ad..a1fd9bcc0b8 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -629,29 +629,29 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
* This should conform to both Sunfire/Wildfire server and Fusion
* desktop designs.
*/
-#define SYSIO_IMAP_SLOT0 0x2c04UL
-#define SYSIO_IMAP_SLOT1 0x2c0cUL
-#define SYSIO_IMAP_SLOT2 0x2c14UL
-#define SYSIO_IMAP_SLOT3 0x2c1cUL
-#define SYSIO_IMAP_SCSI 0x3004UL
-#define SYSIO_IMAP_ETH 0x300cUL
-#define SYSIO_IMAP_BPP 0x3014UL
-#define SYSIO_IMAP_AUDIO 0x301cUL
-#define SYSIO_IMAP_PFAIL 0x3024UL
-#define SYSIO_IMAP_KMS 0x302cUL
-#define SYSIO_IMAP_FLPY 0x3034UL
-#define SYSIO_IMAP_SHW 0x303cUL
-#define SYSIO_IMAP_KBD 0x3044UL
-#define SYSIO_IMAP_MS 0x304cUL
-#define SYSIO_IMAP_SER 0x3054UL
-#define SYSIO_IMAP_TIM0 0x3064UL
-#define SYSIO_IMAP_TIM1 0x306cUL
-#define SYSIO_IMAP_UE 0x3074UL
-#define SYSIO_IMAP_CE 0x307cUL
-#define SYSIO_IMAP_SBERR 0x3084UL
-#define SYSIO_IMAP_PMGMT 0x308cUL
-#define SYSIO_IMAP_GFX 0x3094UL
-#define SYSIO_IMAP_EUPA 0x309cUL
+#define SYSIO_IMAP_SLOT0 0x2c00UL
+#define SYSIO_IMAP_SLOT1 0x2c08UL
+#define SYSIO_IMAP_SLOT2 0x2c10UL
+#define SYSIO_IMAP_SLOT3 0x2c18UL
+#define SYSIO_IMAP_SCSI 0x3000UL
+#define SYSIO_IMAP_ETH 0x3008UL
+#define SYSIO_IMAP_BPP 0x3010UL
+#define SYSIO_IMAP_AUDIO 0x3018UL
+#define SYSIO_IMAP_PFAIL 0x3020UL
+#define SYSIO_IMAP_KMS 0x3028UL
+#define SYSIO_IMAP_FLPY 0x3030UL
+#define SYSIO_IMAP_SHW 0x3038UL
+#define SYSIO_IMAP_KBD 0x3040UL
+#define SYSIO_IMAP_MS 0x3048UL
+#define SYSIO_IMAP_SER 0x3050UL
+#define SYSIO_IMAP_TIM0 0x3060UL
+#define SYSIO_IMAP_TIM1 0x3068UL
+#define SYSIO_IMAP_UE 0x3070UL
+#define SYSIO_IMAP_CE 0x3078UL
+#define SYSIO_IMAP_SBERR 0x3080UL
+#define SYSIO_IMAP_PMGMT 0x3088UL
+#define SYSIO_IMAP_GFX 0x3090UL
+#define SYSIO_IMAP_EUPA 0x3098UL
#define bogon ((unsigned long) -1)
static unsigned long sysio_irq_offsets[] = {
@@ -700,10 +700,10 @@ static unsigned long sysio_irq_offsets[] = {
* Interrupt Clear register pointer, SYSIO specific version.
*/
#define SYSIO_ICLR_UNUSED0 0x3400UL
-#define SYSIO_ICLR_SLOT0 0x340cUL
-#define SYSIO_ICLR_SLOT1 0x344cUL
-#define SYSIO_ICLR_SLOT2 0x348cUL
-#define SYSIO_ICLR_SLOT3 0x34ccUL
+#define SYSIO_ICLR_SLOT0 0x3408UL
+#define SYSIO_ICLR_SLOT1 0x3448UL
+#define SYSIO_ICLR_SLOT2 0x3488UL
+#define SYSIO_ICLR_SLOT3 0x34c8UL
static unsigned long sysio_imap_to_iclr(unsigned long imap)
{
unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d00f51a5683..6fa76161289 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -24,6 +24,7 @@
#include <linux/syscalls.h>
#include <linux/percpu.h>
#include <linux/init.h>
+#include <linux/rwsem.h>
#include <net/compat.h>
#include <asm/oplib.h>
@@ -58,7 +59,6 @@
#include <asm/ns87303.h>
#include <asm/timer.h>
#include <asm/cpudata.h>
-#include <asm/rwsem.h>
struct poll {
int fd;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c504312219b..e6ff3026654 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -278,6 +278,7 @@ config HIGHMEM
config KERNEL_STACK_ORDER
int "Kernel stack size order"
default 1 if 64BIT
+ range 1 10 if 64BIT
default 0 if !64BIT
help
This option determines the size of UML kernel stacks. They will
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ced99106f79..4bd40bb43ec 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/list.h"
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 91153929387..4739dd527b4 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/console.h>
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 70509ddaac0..2e09f162c42 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -20,6 +20,7 @@
#define MAJOR_NR UBD_MAJOR
#define UBD_SHIFT 4
+#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/blkdev.h"
#include "linux/hdreg.h"
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 8b7f2cdedf9..c716b5a6db1 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,8 +1,9 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/ctype.h"
#include "linux/proc_fs.h"
@@ -24,11 +25,14 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count) *eof = 1;
+ if(len <= off+count)
+ *eof = 1;
*start = page + off;
- if(len > count) len = count;
- if(len < 0) len = 0;
- return(len);
+ if(len > count)
+ len = count;
+ if(len < 0)
+ len = 0;
+ return len;
}
static int write_proc_exitcode(struct file *file, const char __user *buffer,
@@ -38,12 +42,14 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
int tmp;
if(copy_from_user(buf, buffer, count))
- return(-EFAULT);
+ return -EFAULT;
+
tmp = simple_strtol(buf, &end, 0);
if((*end != '\0') && !isspace(*end))
- return(-EINVAL);
+ return -EINVAL;
+
uml_exitcode = tmp;
- return(count);
+ return count;
}
static int make_proc_exitcode(void)
@@ -54,24 +60,13 @@ static int make_proc_exitcode(void)
if(ent == NULL){
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
- return(0);
+ return 0;
}
ent->read_proc = read_proc_exitcode;
ent->write_proc = write_proc_exitcode;
-
- return(0);
+
+ return 0;
}
__initcall(make_proc_exitcode);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index cb29fb96948..aac1c0be54c 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -465,13 +465,14 @@ static unsigned int die_nest_count;
unsigned __kprobes long oops_begin(void)
{
- int cpu = smp_processor_id();
+ int cpu;
unsigned long flags;
oops_enter();
/* racy, but better than risking deadlock. */
local_irq_save(flags);
+ cpu = smp_processor_id();
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index bfb62a13d7e..635e58d443d 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -476,6 +476,12 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (error_code & PF_USER) {
+
+ /*
+ * It's possible to have interrupts off here.
+ */
+ local_irq_enable();
+
if (is_prefetch(regs, address, error_code))
return;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 1ad5111aec3..efb6e845114 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -79,6 +79,8 @@ void show_mem(void)
if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
touch_nmi_watchdog();
}
+ if (!pfn_valid(pgdat->node_start_pfn + i))
+ continue;
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
if (PageReserved(page))
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 698079b3a33..d0323cd6a2e 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -39,6 +39,7 @@ int main(void)
DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
+ DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel));
DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9e271ba009b..8dc7a2c26ff 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -125,8 +125,9 @@ _user_exception:
movi a2, 0
rsr a3, SAR
- wsr a2, ICOUNTLEVEL
+ xsr a2, ICOUNTLEVEL
s32i a3, a1, PT_SAR
+ s32i a2, a1, PT_ICOUNTLEVEL
/* Rotate ws so that the current windowbase is at bit0. */
/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
@@ -276,8 +277,9 @@ _kernel_exception:
movi a2, 0
rsr a3, SAR
- wsr a2, ICOUNTLEVEL
+ xsr a2, ICOUNTLEVEL
s32i a3, a1, PT_SAR
+ s32i a2, a1, PT_ICOUNTLEVEL
/* Rotate ws so that the current windowbase is at bit0. */
/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
@@ -330,14 +332,16 @@ _kernel_exception:
common_exception:
- /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
+ /* Save some registers, disable loops and clear the syscall flag. */
rsr a2, DEBUGCAUSE
rsr a3, EPC_1
s32i a2, a1, PT_DEBUGCAUSE
s32i a3, a1, PT_PC
+ movi a2, -1
rsr a3, EXCVADDR
+ s32i a2, a1, PT_SYSCALL
movi a2, 0
s32i a3, a1, PT_EXCVADDR
xsr a2, LCOUNT
@@ -450,27 +454,8 @@ common_exception_return:
/* Restore the state of the task and return from the exception. */
-
- /* If we are returning from a user exception, and the process
- * to run next has PT_SINGLESTEP set, we want to setup
- * ICOUNT and ICOUNTLEVEL to step one instruction.
- * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
- */
-
4: /* a2 holds GET_CURRENT(a2,a1) */
- l32i a3, a2, TI_TASK
- l32i a3, a3, TASK_PTRACE
- bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
-
- movi a3, -2 # PT_SINGLESTEP flag is set,
- movi a4, 1 # icountlevel of 1 means it won't
- wsr a3, ICOUNT # start counting until after rfe
- wsr a4, ICOUNTLEVEL # so setup icount & icountlevel.
- isync
-
-1:
-
#if XCHAL_EXTRA_SA_SIZE
/* For user exceptions, restore the extra state from the user's TCB. */
@@ -665,6 +650,13 @@ common_exception_exit:
wsr a3, LEND
wsr a2, LCOUNT
+ /* We control single stepping through the ICOUNTLEVEL register. */
+
+ l32i a2, a1, PT_ICOUNTLEVEL
+ movi a3, -2
+ wsr a2, ICOUNTLEVEL
+ wsr a3, ICOUNT
+
/* Check if it was double exception. */
l32i a0, a1, PT_DEPC
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index ea89910efa4..67e69139520 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -19,6 +19,8 @@
#include <asm/page.h>
#include <asm/cacheasm.h>
+#include <linux/linkage.h>
+
/*
* This module contains the entry code for kernel images. It performs the
* minimal setup needed to call the generic C routines.
@@ -227,13 +229,14 @@ _startup:
should_never_return:
j should_never_return
- /* Define some common data structures here. We define them
- * here in this assembly file due to their unusual alignment
- * requirements.
- */
- .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
- .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
- .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE
- .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE
+/*
+ * BSS section
+ */
+
+.section ".bss.page_aligned", "w"
+ENTRY(swapper_pg_dir)
+ .fill PAGE_SIZE, 1, 0
+ENTRY(empty_zero_page)
+ .fill PAGE_SIZE, 1, 0
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 45571ccb72d..77deae5290f 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -401,7 +401,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
* Also, think for a moment about likes of floppy.c that
* include architecture specific parts. They may want to redefine ins/outs.
*
- * We do not use horroble macroses here because we want to
+ * We do not use horrible macros here because we want to
* advance pointer by sizeof(size).
*/
void outsb(unsigned long addr, const void *src, unsigned long count) {
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 1ecf6716c32..2e8d398cf19 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -41,6 +41,7 @@
#include <asm/platform.h>
#include <asm/page.h>
#include <asm/setup.h>
+#include <asm/param.h>
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 58107672a61..033aae0336d 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -1,397 +1,239 @@
-// TODO coprocessor stuff
/*
- * linux/arch/xtensa/kernel/signal.c
+ * arch/xtensa/kernel/signal.c
*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
- *
- * Joe Taylor <joe@tensilica.com>
- * Chris Zankel <chris@zankel.net>
+ * Default platform functions.
*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
+ * Copyright (C) 2005, 2006 Tensilica Inc.
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
*/
-#include <asm/variant/core.h>
-#include <asm/coprocessor.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
-#include <linux/wait.h>
#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
#include <linux/personality.h>
+#include <linux/freezer.h>
+
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
#include <asm/cacheflush.h>
+#include <asm/coprocessor.h>
+#include <asm/unistd.h>
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
- struct rusage * ru);
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
extern struct task_struct *coproc_owners[];
+extern void release_all_cp (struct task_struct *);
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ cp_state_t cpstate;
+ unsigned char retcode[6];
+ unsigned int window[4];
+};
+
+/*
+ * Flush register windows stored in pt_regs to stack.
+ * Returns 1 for errors.
+ *
+ * Note that windowbase, windowstart, and wmask are not updated!
*/
-int xtensa_sigsuspend(struct pt_regs *regs)
+int
+flush_window_regs_user(struct pt_regs *regs)
{
- old_sigset_t mask = (old_sigset_t) regs->areg[3];
- sigset_t saveset;
+ const unsigned long ws = regs->windowstart;
+ const unsigned long wb = regs->windowbase;
+ unsigned long sp = 0;
+ unsigned long wm;
+ int err = 1;
+ int base;
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ /* Return if no other frames. */
- regs->areg[2] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
+ if (regs->wmask == 1)
+ return 0;
-asmlinkage int
-xtensa_rt_sigsuspend(struct pt_regs *regs)
-{
- sigset_t *unewset = (sigset_t *) regs->areg[4];
- size_t sigsetsize = (size_t) regs->areg[3];
- sigset_t saveset, newset;
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ /* Rotate windowmask and skip empty frames. */
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb));
+ base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4);
+
+ /* For call8 or call12 frames, we need the previous stack pointer. */
- regs->areg[2] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
+ if ((regs->wmask & 2) == 0)
+ if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12)))
+ goto errout;
-asmlinkage int
-xtensa_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
+ /* Spill frames to stack. */
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
+ while (base < XCHAL_NUM_AREGS / 4) {
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+ int m = (wm >> base);
+ int inc = 0;
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
+ /* Save registers a4..a7 (call8) or a4...a11 (call12) */
- return ret;
-}
+ if (m & 2) { /* call4 */
+ inc = 1;
-asmlinkage int
-xtensa_sigaltstack(struct pt_regs *regs)
-{
- const stack_t *uss = (stack_t *) regs->areg[4];
- stack_t *uoss = (stack_t *) regs->areg[3];
+ } else if (m & 4) { /* call8 */
+ if (copy_to_user((void*)(sp - 32),
+ &regs->areg[(base + 1) * 4], 16))
+ goto errout;
+ inc = 2;
- if (regs->depc > 64)
- panic ("Double exception sys_sigreturn\n");
+ } else if (m & 8) { /* call12 */
+ if (copy_to_user((void*)(sp - 48),
+ &regs->areg[(base + 1) * 4], 32))
+ goto errout;
+ inc = 3;
+ }
+ /* Save current frame a0..a3 under next SP */
- return do_sigaltstack(uss, uoss, regs->areg[1]);
-}
+ sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS];
+ if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16))
+ goto errout;
+
+ /* Get current stack pointer for next loop iteration. */
+
+ sp = regs->areg[base * 4 + 1];
+ base += inc;
+ }
+
+ return 0;
+errout:
+ return err;
+}
/*
- * Do a signal return; undo the signal stack.
+ * Note: We don't copy double exception 'regs', we have to finish double exc.
+ * first before we return to signal handler! This dbl.exc.handler might cause
+ * another double exception, but I think we are fine as the situation is the
+ * same as if we had returned to the signal handerl and got an interrupt
+ * immediately...
*/
-struct sigframe
-{
- struct sigcontext sc;
- struct _cpstate cpstate;
- unsigned long extramask[_NSIG_WORDS-1];
- unsigned char retcode[6];
- unsigned int reserved[4]; /* Reserved area for chaining */
- unsigned int window[4]; /* Window of 4 registers for initial context */
-};
-
-struct rt_sigframe
+static int
+setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate,
+ struct pt_regs *regs, unsigned long mask)
{
- struct siginfo info;
- struct ucontext uc;
- struct _cpstate cpstate;
- unsigned char retcode[6];
- unsigned int reserved[4]; /* Reserved area for chaining */
- unsigned int window[4]; /* Window of 4 registers for initial context */
-};
+ int err = 0;
-extern void release_all_cp (struct task_struct *);
+#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
+ COPY(pc);
+ COPY(ps);
+ COPY(lbeg);
+ COPY(lend);
+ COPY(lcount);
+ COPY(sar);
+#undef COPY
+ err |= flush_window_regs_user(regs);
+ err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4);
-// FIXME restore_cpextra
-static inline int
-restore_cpextra (struct _cpstate *buf)
-{
-#if 0
- /* The signal handler may have used coprocessors in which
- * case they are still enabled. We disable them to force a
- * reloading of the original task's CP state by the lazy
- * context-switching mechanisms of CP exception handling.
- * Also, we essentially discard any coprocessor state that the
- * signal handler created. */
+ // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4)
- struct task_struct *tsk = current;
- release_all_cp(tsk);
- return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE);
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
+ err |= save_cpextra(cpstate);
+ err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
#endif
- return 0;
-}
-
-/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
- */
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+ return err;
+}
static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
- struct thread_struct *thread;
unsigned int err = 0;
unsigned long ps;
- struct _cpstate *buf;
#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
COPY(pc);
- COPY(depc);
- COPY(wmask);
COPY(lbeg);
COPY(lend);
COPY(lcount);
COPY(sar);
- COPY(windowbase);
- COPY(windowstart);
#undef COPY
+ /* All registers were flushed to stack. Start with a prestine frame. */
+
+ regs->wmask = 1;
+ regs->windowbase = 0;
+ regs->windowstart = 1;
+
/* For PS, restore only PS.CALLINC.
* Assume that all other bits are either the same as for the signal
* handler, or the user mode value doesn't matter (e.g. PS.OWB).
*/
err |= __get_user(ps, &sc->sc_ps);
- regs->ps = (regs->ps & ~PS_CALLINC_MASK)
- | (ps & PS_CALLINC_MASK);
+ regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK);
/* Additional corruption checks */
- if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
- || ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
- err = 1;
if ((regs->lcount > 0)
- && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
+ && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
err = 1;
- /* Restore extended register state.
- * See struct thread_struct in processor.h.
- */
- thread = &current->thread;
-
- err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
- err |= __get_user(buf, &sc->sc_cpstate);
- if (buf) {
- if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
- goto badframe;
- err |= restore_cpextra(buf);
- }
-
- regs->syscall = -1; /* disable syscall checks */
- return err;
-
-badframe:
- return 1;
-}
-
-static inline void
-flush_my_cpstate(struct task_struct *tsk)
-{
- unsigned long flags;
- local_irq_save(flags);
-
-#if 0 // FIXME
- for (i = 0; i < XCHAL_CP_NUM; i++) {
- if (tsk == coproc_owners[i]) {
- xthal_validate_cp(i);
- xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
+ err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4);
- /* Invalidate and "disown" the cp to allow
- * callers the chance to reset cp state in the
- * task_struct. */
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
+ /* The signal handler may have used coprocessors in which
+ * case they are still enabled. We disable them to force a
+ * reloading of the original task's CP state by the lazy
+ * context-switching mechanisms of CP exception handling.
+ * Also, we essentially discard any coprocessor state that the
+ * signal handler created. */
- xthal_invalidate_cp(i);
- coproc_owners[i] = 0;
- }
+ if (!err) {
+ struct task_struct *tsk = current;
+ release_all_cp(tsk);
+ err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate,
+ XTENSA_CP_EXTRA_SIZE);
}
#endif
- local_irq_restore(flags);
-}
-
-/* Return codes:
- 0: nothing saved
- 1: stuff to save, successful
- -1: stuff to save, error happened
-*/
-static int
-save_cpextra (struct _cpstate *buf)
-{
-#if XCHAL_CP_NUM == 0
- return 0;
-#else
-
- /* FIXME: If a task has never used a coprocessor, there is
- * no need to save and restore anything. Tracking this
- * information would allow us to optimize this section.
- * Perhaps we can use current->used_math or (current->flags &
- * PF_USEDFPU) or define a new field in the thread
- * structure. */
-
- /* We flush any live, task-owned cp state to the task_struct,
- * then copy it all to the sigframe. Then we clear all
- * cp/extra state in the task_struct, effectively
- * clearing/resetting all cp/extra state for the signal
- * handler (cp-exception handling will load these new values
- * into the cp/extra registers.) This step is important for
- * things like a floating-point cp, where the OS must reset
- * the FCR to the default rounding mode. */
-
- int err = 0;
- struct task_struct *tsk = current;
-
- flush_my_cpstate(tsk);
- /* Note that we just copy everything: 'extra' and 'cp' state together.*/
- err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
- memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
-
-#if (XTENSA_CP_EXTRA_SIZE == 0)
-#error Sanity check on memset above, cpextra_size should not be zero.
-#endif
-
- return err ? -1 : 1;
-#endif
-}
-
-static int
-setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
- struct pt_regs *regs, unsigned long mask)
-{
- struct thread_struct *thread;
- int err = 0;
-
-//printk("setup_sigcontext\n");
-#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
- COPY(pc);
- COPY(ps);
- COPY(depc);
- COPY(wmask);
- COPY(lbeg);
- COPY(lend);
- COPY(lcount);
- COPY(sar);
- COPY(windowbase);
- COPY(windowstart);
-#undef COPY
-
- /* Save extended register state.
- * See struct thread_struct in processor.h.
- */
- thread = &current->thread;
- err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
- err |= save_cpextra(cpstate);
- err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
- /* non-iBCS2 extensions.. */
- err |= __put_user(mask, &sc->oldmask);
+ regs->syscall = -1; /* disable syscall checks */
return err;
}
-asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
-{
- struct sigframe *frame = (struct sigframe *)regs->areg[1];
- sigset_t set;
- if (regs->depc > 64)
- panic ("Double exception sys_sigreturn\n");
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_NSIG_WORDS > 1
- && __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- if (restore_sigcontext(regs, &frame->sc))
- goto badframe;
- return regs->areg[2];
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
+/*
+ * Do a signal return; undo the signal stack.
+ */
-asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
+ long a4, long a5, struct pt_regs *regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
+ struct rt_sigframe __user *frame;
sigset_t set;
- stack_t st;
int ret;
+
if (regs->depc > 64)
- {
- printk("!!!!!!! DEPC !!!!!!!\n");
- return 0;
- }
+ panic("rt_sigreturn in double exception!\n");
+
+ frame = (struct rt_sigframe __user *) regs->areg[1];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -407,13 +249,11 @@ asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
+
ret = regs->areg[2];
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT)
goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->areg[1]);
return ret;
@@ -422,77 +262,50 @@ badframe:
return 0;
}
-/*
- * Set up a signal frame.
- */
+
/*
- * Determine which stack to use..
+ * Set up a signal frame.
*/
-static inline void *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
-{
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- return (void *)((sp - frame_size) & -16ul);
-}
-
-#define USE_SIGRETURN 0
-#define USE_RT_SIGRETURN 1
static int
-gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
+gen_return_code(unsigned char *codemem)
{
- unsigned int retcall;
int err = 0;
-#if 0
- /* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
- * and the xtensa glibc doesn't use it.
+ /*
+ * The 12-bit immediate is really split up within the 24-bit MOVI
+ * instruction. As long as the above system call numbers fit within
+ * 8-bits, the following code works fine. See the Xtensa ISA for
+ * details.
*/
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->pr = (unsigned long) ka->sa.sa_restorer;
- } else
-#endif /* 0 */
- {
-
-#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
-
-/* The 12-bit immediate is really split up within the 24-bit MOVI
- * instruction. As long as the above system call numbers fit within
- * 8-bits, the following code works fine. See the Xtensa ISA for
- * details.
- */
-#error Generating the MOVI instruction below breaks!
+#if __NR_rt_sigreturn > 255
+# error Generating the MOVI instruction below breaks!
#endif
- retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
-
#ifdef __XTENSA_EB__ /* Big Endian version */
- /* Generate instruction: MOVI a2, retcall */
- err |= __put_user(0x22, &codemem[0]);
- err |= __put_user(0x0a, &codemem[1]);
- err |= __put_user(retcall, &codemem[2]);
- /* Generate instruction: SYSCALL */
- err |= __put_user(0x00, &codemem[3]);
- err |= __put_user(0x05, &codemem[4]);
- err |= __put_user(0x00, &codemem[5]);
+ /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0x0a, &codemem[1]);
+ err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x05, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
#elif defined __XTENSA_EL__ /* Little Endian version */
- /* Generate instruction: MOVI a2, retcall */
- err |= __put_user(0x22, &codemem[0]);
- err |= __put_user(0xa0, &codemem[1]);
- err |= __put_user(retcall, &codemem[2]);
- /* Generate instruction: SYSCALL */
- err |= __put_user(0x00, &codemem[3]);
- err |= __put_user(0x50, &codemem[4]);
- err |= __put_user(0x00, &codemem[5]);
+ /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0xa0, &codemem[1]);
+ err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x50, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
#else
-#error Must use compiler for Xtensa processors.
+# error Must use compiler for Xtensa processors.
#endif
- }
/* Flush generated code out of the data cache */
@@ -504,97 +317,29 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
return err;
}
-static void
-set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
- void *handler, unsigned long arg1, void *arg2, void *arg3)
-{
- /* Set up registers for signal handler */
- start_thread(regs, (unsigned long) handler, (unsigned long) stack);
-
- /* Set up a stack frame for a call4
- * Note: PS.CALLINC is set to one by start_thread
- */
- regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
- regs->areg[6] = arg1;
- regs->areg[7] = (unsigned long) arg2;
- regs->areg[8] = (unsigned long) arg3;
-}
-static void setup_frame(int sig, struct k_sigaction *ka,
+static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
- struct sigframe *frame;
+ struct rt_sigframe *frame;
int err = 0;
int signal;
+ unsigned long sp, ra;
- frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
- if (regs->depc > 64)
- {
- printk("!!!!!!! DEPC !!!!!!!\n");
- return;
- }
-
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- signal = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
+ sp = regs->areg[1];
- if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) {
+ sp = current->sas_ss_sp + current->sas_ss_size;
}
- /* Create sys_sigreturn syscall in stack frame */
- err |= gen_return_code(frame->retcode, USE_SIGRETURN);
-
- if (err)
- goto give_sigsegv;
-
- /* Create signal handler execution context.
- * Return context not modified until this point.
- */
- set_thread_state(regs, frame, frame->retcode,
- ka->sa.sa_handler, signal, &frame->sc, NULL);
-
- /* Set access mode to USER_DS. Nomenclature is outdated, but
- * functionality is used in uaccess.h
- */
- set_fs(USER_DS);
-
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
- current->comm, current->pid, signal, frame, regs->pc);
-#endif
-
- return;
-
-give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
-}
-
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe *frame;
- int err = 0;
- int signal;
+ frame = (void *)((sp - sizeof(*frame)) & -16ul);
- frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
if (regs->depc > 64)
panic ("Double exception sys_sigreturn\n");
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
goto give_sigsegv;
+ }
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -602,9 +347,12 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- err |= copy_siginfo_to_user(&frame->info, info);
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, info);
+ }
+
+ /* Create the user context. */
- /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
@@ -617,16 +365,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Create sys_rt_sigreturn syscall in stack frame */
- err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
- if (err)
+ err |= gen_return_code(frame->retcode);
+
+ if (err) {
goto give_sigsegv;
+ }
+
- /* Create signal handler execution context.
+ /*
+ * Create signal handler execution context.
* Return context not modified until this point.
*/
- set_thread_state(regs, frame, frame->retcode,
- ka->sa.sa_handler, signal, &frame->info, &frame->uc);
+
+ /* Set up registers for signal handler */
+ start_thread(regs, (unsigned long) ka->sa.sa_handler,
+ (unsigned long) frame);
+
+ /* Set up a stack frame for a call4
+ * Note: PS.CALLINC is set to one by start_thread
+ */
+ ra = (unsigned long) frame->retcode;
+ regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
+ regs->areg[6] = (unsigned long) signal;
+ regs->areg[7] = (unsigned long) &frame->info;
+ regs->areg[8] = (unsigned long) &frame->uc;
/* Set access mode to USER_DS. Nomenclature is outdated, but
* functionality is used in uaccess.h
@@ -646,6 +409,48 @@ give_sigsegv:
force_sig(SIGSEGV, current);
}
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset,
+ size_t sigsetsize,
+ long a2, long a3, long a4, long a5,
+ struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs->areg[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
+ stack_t __user *uoss,
+ long a2, long a3, long a4, long a5,
+ struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->areg[1]);
+}
+
/*
@@ -663,51 +468,89 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
int signr;
struct k_sigaction ka;
+ if (!user_mode(regs))
+ return 0;
+
+ if (try_to_freeze())
+ goto no_signal;
+
if (!oldset)
oldset = &current->blocked;
+ task_pt_regs(current)->icountlevel = 0;
+
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- /* Are we from a system call? */
- if (regs->syscall >= 0) {
- /* If so, check system call restarting.. */
- switch (regs->areg[2]) {
- case ERESTARTNOHAND:
- case ERESTART_RESTARTBLOCK:
- regs->areg[2] = -EINTR;
- break;
+ if (signr > 0) {
+
+ /* Are we from a system call? */
+
+ if ((signed)regs->syscall >= 0) {
- case ERESTARTSYS:
- if (!(ka.sa.sa_flags & SA_RESTART)) {
+ /* If so, check system call restarting.. */
+
+ switch (regs->areg[2]) {
+ case -ERESTARTNOHAND:
+ case -ERESTART_RESTARTBLOCK:
regs->areg[2] = -EINTR;
break;
- }
- /* fallthrough */
- case ERESTARTNOINTR:
- regs->areg[2] = regs->syscall;
- regs->pc -= 3;
+
+ case -ERESTARTSYS:
+ if (!(ka.sa.sa_flags & SA_RESTART)) {
+ regs->areg[2] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->areg[2] = regs->syscall;
+ regs->pc -= 3;
+ break;
+
+ default:
+ /* nothing to do */
+ if (regs->areg[2] != 0)
+ break;
+ }
}
- }
- if (signr == 0)
- return 0; /* no signals delivered */
+ /* Whee! Actually deliver the signal. */
+ /* Set up the stack frame */
+ setup_frame(signr, &ka, &info, oldset, regs);
- /* Whee! Actually deliver the signal. */
+ if (ka.sa.sa_flags & SA_ONESHOT)
+ ka.sa.sa_handler = SIG_DFL;
- /* Set up the stack frame */
- if (ka.sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(signr, &ka, &info, oldset, regs);
- else
- setup_frame(signr, &ka, oldset, regs);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, signr);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ if (current->ptrace & PT_SINGLESTEP)
+ task_pt_regs(current)->icountlevel = 1;
- if (ka.sa.sa_flags & SA_ONESHOT)
- ka.sa.sa_handler = SIG_DFL;
+ return 1;
+ }
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
- if (!(ka.sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- return 1;
+no_signal:
+ /* Did we come from a system call? */
+ if ((signed) regs->syscall >= 0) {
+ /* Restart the system call - no handlers present */
+ switch (regs->areg[2]) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->areg[2] = regs->syscall;
+ regs->pc -= 3;
+ break;
+ case -ERESTART_RESTARTBLOCK:
+ regs->areg[2] = __NR_restart_syscall;
+ regs->pc -= 3;
+ break;
+ }
+ }
+ if (current->ptrace & PT_SINGLESTEP)
+ task_pt_regs(current)->icountlevel = 1;
+ return 0;
}
+
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 4b7b4ff7997..b0582c3c5f8 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -84,9 +84,7 @@ SECTIONS
{
/* The .head.text section must be the first section! */
*(.head.text)
- *(.literal)
- TEXT_TEXT
- *(.srom.text)
+ *(.literal .text)
VMLINUX_SYMBOL(__sched_text_start) = .;
*(.sched.literal .sched.text)
VMLINUX_SYMBOL(__sched_text_end) = .;
@@ -96,6 +94,7 @@ SECTIONS
}
_etext = .;
+ PROVIDE (etext = .);
. = ALIGN(16);
@@ -103,32 +102,6 @@ SECTIONS
/* Relocation table */
- . = ALIGN(16);
- __boot_reloc_table_start = ABSOLUTE(.);
-
- __relocate : {
-
- RELOCATE_ENTRY(_WindowVectors_text,
- .WindowVectors.text);
-#if 0
- RELOCATE_ENTRY(_KernelExceptionVector_literal,
- .KernelExceptionVector.literal);
-#endif
- RELOCATE_ENTRY(_KernelExceptionVector_text,
- .KernelExceptionVector.text);
-#if 0
- RELOCATE_ENTRY(_UserExceptionVector_literal,
- .UserExceptionVector.literal);
-#endif
- RELOCATE_ENTRY(_UserExceptionVector_text,
- .UserExceptionVector.text);
- RELOCATE_ENTRY(_DoubleExceptionVector_literal,
- .DoubleExceptionVector.literal);
- RELOCATE_ENTRY(_DoubleExceptionVector_text,
- .DoubleExceptionVector.text);
- }
- __boot_reloc_table_end = ABSOLUTE(.) ;
-
.fixup : { *(.fixup) }
. = ALIGN(16);
@@ -145,8 +118,7 @@ SECTIONS
_fdata = .;
.data :
{
- DATA_DATA
- CONSTRUCTORS
+ *(.data) CONSTRUCTORS
. = ALIGN(XCHAL_ICACHE_LINESIZE);
*(.data.cacheline_aligned)
}
@@ -174,6 +146,22 @@ SECTIONS
__tagtable_begin = .;
*(.taglist)
__tagtable_end = .;
+
+ . = ALIGN(16);
+ __boot_reloc_table_start = ABSOLUTE(.);
+
+ RELOCATE_ENTRY(_WindowVectors_text,
+ .WindowVectors.text);
+ RELOCATE_ENTRY(_KernelExceptionVector_text,
+ .KernelExceptionVector.text);
+ RELOCATE_ENTRY(_UserExceptionVector_text,
+ .UserExceptionVector.text);
+ RELOCATE_ENTRY(_DoubleExceptionVector_literal,
+ .DoubleExceptionVector.literal);
+ RELOCATE_ENTRY(_DoubleExceptionVector_text,
+ .DoubleExceptionVector.text);
+
+ __boot_reloc_table_end = ABSOLUTE(.) ;
}
. = ALIGN(XCHAL_ICACHE_LINESIZE);
@@ -194,16 +182,6 @@ SECTIONS
SECURITY_INIT
- . = ALIGN(4);
-
- __start___ftr_fixup = .;
- __ftr_fixup : { *(__ftr_fixup) }
- __stop___ftr_fixup = .;
-
- . = ALIGN(4096);
- __per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
- __per_cpu_end = .;
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(4096);
@@ -212,6 +190,12 @@ SECTIONS
__initramfs_end = .;
#endif
+ . = ALIGN(4096);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+
+
/* We need this dummy segment here */
. = ALIGN(4);
@@ -273,9 +257,9 @@ SECTIONS
/* BSS section */
_bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
- .bss : { *(COMMON) *(.bss) }
+ .bss : { *(.bss.page_aligned) *(.bss) }
_bss_end = .;
+
_end = .;
/* only used by the boot loader */
@@ -293,16 +277,16 @@ SECTIONS
*(.ResetVector.text)
}
-
/* Sections to be discarded */
/DISCARD/ :
{
- *(.text.exit)
- *(.text.exit.literal)
- *(.data.exit)
+ *(.exit.literal .exit.text)
+ *(.exit.data)
*(.exitcall.exit)
}
+ .xt.lit : { *(.xt.lit) }
+ .xt.prop : { *(.xt.prop) }
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index cd7e6a02060..60dbdb43fb4 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -38,21 +38,10 @@
/*
* String functions
*/
-EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
/*
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
index a834057bda6..b2655d94558 100644
--- a/arch/xtensa/lib/strncpy_user.S
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -25,18 +25,18 @@
/*
* char *__strncpy_user(char *dst, const char *src, size_t len)
*/
-.text
-.begin literal
-.align 4
-.Lmask0:
- .byte 0xff, 0x00, 0x00, 0x00
-.Lmask1:
- .byte 0x00, 0xff, 0x00, 0x00
-.Lmask2:
- .byte 0x00, 0x00, 0xff, 0x00
-.Lmask3:
- .byte 0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
# Register use
# a0/ return address
@@ -53,6 +53,7 @@
# a11/ dst
# a12/ tmp
+.text
.align 4
.global __strncpy_user
.type __strncpy_user,@function
@@ -61,10 +62,10 @@ __strncpy_user:
# a2/ dst, a3/ src, a4/ len
mov a11, a2 # leave dst in return value register
beqz a4, .Lret # if len is zero
- l32r a5, .Lmask0 # mask for byte 0
- l32r a6, .Lmask1 # mask for byte 1
- l32r a7, .Lmask2 # mask for byte 2
- l32r a8, .Lmask3 # mask for byte 3
+ movi a5, MASK0 # mask for byte 0
+ movi a6, MASK1 # mask for byte 1
+ movi a7, MASK2 # mask for byte 2
+ movi a8, MASK3 # mask for byte 3
bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned
bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned
.Lsrcaligned: # return here when src is word-aligned
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
index 5e9c1e709b2..ad3f616322c 100644
--- a/arch/xtensa/lib/strnlen_user.S
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -24,18 +24,18 @@
/*
* size_t __strnlen_user(const char *s, size_t len)
*/
-.text
-.begin literal
-.align 4
-.Lmask0:
- .byte 0xff, 0x00, 0x00, 0x00
-.Lmask1:
- .byte 0x00, 0xff, 0x00, 0x00
-.Lmask2:
- .byte 0x00, 0x00, 0xff, 0x00
-.Lmask3:
- .byte 0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
# Register use:
# a2/ src
@@ -48,6 +48,7 @@
# a9/ tmp
# a10/ tmp
+.text
.align 4
.global __strnlen_user
.type __strnlen_user,@function
@@ -56,10 +57,10 @@ __strnlen_user:
# a2/ s, a3/ len
addi a4, a2, -4 # because we overincrement at the end;
# we compensate with load offsets of 4
- l32r a5, .Lmask0 # mask for byte 0
- l32r a6, .Lmask1 # mask for byte 1
- l32r a7, .Lmask2 # mask for byte 2
- l32r a8, .Lmask3 # mask for byte 3
+ movi a5, MASK0 # mask for byte 0
+ movi a6, MASK1 # mask for byte 1
+ movi a7, MASK2 # mask for byte 2
+ movi a8, MASK3 # mask for byte 3
bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned
bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index e1ec2d1e818..8415c76f11c 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -205,7 +205,7 @@ void __init init_mmu (void)
/* Writing zeros to the <t>TLBCFG special registers ensure
* that valid values exist in the register. For existing
* PGSZID<w> fields, zero selects the first element of the
- * page-size array. For nonexistant PGSZID<w> fields, zero is
+ * page-size array. For nonexistent PGSZID<w> fields, zero is
* the best value to write. Also, when changing PGSZID<w>
* fields, the corresponding TLB must be flushed.
*/
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index 4bfe333be22..f09962fa98c 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -473,7 +473,7 @@ static int iss_net_open(struct net_device *dev)
netif_start_queue(dev);
/* clear buffer - it can happen that the host side of the interface
- * is full when we gethere. In this case, new data is never queued,
+ * is full when we get here. In this case, new data is never queued,
* SIGIOs never arrive, and the net never works.
*/
while ((err = iss_net_rx(dev)) > 0)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7baeaffefe7..545f330e59a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -426,6 +426,30 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 4733f009c7c..047eabd7536 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1727,7 +1727,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
/* sanity check */
rc = -EINVAL;
- reason = "device reports illegal type";
+ reason = "device reports invalid type";
if (class == ATA_DEV_ATA) {
if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
@@ -1900,6 +1900,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dump_id(id);
+ /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
+ ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
+ sizeof(fwrevbuf));
+
+ ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
+ sizeof(modelbuf));
+
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) {
@@ -1914,13 +1921,6 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id);
- /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
- ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
- sizeof(fwrevbuf));
-
- ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
- sizeof(modelbuf));
-
if (dev->id[59] & 0x100)
dev->multi_count = dev->id[59] & 0xff;
@@ -2009,7 +2009,9 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
+ ata_dev_printk(dev, KERN_INFO,
+ "ATAPI: %s, %s, max %s%s\n",
+ modelbuf, fwrevbuf,
ata_mode_string(xfer_mask),
cdb_intr_string);
}
@@ -3059,22 +3061,28 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
}
}
- /* if device 1 was found in ata_devchk, wait for
- * register access, then wait for BSY to clear
+ /* if device 1 was found in ata_devchk, wait for register
+ * access briefly, then wait for BSY to clear.
*/
- while (dev1) {
- u8 nsect, lbal;
+ if (dev1) {
+ int i;
ap->ops->dev_select(ap, 1);
- nsect = ioread8(ioaddr->nsect_addr);
- lbal = ioread8(ioaddr->lbal_addr);
- if ((nsect == 1) && (lbal == 1))
- break;
- if (time_after(jiffies, deadline))
- return -EBUSY;
- msleep(50); /* give drive a breather */
- }
- if (dev1) {
+
+ /* Wait for register access. Some ATAPI devices fail
+ * to set nsect/lbal after reset, so don't waste too
+ * much time on it. We're gonna wait for !BSY anyway.
+ */
+ for (i = 0; i < 2; i++) {
+ u8 nsect, lbal;
+
+ nsect = ioread8(ioaddr->nsect_addr);
+ lbal = ioread8(ioaddr->lbal_addr);
+ if ((nsect == 1) && (lbal == 1))
+ break;
+ msleep(50); /* give drive a breather */
+ }
+
rc = ata_wait_ready(ap, deadline);
if (rc) {
if (rc != -ENODEV)
@@ -3769,6 +3777,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
+ { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
@@ -3791,6 +3800,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
+ /* Drives which do spurious command completion */
+ { "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, },
/* Devices with NCQ limits */
@@ -6313,7 +6324,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
- ap->hw_sata_spd_limit &= (1 << spd) - 1;
+ if (spd)
+ ap->hw_sata_spd_limit &= (1 << spd) - 1;
}
ap->sata_spd_limit = ap->hw_sata_spd_limit;
@@ -6433,6 +6445,9 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc)
devm_free_irq(host->dev, irq, host);
+ /* Used to print device info at probe */
+ host->irq = irq;
+
return rc;
}
@@ -6818,6 +6833,7 @@ EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_sff_port_start);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_do_set_mode);
EXPORT_SYMBOL_GPL(ata_data_xfer);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b3900cfbd88..c228df298bd 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1363,12 +1363,22 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache
*/
- if (ap->ops->error_handler &&
- !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
- ((qc->tf.feature == SETFEATURES_WC_ON) ||
- (qc->tf.feature == SETFEATURES_WC_OFF))) {
- ap->eh_info.action |= ATA_EH_REVALIDATE;
- ata_port_schedule_eh(ap);
+ if (ap->ops->error_handler && !need_sense) {
+ switch (qc->tf.command) {
+ case ATA_CMD_SET_FEATURES:
+ if ((qc->tf.feature == SETFEATURES_WC_ON) ||
+ (qc->tf.feature == SETFEATURES_WC_OFF)) {
+ ap->eh_info.action |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ }
+ break;
+
+ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ case ATA_CMD_SET_MULTI: /* multi_count changed */
+ ap->eh_info.action |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ break;
+ }
}
/* For ATA pass thru (SAT) commands, generate a sense block if
@@ -2506,22 +2516,21 @@ ata_scsi_map_proto(u8 byte1)
return ATA_PROT_NODATA;
case 6: /* DMA */
+ case 10: /* UDMA Data-in */
+ case 11: /* UDMA Data-Out */
return ATA_PROT_DMA;
case 4: /* PIO Data-in */
case 5: /* PIO Data-out */
return ATA_PROT_PIO;
- case 10: /* Device Reset */
case 0: /* Hard Reset */
case 1: /* SRST */
- case 2: /* Bus Idle */
- case 7: /* Packet */
- case 8: /* DMA Queued */
- case 9: /* Device Diagnostic */
- case 11: /* UDMA Data-in */
- case 12: /* UDMA Data-Out */
- case 13: /* FPDMA */
+ case 8: /* Device Diagnostic */
+ case 9: /* Device Reset */
+ case 7: /* DMA Queued */
+ case 12: /* FPDMA */
+ case 15: /* Return Response Info */
default: /* Reserved */
break;
}
@@ -2552,10 +2561,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
- if (cdb[1] & 0xe0)
- /* PIO multi not supported yet */
- goto invalid_fld;
-
/*
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
@@ -2600,12 +2605,26 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->device = cdb[8];
tf->command = cdb[9];
}
- /*
- * If slave is possible, enforce correct master/slave bit
- */
- if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
- tf->device = qc->dev->devno ?
- tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+ /* enforce correct master/slave bit */
+ tf->device = dev->devno ?
+ tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+ /* sanity check for pio multi commands */
+ if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
+ goto invalid_fld;
+
+ if (is_multi_taskfile(tf)) {
+ unsigned int multi_count = 1 << (cdb[1] >> 5);
+
+ /* compare the passed through multi_count
+ * with the cached multi_count of libata
+ */
+ if (multi_count != dev->multi_count)
+ ata_dev_printk(dev, KERN_WARNING,
+ "invalid multi_count %u ignored\n",
+ multi_count);
+ }
/* READ/WRITE LONG use a non-standard sect_size */
qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e35d13466c6..ce84805ba5f 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; }
u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
- u8 host_stat, post_stat, status;
+ u8 host_stat = 0, post_stat = 0, status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
- /* get controller status; clear intr, err bits */
- host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
- ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
- post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ if (ap->ioaddr.bmdma_addr) {
+ /* get controller status; clear intr, err bits */
+ host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+ ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
-
return status;
}
@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
ata_bmdma_stop(qc);
}
+/**
+ * ata_sff_port_start - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates space for PRD table if the device
+ * is DMA capable SFF.
+ *
+ * May be used as the port_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+int ata_sff_port_start(struct ata_port *ap)
+{
+ if (ap->ioaddr.bmdma_addr)
+ return ata_port_start(ap);
+ return 0;
+}
+
#ifdef CONFIG_PCI
static int ata_resources_present(struct pci_dev *pdev, int port)
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 1f647b64820..5525518204e 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -77,7 +77,6 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
struct ata_host *host;
struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
- int rc;
if (pnp_port_valid(idev, 0) == 0)
return -ENODEV;
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 2b924a69b36..6dc0b011a6b 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -784,9 +784,12 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
+ case ATA_PROT_NODATA:
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ break;
+ /*FALLTHROUGH*/
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_DMA:
- case ATA_PROT_NODATA:
pdc_packet_start(qc);
return 0;
@@ -800,7 +803,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_tf_load(ap, tf);
}
@@ -808,7 +811,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_exec_command(ap, tf);
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 20c4ea6eb50..8c506dbe391 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -369,36 +369,6 @@ char *make_class_name(const char *name, struct kobject *kobj)
return class_name;
}
-static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size,
- int *cur_len,
- struct class_device *class_dev)
-{
- struct device *dev = class_dev->dev;
- char *path;
-
- if (!dev)
- return 0;
-
- /* add device, backing this class device (deprecated) */
- path = kobject_get_path(&dev->kobj, GFP_KERNEL);
-
- add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
- cur_len, "PHYSDEVPATH=%s", path);
- kfree(path);
-
- if (dev->bus)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVBUS=%s", dev->bus->name);
-
- if (dev->driver)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVDRIVER=%s", dev->driver->name);
- return 0;
-}
-
static int make_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
@@ -430,11 +400,6 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev)
kfree(class_name);
}
#else
-static inline int deprecated_class_uevent(char **envp, int num_envp,
- int *cur_index, char *buffer,
- int buffer_size, int *cur_len,
- struct class_device *class_dev)
-{ return 0; }
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
@@ -445,15 +410,13 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
+ struct device *dev = class_dev->dev;
int i = 0;
int length = 0;
int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
- deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
- &length, class_dev);
-
if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
@@ -464,6 +427,26 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
"MINOR=%u", MINOR(class_dev->devt));
}
+ if (dev) {
+ const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
+
+ if (dev->bus)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
+
+ if (dev->driver)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
+ }
+
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
envp = &envp[i];
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b78fc1e6826..dd40d78a023 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -180,10 +180,12 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
const char *path;
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
- add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVPATH=%s", path);
- kfree(path);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 92428e55b0c..b0088b0efec 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -207,19 +207,6 @@ static int __device_attach(struct device_driver * drv, void * data)
return driver_probe_device(drv, dev);
}
-static int device_probe_drivers(void *data)
-{
- struct device *dev = data;
- int ret = 0;
-
- if (dev->bus) {
- down(&dev->sem);
- ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
- up(&dev->sem);
- }
- return ret;
-}
-
/**
* device_attach - try to attach device to a driver.
* @dev: device.
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 97ab5bd1c4d..89a5f4a5491 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_class.c - Multi purpose firmware loading support
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Please see Documentation/firmware_class/ for more information.
*
@@ -23,7 +23,7 @@
#define to_dev(obj) container_of(obj, struct device, kobj)
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5526eadb659..0ed5470d253 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1354,7 +1354,7 @@ static struct block_device_operations lo_fops = {
*/
static int max_loop;
module_param(max_loop, int, 0);
-MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -1394,16 +1394,11 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-static struct loop_device *loop_init_one(int i)
+static struct loop_device *loop_alloc(int i)
{
struct loop_device *lo;
struct gendisk *disk;
- list_for_each_entry(lo, &loop_devices, lo_list) {
- if (lo->lo_number == i)
- return lo;
- }
-
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo)
goto out;
@@ -1427,8 +1422,6 @@ static struct loop_device *loop_init_one(int i)
disk->private_data = lo;
disk->queue = lo->lo_queue;
sprintf(disk->disk_name, "loop%d", i);
- add_disk(disk);
- list_add_tail(&lo->lo_list, &loop_devices);
return lo;
out_free_queue:
@@ -1439,15 +1432,37 @@ out:
return NULL;
}
-static void loop_del_one(struct loop_device *lo)
+static void loop_free(struct loop_device *lo)
{
- del_gendisk(lo->lo_disk);
blk_cleanup_queue(lo->lo_queue);
put_disk(lo->lo_disk);
list_del(&lo->lo_list);
kfree(lo);
}
+static struct loop_device *loop_init_one(int i)
+{
+ struct loop_device *lo;
+
+ list_for_each_entry(lo, &loop_devices, lo_list) {
+ if (lo->lo_number == i)
+ return lo;
+ }
+
+ lo = loop_alloc(i);
+ if (lo) {
+ add_disk(lo->lo_disk);
+ list_add_tail(&lo->lo_list, &loop_devices);
+ }
+ return lo;
+}
+
+static void loop_del_one(struct loop_device *lo)
+{
+ del_gendisk(lo->lo_disk);
+ loop_free(lo);
+}
+
static struct kobject *loop_probe(dev_t dev, int *part, void *data)
{
struct loop_device *lo;
@@ -1464,28 +1479,77 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
static int __init loop_init(void)
{
- if (register_blkdev(LOOP_MAJOR, "loop"))
- return -EIO;
- blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
- THIS_MODULE, loop_probe, NULL, NULL);
+ int i, nr;
+ unsigned long range;
+ struct loop_device *lo, *next;
+
+ /*
+ * loop module now has a feature to instantiate underlying device
+ * structure on-demand, provided that there is an access dev node.
+ * However, this will not work well with user space tool that doesn't
+ * know about such "feature". In order to not break any existing
+ * tool, we do the following:
+ *
+ * (1) if max_loop is specified, create that many upfront, and this
+ * also becomes a hard limit.
+ * (2) if max_loop is not specified, create 8 loop device on module
+ * load, user can further extend loop device by create dev node
+ * themselves and have kernel automatically instantiate actual
+ * device on-demand.
+ */
+ if (max_loop > 1UL << MINORBITS)
+ return -EINVAL;
if (max_loop) {
- printk(KERN_INFO "loop: the max_loop option is obsolete "
- "and will be removed in March 2008\n");
+ nr = max_loop;
+ range = max_loop;
+ } else {
+ nr = 8;
+ range = 1UL << MINORBITS;
+ }
+
+ if (register_blkdev(LOOP_MAJOR, "loop"))
+ return -EIO;
+ for (i = 0; i < nr; i++) {
+ lo = loop_alloc(i);
+ if (!lo)
+ goto Enomem;
+ list_add_tail(&lo->lo_list, &loop_devices);
}
+
+ /* point of no return */
+
+ list_for_each_entry(lo, &loop_devices, lo_list)
+ add_disk(lo->lo_disk);
+
+ blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
+ THIS_MODULE, loop_probe, NULL, NULL);
+
printk(KERN_INFO "loop: module loaded\n");
return 0;
+
+Enomem:
+ printk(KERN_INFO "loop: out of memory\n");
+
+ list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ loop_free(lo);
+
+ unregister_blkdev(LOOP_MAJOR, "loop");
+ return -ENOMEM;
}
static void __exit loop_exit(void)
{
+ unsigned long range;
struct loop_device *lo, *next;
+ range = max_loop ? max_loop : 1UL << MINORBITS;
+
list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
loop_del_one(lo);
- blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
+ blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
if (unregister_blkdev(LOOP_MAJOR, "loop"))
printk(KERN_WARNING "loop: cannot unregister blkdev\n");
}
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index f574962f428..4310cc84dfe 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1053,11 +1053,11 @@ static void __exit mcdx_exit(void)
if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
xwarn("cleanup() unregister_blkdev() failed\n");
}
- blk_cleanup_queue(mcdx_queue);
#if !MCDX_QUIET
else
xinfo("cleanup() succeeded\n");
#endif
+ blk_cleanup_queue(mcdx_queue);
}
#ifdef MODULE
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index fdbca25a394..35ab1a9f8e8 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -176,7 +176,7 @@ struct agp_bridge_data {
#define I830_GMCH_MEM_MASK 0x1
#define I830_GMCH_MEM_64M 0x1
#define I830_GMCH_MEM_128M 0
-#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_MASK 0xF0
#define I830_GMCH_GMS_DISABLED 0x00
#define I830_GMCH_GMS_LOCAL 0x10
#define I830_GMCH_GMS_STOLEN_512 0x20
@@ -231,6 +231,10 @@ struct agp_bridge_data {
#define I965_PGETBL_SIZE_512KB (0 << 1)
#define I965_PGETBL_SIZE_256KB (1 << 1)
#define I965_PGETBL_SIZE_128KB (2 << 1)
+#define G33_PGETBL_SIZE_MASK (3 << 8)
+#define G33_PGETBL_SIZE_1M (1 << 8)
+#define G33_PGETBL_SIZE_2M (2 << 8)
+
#define I810_DRAM_CTL 0x3000
#define I810_DRAM_ROW_0 0x00000001
#define I810_DRAM_ROW_0_SDRAM 0x00000001
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 9c69f2e761f..d383168b75f 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -20,6 +20,14 @@
#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
+#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
+#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
+#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
+#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
+#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
+#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
+#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
+#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
@@ -27,6 +35,9 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
+#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB)
extern int agp_memory_reserved;
@@ -53,6 +64,8 @@ extern int agp_memory_reserved;
#define I915_PTEADDR 0x1C
#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
/* Intel 965G registers */
#define I965_MSAC 0x62
@@ -86,11 +99,18 @@ static struct gatt_mask intel_i810_masks[] =
.type = INTEL_AGP_CACHED_MEMORY}
};
-static struct _intel_i810_private {
- struct pci_dev *i810_dev; /* device one */
- volatile u8 __iomem *registers;
+static struct _intel_private {
+ struct pci_dev *pcidev; /* device one */
+ u8 __iomem *registers;
+ u32 __iomem *gtt; /* I915G */
int num_dcache_entries;
-} intel_i810_private;
+ /* gtt_entries is the number of gtt entries that are already mapped
+ * to stolen memory. Stolen memory is larger than the memory mapped
+ * through gtt_entries, as it includes some reserved space for the BIOS
+ * popup and for the GTT.
+ */
+ int gtt_entries; /* i830+ */
+} intel_private;
static int intel_i810_fetch_size(void)
{
@@ -127,32 +147,32 @@ static int intel_i810_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- if (!intel_i810_private.registers) {
- pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+ if (!intel_private.registers) {
+ pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
temp &= 0xfff80000;
- intel_i810_private.registers = ioremap(temp, 128 * 4096);
- if (!intel_i810_private.registers) {
+ intel_private.registers = ioremap(temp, 128 * 4096);
+ if (!intel_private.registers) {
printk(KERN_ERR PFX "Unable to remap memory.\n");
return -ENOMEM;
}
}
- if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
+ if ((readl(intel_private.registers+I810_DRAM_CTL)
& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
/* This will need to be dynamically assigned */
printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
- intel_i810_private.num_dcache_entries = 1024;
+ intel_private.num_dcache_entries = 1024;
}
- pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
for (i = 0; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+ readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
}
}
global_cache_flush();
@@ -161,9 +181,9 @@ static int intel_i810_configure(void)
static void intel_i810_cleanup(void)
{
- writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers); /* PCI Posting. */
- iounmap(intel_i810_private.registers);
+ writel(0, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers); /* PCI Posting. */
+ iounmap(intel_private.registers);
}
static void intel_i810_tlbflush(struct agp_memory *mem)
@@ -261,9 +281,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
global_cache_flush();
for (i = pg_start; i < (pg_start + mem->page_count); i++) {
writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
- intel_i810_private.registers+I810_PTE_BASE+(i*4));
+ intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
break;
case AGP_PHYS_MEMORY:
case AGP_NORMAL_MEMORY:
@@ -273,9 +293,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i],
mask_type),
- intel_i810_private.registers+I810_PTE_BASE+(j*4));
+ intel_private.registers+I810_PTE_BASE+(j*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
break;
default:
goto out_err;
@@ -298,9 +318,9 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
return 0;
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -354,7 +374,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
struct agp_memory *new;
if (type == AGP_DCACHE_MEMORY) {
- if (pg_count != intel_i810_private.num_dcache_entries)
+ if (pg_count != intel_private.num_dcache_entries)
return NULL;
new = agp_create_memory(1);
@@ -404,18 +424,6 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
{512, 131072, 7},
};
-static struct _intel_i830_private {
- struct pci_dev *i830_dev; /* device one */
- volatile u8 __iomem *registers;
- volatile u32 __iomem *gtt; /* I915G */
- /* gtt_entries is the number of gtt entries that are already mapped
- * to stolen memory. Stolen memory is larger than the memory mapped
- * through gtt_entries, as it includes some reserved space for the BIOS
- * popup and for the GTT.
- */
- int gtt_entries;
-} intel_i830_private;
-
static void intel_i830_init_gtt_entries(void)
{
u16 gmch_ctrl;
@@ -429,7 +437,7 @@ static void intel_i830_init_gtt_entries(void)
if (IS_I965) {
u32 pgetbl_ctl;
- pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL);
+ pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
/* The 965 has a field telling us the size of the GTT,
* which may be larger than what is necessary to map the
@@ -451,6 +459,22 @@ static void intel_i830_init_gtt_entries(void)
size = 512;
}
size += 4; /* add in BIOS popup space */
+ } else if (IS_G33) {
+ /* G33's GTT size defined in gmch_ctrl */
+ switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+ case G33_PGETBL_SIZE_1M:
+ size = 1024;
+ break;
+ case G33_PGETBL_SIZE_2M:
+ size = 2048;
+ break;
+ default:
+ printk(KERN_INFO PFX "Unknown page table size 0x%x, "
+ "assuming 512KB\n",
+ (gmch_ctrl & G33_PGETBL_SIZE_MASK));
+ size = 512;
+ }
+ size += 4;
} else {
/* On previous hardware, the GTT size was just what was
* required to map the aperture.
@@ -471,7 +495,7 @@ static void intel_i830_init_gtt_entries(void)
gtt_entries = MB(8) - KB(size);
break;
case I830_GMCH_GMS_LOCAL:
- rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
+ rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
MB(ddt[I830_RDRAM_DDT(rdct)]);
local = 1;
@@ -502,7 +526,8 @@ static void intel_i830_init_gtt_entries(void)
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+ IS_I965 || IS_G33)
gtt_entries = MB(48) - KB(size);
else
gtt_entries = 0;
@@ -512,10 +537,24 @@ static void intel_i830_init_gtt_entries(void)
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+ IS_I965 || IS_G33)
gtt_entries = MB(64) - KB(size);
else
gtt_entries = 0;
+ break;
+ case G33_GMCH_GMS_STOLEN_128M:
+ if (IS_G33)
+ gtt_entries = MB(128) - KB(size);
+ else
+ gtt_entries = 0;
+ break;
+ case G33_GMCH_GMS_STOLEN_256M:
+ if (IS_G33)
+ gtt_entries = MB(256) - KB(size);
+ else
+ gtt_entries = 0;
+ break;
default:
gtt_entries = 0;
break;
@@ -529,7 +568,7 @@ static void intel_i830_init_gtt_entries(void)
"No pre-allocated video memory detected.\n");
gtt_entries /= KB(4);
- intel_i830_private.gtt_entries = gtt_entries;
+ intel_private.gtt_entries = gtt_entries;
}
/* The intel i830 automatically initializes the agp aperture during POST.
@@ -547,14 +586,14 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
+ pci_read_config_dword(intel_private.pcidev,I810_MMADDR,&temp);
temp &= 0xfff80000;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ?? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -614,20 +653,20 @@ static int intel_i830_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
+ pci_read_config_dword(intel_private.pcidev,I810_GMADDR,&temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
gmch_ctrl |= I830_GMCH_ENABLED;
pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
+ for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+ readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
}
@@ -637,7 +676,7 @@ static int intel_i830_configure(void)
static void intel_i830_cleanup(void)
{
- iounmap(intel_i830_private.registers);
+ iounmap(intel_private.registers);
}
static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
@@ -653,9 +692,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
+ if (pg_start < intel_private.gtt_entries) {
+ printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+ pg_start,intel_private.gtt_entries);
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
goto out_err;
@@ -683,9 +722,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mask_type),
- intel_i830_private.registers+I810_PTE_BASE+(j*4));
+ intel_private.registers+I810_PTE_BASE+(j*4));
}
- readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
agp_bridge->driver->tlb_flush(mem);
out:
@@ -703,15 +742,15 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
if (mem->page_count == 0)
return 0;
- if (pg_start < intel_i830_private.gtt_entries) {
+ if (pg_start < intel_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
return -EINVAL;
}
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -734,7 +773,7 @@ static int intel_i915_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
@@ -742,13 +781,13 @@ static int intel_i915_configure(void)
gmch_ctrl |= I830_GMCH_ENABLED;
pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i); /* PCI Posting. */
+ for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+ writel(agp_bridge->scratch_page, intel_private.gtt+i);
+ readl(intel_private.gtt+i); /* PCI Posting. */
}
}
@@ -758,8 +797,8 @@ static int intel_i915_configure(void)
static void intel_i915_cleanup(void)
{
- iounmap(intel_i830_private.gtt);
- iounmap(intel_i830_private.registers);
+ iounmap(intel_private.gtt);
+ iounmap(intel_private.registers);
}
static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -776,9 +815,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
+ if (pg_start < intel_private.gtt_entries) {
+ printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+ pg_start,intel_private.gtt_entries);
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
goto out_err;
@@ -805,10 +844,10 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mask_type), intel_i830_private.gtt+j);
+ mem->memory[i], mask_type), intel_private.gtt+j);
}
- readl(intel_i830_private.gtt+j-1);
+ readl(intel_private.gtt+j-1);
agp_bridge->driver->tlb_flush(mem);
out:
@@ -826,15 +865,15 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
if (mem->page_count == 0)
return 0;
- if (pg_start < intel_i830_private.gtt_entries) {
+ if (pg_start < intel_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
return -EINVAL;
}
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
+ writel(agp_bridge->scratch_page, intel_private.gtt+i);
}
- readl(intel_i830_private.gtt+i-1);
+ readl(intel_private.gtt+i-1);
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -850,7 +889,7 @@ static int intel_i9xx_fetch_size(void)
int aper_size; /* size in megabytes */
int i;
- aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
+ aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
for (i = 0; i < num_sizes; i++) {
if (aper_size == intel_i830_sizes[i].size) {
@@ -878,20 +917,20 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
+ pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
- intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
- if (!intel_i830_private.gtt)
+ intel_private.gtt = ioremap(temp2, 256 * 1024);
+ if (!intel_private.gtt)
return -ENOMEM;
temp &= 0xfff80000;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -938,20 +977,20 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
temp &= 0xfff00000;
- intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
+ intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
- if (!intel_i830_private.gtt)
+ if (!intel_private.gtt)
return -ENOMEM;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -1722,41 +1761,126 @@ static const struct agp_bridge_driver intel_7505_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static int find_i810(u16 device)
-{
- struct pci_dev *i810_dev;
-
- i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (!i810_dev)
- return 0;
- intel_i810_private.i810_dev = i810_dev;
- return 1;
-}
+static const struct agp_bridge_driver intel_g33_driver = {
+ .owner = THIS_MODULE,
+ .aperture_sizes = intel_i830_sizes,
+ .size_type = FIXED_APER_SIZE,
+ .num_aperture_sizes = 4,
+ .needs_scratch_page = TRUE,
+ .configure = intel_i915_configure,
+ .fetch_size = intel_i9xx_fetch_size,
+ .cleanup = intel_i915_cleanup,
+ .tlb_flush = intel_i810_tlbflush,
+ .mask_memory = intel_i965_mask_memory,
+ .masks = intel_i810_masks,
+ .agp_enable = intel_i810_agp_enable,
+ .cache_flush = global_cache_flush,
+ .create_gatt_table = intel_i915_create_gatt_table,
+ .free_gatt_table = intel_i830_free_gatt_table,
+ .insert_memory = intel_i915_insert_entries,
+ .remove_memory = intel_i915_remove_entries,
+ .alloc_by_type = intel_i830_alloc_by_type,
+ .free_by_type = intel_i810_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .agp_type_to_mask_type = intel_i830_type_to_mask_type,
+};
-static int find_i830(u16 device)
+static int find_gmch(u16 device)
{
- struct pci_dev *i830_dev;
+ struct pci_dev *gmch_device;
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- device, i830_dev);
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+ if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+ device, gmch_device);
}
- if (!i830_dev)
+ if (!gmch_device)
return 0;
- intel_i830_private.i830_dev = i830_dev;
+ intel_private.pcidev = gmch_device;
return 1;
}
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_driver_description {
+ unsigned int chip_id;
+ unsigned int gmch_chip_id;
+ char *name;
+ const struct agp_bridge_driver *driver;
+ const struct agp_bridge_driver *gmch_driver;
+} intel_agp_chipsets[] = {
+ { PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815",
+ &intel_810_driver, &intel_815_driver },
+ { PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
+ &intel_830mp_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, "855PM", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82860_HB, 0, "i860", &intel_860_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, "865",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82875_HB, 0, "i875", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
+ &intel_845_driver, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
+ &intel_845_driver, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
+ &intel_845_driver, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
+ &intel_845_driver, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
+ &intel_845_driver, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_1_HB, PCI_DEVICE_ID_INTEL_82965G_1_IG, "965G",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
+ &intel_845_driver, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_7505_0, 0, "E7505", &intel_7505_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_7205_0, 0, "E7205", &intel_7505_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, "G33",
+ &intel_845_driver, &intel_g33_driver },
+ { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
+ &intel_845_driver, &intel_g33_driver },
+ { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
+ &intel_845_driver, &intel_g33_driver },
+ { 0, 0, NULL, NULL, NULL }
+};
+
static int __devinit agp_intel_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
- char *name = "(unknown)";
u8 cap_ptr = 0;
struct resource *r;
+ int i;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
@@ -1764,195 +1888,42 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
if (!bridge)
return -ENOMEM;
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_82443LX_0:
- bridge->driver = &intel_generic_driver;
- name = "440LX";
- break;
- case PCI_DEVICE_ID_INTEL_82443BX_0:
- bridge->driver = &intel_generic_driver;
- name = "440BX";
- break;
- case PCI_DEVICE_ID_INTEL_82443GX_0:
- bridge->driver = &intel_generic_driver;
- name = "440GX";
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC1:
- name = "i810";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC3:
- name = "i810 DC100";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810E_MC:
- name = "i810 E";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82815_MC:
- /*
- * The i815 can operate either as an i810 style
- * integrated device, or as an AGP4X motherboard.
- */
- if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
- bridge->driver = &intel_810_driver;
- else
- bridge->driver = &intel_815_driver;
- name = "i815";
- break;
- case PCI_DEVICE_ID_INTEL_82820_HB:
- case PCI_DEVICE_ID_INTEL_82820_UP_HB:
- bridge->driver = &intel_820_driver;
- name = "i820";
- break;
- case PCI_DEVICE_ID_INTEL_82830_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_830mp_driver;
- name = "830M";
- break;
- case PCI_DEVICE_ID_INTEL_82840_HB:
- bridge->driver = &intel_840_driver;
- name = "i840";
- break;
- case PCI_DEVICE_ID_INTEL_82845_HB:
- bridge->driver = &intel_845_driver;
- name = "i845";
- break;
- case PCI_DEVICE_ID_INTEL_82845G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "845G";
- break;
- case PCI_DEVICE_ID_INTEL_82850_HB:
- bridge->driver = &intel_850_driver;
- name = "i850";
- break;
- case PCI_DEVICE_ID_INTEL_82855PM_HB:
- bridge->driver = &intel_845_driver;
- name = "855PM";
- break;
- case PCI_DEVICE_ID_INTEL_82855GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
- bridge->driver = &intel_830_driver;
- name = "855";
- } else {
- bridge->driver = &intel_845_driver;
- name = "855GM";
- }
- break;
- case PCI_DEVICE_ID_INTEL_82860_HB:
- bridge->driver = &intel_860_driver;
- name = "i860";
- break;
- case PCI_DEVICE_ID_INTEL_82865_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "865";
- break;
- case PCI_DEVICE_ID_INTEL_82875_HB:
- bridge->driver = &intel_845_driver;
- name = "i875";
- break;
- case PCI_DEVICE_ID_INTEL_82915G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "915G";
- break;
- case PCI_DEVICE_ID_INTEL_82915GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "915GM";
- break;
- case PCI_DEVICE_ID_INTEL_82945G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "945G";
- break;
- case PCI_DEVICE_ID_INTEL_82945GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "945GM";
- break;
- case PCI_DEVICE_ID_INTEL_82946GZ_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "946GZ";
- break;
- case PCI_DEVICE_ID_INTEL_82965G_1_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965G";
- break;
- case PCI_DEVICE_ID_INTEL_82965Q_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965Q";
- break;
- case PCI_DEVICE_ID_INTEL_82965G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965G";
- break;
- case PCI_DEVICE_ID_INTEL_82965GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965GM";
- break;
- case PCI_DEVICE_ID_INTEL_7505_0:
- bridge->driver = &intel_7505_driver;
- name = "E7505";
- break;
- case PCI_DEVICE_ID_INTEL_7205_0:
- bridge->driver = &intel_7505_driver;
- name = "E7205";
- break;
- default:
+ for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
+ /* In case that multiple models of gfx chip may
+ stand on same host bridge type, this can be
+ sure we detect the right IGD. */
+ if ((pdev->device == intel_agp_chipsets[i].chip_id) &&
+ ((intel_agp_chipsets[i].gmch_chip_id == 0) ||
+ find_gmch(intel_agp_chipsets[i].gmch_chip_id)))
+ break;
+ }
+
+ if (intel_agp_chipsets[i].name == NULL) {
if (cap_ptr)
- printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
- pdev->device);
+ printk(KERN_WARNING PFX "Unsupported Intel chipset"
+ "(device id: %04x)\n", pdev->device);
agp_put_bridge(bridge);
return -ENODEV;
- };
+ }
+
+ if (intel_agp_chipsets[i].gmch_chip_id != 0)
+ bridge->driver = intel_agp_chipsets[i].gmch_driver;
+ else
+ bridge->driver = intel_agp_chipsets[i].driver;
+
+ if (bridge->driver == NULL) {
+ printk(KERN_WARNING PFX "Failed to find bridge device "
+ "(chip_id: %04x)\n", intel_agp_chipsets[i].gmch_chip_id);
+ agp_put_bridge(bridge);
+ return -ENODEV;
+ }
bridge->dev = pdev;
bridge->capndx = cap_ptr;
+ bridge->dev_private_data = &intel_private;
- if (bridge->driver == &intel_810_driver)
- bridge->dev_private_data = &intel_i810_private;
- else if (bridge->driver == &intel_830_driver)
- bridge->dev_private_data = &intel_i830_private;
-
- printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
+ printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n",
+ intel_agp_chipsets[i].name);
/*
* The following fixes the case where the BIOS has "forgotten" to
@@ -1988,12 +1959,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
-
-fail:
- printk(KERN_ERR PFX "Detected an Intel %s chipset, "
- "but could not find the secondary device.\n", name);
- agp_put_bridge(bridge);
- return -ENODEV;
}
static void __devexit agp_intel_remove(struct pci_dev *pdev)
@@ -2002,10 +1967,8 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_remove_bridge(bridge);
- if (intel_i810_private.i810_dev)
- pci_dev_put(intel_i810_private.i810_dev);
- if (intel_i830_private.i830_dev)
- pci_dev_put(intel_i830_private.i830_dev);
+ if (intel_private.pcidev)
+ pci_dev_put(intel_private.pcidev);
agp_put_bridge(bridge);
}
@@ -2021,10 +1984,8 @@ static int agp_intel_resume(struct pci_dev *pdev)
* as host bridge (00:00) resumes before graphics device (02:00),
* then our access to its pci space can work right.
*/
- if (intel_i810_private.i810_dev)
- pci_restore_state(intel_i810_private.i810_dev);
- if (intel_i830_private.i830_dev)
- pci_restore_state(intel_i830_private.i830_dev);
+ if (intel_private.pcidev)
+ pci_restore_state(intel_private.pcidev);
if (bridge->driver == &intel_generic_driver)
intel_configure();
@@ -2087,6 +2048,9 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
ID(PCI_DEVICE_ID_INTEL_82965G_HB),
ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_G33_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q33_HB),
{ }
};
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index e45113a7a47..45bf2a262a8 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2172,11 +2172,12 @@ static int __devinit stl_initech(struct stlbrd *brdp)
}
status = inb(ioaddr + ECH_PNLSTATUS);
if ((status & ECH_PNLIDMASK) != nxtid)
- goto err_fr;
+ break;
panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
if (!panelp) {
printk("STALLION: failed to allocate memory "
"(size=%Zd)\n", sizeof(struct stlpanel));
+ retval = -ENOMEM;
goto err_fr;
}
panelp->magic = STL_PANELMAGIC;
@@ -2223,8 +2224,10 @@ static int __devinit stl_initech(struct stlbrd *brdp)
brdp->nrports += panelp->nrports;
brdp->panels[panelnr++] = panelp;
if ((brdp->brdtype != BRD_ECHPCI) &&
- (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
+ (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
+ retval = -EINVAL;
goto err_fr;
+ }
}
brdp->nrpanels = panelnr;
@@ -2371,6 +2374,7 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev,
dev_err(&pdev->dev, "too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
mutex_unlock(&stl_brdslock);
+ retval = -ENODEV;
goto err_fr;
}
brdp->brdnr = (unsigned int)brdnr;
@@ -4710,6 +4714,29 @@ static int __init stallion_module_init(void)
spin_lock_init(&stallion_lock);
spin_lock_init(&brd_lock);
+ stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stl_serial) {
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ stl_serial->owner = THIS_MODULE;
+ stl_serial->driver_name = stl_drvname;
+ stl_serial->name = "ttyE";
+ stl_serial->major = STL_SERIALMAJOR;
+ stl_serial->minor_start = 0;
+ stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+ stl_serial->subtype = SERIAL_TYPE_NORMAL;
+ stl_serial->init_termios = stl_deftermios;
+ stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(stl_serial, &stl_ops);
+
+ retval = tty_register_driver(stl_serial);
+ if (retval) {
+ printk("STALLION: failed to register serial driver\n");
+ goto err_frtty;
+ }
+
/*
* Find any dynamically supported boards. That is via module load
* line options.
@@ -4739,13 +4766,9 @@ static int __init stallion_module_init(void)
/* this has to be _after_ isa finding because of locking */
retval = pci_register_driver(&stl_pcidriver);
- if (retval && stl_nrbrds == 0)
- goto err;
-
- stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stl_serial) {
- retval = -ENOMEM;
- goto err_pcidr;
+ if (retval && stl_nrbrds == 0) {
+ printk(KERN_ERR "STALLION: can't register pci driver\n");
+ goto err_unrtty;
}
/*
@@ -4756,43 +4779,18 @@ static int __init stallion_module_init(void)
printk("STALLION: failed to register serial board device\n");
stallion_class = class_create(THIS_MODULE, "staliomem");
- if (IS_ERR(stallion_class)) {
- retval = PTR_ERR(stallion_class);
- goto err_reg;
- }
+ if (IS_ERR(stallion_class))
+ printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
class_device_create(stallion_class, NULL,
MKDEV(STL_SIOMEMMAJOR, i), NULL,
"staliomem%d", i);
- stl_serial->owner = THIS_MODULE;
- stl_serial->driver_name = stl_drvname;
- stl_serial->name = "ttyE";
- stl_serial->major = STL_SERIALMAJOR;
- stl_serial->minor_start = 0;
- stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
- stl_serial->subtype = SERIAL_TYPE_NORMAL;
- stl_serial->init_termios = stl_deftermios;
- stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(stl_serial, &stl_ops);
-
- retval = tty_register_driver(stl_serial);
- if (retval) {
- printk("STALLION: failed to register serial driver\n");
- goto err_clsdev;
- }
-
return 0;
-err_clsdev:
- for (i = 0; i < 4; i++)
- class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
- class_destroy(stallion_class);
-err_reg:
- unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+err_unrtty:
+ tty_unregister_driver(stl_serial);
+err_frtty:
put_tty_driver(stl_serial);
-err_pcidr:
- pci_unregister_driver(&stl_pcidriver);
- stl_free_isabrds();
err:
return retval;
}
@@ -4821,8 +4819,6 @@ static void __exit stallion_module_exit(void)
tty_unregister_device(stl_serial,
brdp->brdnr * STL_MAXPORTS + j);
}
- tty_unregister_driver(stl_serial);
- put_tty_driver(stl_serial);
for (i = 0; i < 4; i++)
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
@@ -4834,6 +4830,9 @@ static void __exit stallion_module_exit(void)
pci_unregister_driver(&stl_pcidriver);
stl_free_isabrds();
+
+ tty_unregister_driver(stl_serial);
+ put_tty_driver(stl_serial);
}
module_init(stallion_module_init);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7fff773f2df..dc2175c81f5 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1037,6 +1037,17 @@ static void ide_disk_release(struct kref *kref)
static int ide_disk_probe(ide_drive_t *drive);
+/*
+ * On HPA drives the capacity needs to be
+ * reinitilized on resume otherwise the disk
+ * can not be used and a hard reset is required
+ */
+static void ide_disk_resume(ide_drive_t *drive)
+{
+ if (idedisk_supports_hpa(drive->id))
+ init_idedisk_capacity(drive);
+}
+
static void ide_device_shutdown(ide_drive_t *drive)
{
#ifdef CONFIG_ALPHA
@@ -1071,6 +1082,7 @@ static ide_driver_t idedisk_driver = {
},
.probe = ide_disk_probe,
.remove = ide_disk_remove,
+ .resume = ide_disk_resume,
.shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
.media = ide_disk,
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 3cebed77f55..41bfa4d21ab 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -717,7 +717,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
* This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/
-static void probe_hwif(ide_hwif_t *hwif)
+static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{
unsigned int unit;
unsigned long flags;
@@ -820,6 +820,9 @@ static void probe_hwif(ide_hwif_t *hwif)
return;
}
+ if (fixup)
+ fixup(hwif);
+
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
@@ -874,10 +877,7 @@ static int hwif_init(ide_hwif_t *hwif);
int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{
- probe_hwif(hwif);
-
- if (fixup)
- fixup(hwif);
+ probe_hwif(hwif, fixup);
if (!hwif_init(hwif)) {
printk(KERN_INFO "%s: failed to initialize IDE interface\n",
@@ -1404,7 +1404,7 @@ int ideprobe_init (void)
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
- probe_hwif(&ide_hwifs[index]);
+ probe_hwif(&ide_hwifs[index], NULL);
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
hwif_init(&ide_hwifs[index]);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6002713a20a..0af0d1614f7 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1010,9 +1010,11 @@ static int generic_ide_resume(struct device *dev)
{
ide_drive_t *drive = dev->driver_data;
ide_hwif_t *hwif = HWIF(drive);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
struct request rq;
struct request_pm_state rqpm;
ide_task_t args;
+ int err;
/* Call ACPI _STM only once */
if (!(drive->dn % 2))
@@ -1029,7 +1031,12 @@ static int generic_ide_resume(struct device *dev)
rqpm.pm_step = ide_pm_state_start_resume;
rqpm.pm_state = PM_EVENT_ON;
- return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+ err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+
+ if (err == 0 && drv && drv->resume)
+ drv->resume(drive);
+
+ return err;
}
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index becb1a5648b..9db1be826e8 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,5 +1,5 @@
/*
- * Version 2.13
+ * Version 2.15
*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
@@ -76,6 +76,8 @@ static struct amd_ide_chip {
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, AMD_UDMA_133 },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
{ 0 }
};
@@ -494,7 +496,9 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
- /* 20 */ DECLARE_AMD_DEV("AMD5536"),
+ /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
+ /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
+ /* 22 */ DECLARE_AMD_DEV("AMD5536"),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -534,7 +538,9 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index f2c5a141ca1..0d51a11e81d 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -198,32 +198,41 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_pci_device_t *d = &generic_chipsets[id->driver_data];
- u16 command;
int ret = -ENODEV;
/* Don't use the generic entry unless instructed to do so */
if (id->driver_data == 0 && ide_generic_all == 0)
goto out;
- if (dev->vendor == PCI_VENDOR_ID_UMC &&
- dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
- (!(PCI_FUNC(dev->devfn) & 1)))
- goto out; /* UM8886A/BF pair */
-
- if (dev->vendor == PCI_VENDOR_ID_OPTI &&
- dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
- (!(PCI_FUNC(dev->devfn) & 1)))
- goto out;
-
- if (dev->vendor == PCI_VENDOR_ID_JMICRON) {
- if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1)
+ switch (dev->vendor) {
+ case PCI_VENDOR_ID_UMC:
+ if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
+ !(PCI_FUNC(dev->devfn) & 1))
+ goto out; /* UM8886A/BF pair */
+ break;
+ case PCI_VENDOR_ID_OPTI:
+ if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
+ !(PCI_FUNC(dev->devfn) & 1))
+ goto out;
+ break;
+ case PCI_VENDOR_ID_JMICRON:
+ if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
+ PCI_FUNC(dev->devfn) != 1)
+ goto out;
+ break;
+ case PCI_VENDOR_ID_NS:
+ if (dev->device == PCI_DEVICE_ID_NS_87410 &&
+ (dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
goto out;
+ break;
}
if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
+ u16 command;
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
- printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
+ printk(KERN_INFO "Skipping disabled %s IDE "
+ "controller.\n", d->name);
goto out;
}
}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index fcbc5605b38..ce8a5449a57 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.03 May 4, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.04 Jun 4, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -106,7 +106,8 @@
* switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency
* - switch to using the DPLL clock and enable UltraATA/133 mode by default on
- * anything newer than HPT370/A
+ * anything newer than HPT370/A (except HPT374 that is not capable of this
+ * mode according to the manual)
* - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining
@@ -365,7 +366,6 @@ static u32 sixty_six_base_hpt37x[] = {
};
#define HPT366_DEBUG_DRIVE_INFO 0
-#define HPT374_ALLOW_ATA133_6 1
#define HPT371_ALLOW_ATA133_6 1
#define HPT302_ALLOW_ATA133_6 1
#define HPT372_ALLOW_ATA133_6 1
@@ -450,7 +450,7 @@ static struct hpt_info hpt370a __devinitdata = {
static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
- .max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3,
+ .max_mode = 3,
.dpll_clk = 48,
.settings = hpt37x_settings
};
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5faaff87d58..4bd4bf02e91 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,6 +1,6 @@
/*
- * linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007
+ * linux/drivers/ide/pci/it821x.c Version 0.15 Jun 2 2007
*
* Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -262,7 +262,7 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
}
if (itdev->smart)
- goto set_drive_speed;
+ return 0;
/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
itdev->want[unit][1] = pio_want[set_pio];
@@ -271,7 +271,6 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
it821x_clock_strategy(drive);
it821x_program(drive, itdev->pio[unit]);
-set_drive_speed:
return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
}
@@ -455,12 +454,12 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
default:
return 1;
}
+
+ return ide_config_drive_speed(drive, speed);
}
- /*
- * In smart mode the clocking is done by the host controller
- * snooping the mode we picked. The rest of it is not our problem
- */
- return ide_config_drive_speed(drive, speed);
+
+ /* don't touch anything in the smart mode */
+ return 0;
}
/**
@@ -559,17 +558,10 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
if(idbits[129] != 1)
printk("(%dK stripe)", idbits[146]);
printk(".\n");
- /* Now the core code will have wrongly decided no DMA
- so we need to fix this */
- hwif->dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media == ide_disk)
-#endif
- ide_set_dma(drive);
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
- id->field_valid &= 1;
+ id->field_valid &= 3;
id->queue_depth = 0;
id->command_set_1 = 0;
id->command_set_2 &= 0xC400;
@@ -584,6 +576,16 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name);
}
+
+ /*
+ * Set MWDMA0 mode as enabled/support - just to tell
+ * IDE core that DMA is supported (it821x hardware
+ * takes care of DMA mode programming).
+ */
+ if (id->capability & 1) {
+ id->dma_mword |= 0x0101;
+ drive->current_speed = XFER_MW_DMA_0;
+ }
}
}
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 47bcd91c9b5..d9c4fd1ae99 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.9 Mar 4 2007
+ * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -170,42 +170,55 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if (!drive->init_speed) {
u8 dma_stat = inb(hwif->dma_status);
-dma_pio:
if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
return 0;
} else if ((dma_timing) &&
((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
- u8 dmaspeed = dma_timing;
+ u8 dmaspeed;
- dma_timing &= ~0xFFU;
- if ((dmaspeed & 0x20) == 0x20)
+ switch (dma_timing & 0x77) {
+ case 0x20:
dmaspeed = XFER_MW_DMA_2;
- else if ((dmaspeed & 0x21) == 0x21)
+ break;
+ case 0x21:
dmaspeed = XFER_MW_DMA_1;
- else if ((dmaspeed & 0x77) == 0x77)
+ break;
+ case 0x77:
dmaspeed = XFER_MW_DMA_0;
- else
+ break;
+ default:
goto dma_pio;
+ }
+
drive->current_speed = drive->init_speed = dmaspeed;
return 0;
- } else if (pio_timing) {
- u8 piospeed = pio_timing;
+ }
+dma_pio:
+ if (pio_timing) {
+ u8 piospeed;
- pio_timing &= ~0xFFU;
- if ((piospeed & 0x20) == 0x20)
+ switch (pio_timing & 0x7f) {
+ case 0x20:
piospeed = XFER_PIO_4;
- else if ((piospeed & 0x22) == 0x22)
+ break;
+ case 0x22:
piospeed = XFER_PIO_3;
- else if ((piospeed & 0x34) == 0x34)
+ break;
+ case 0x34:
piospeed = XFER_PIO_2;
- else if ((piospeed & 0x47) == 0x47)
+ break;
+ case 0x47:
piospeed = XFER_PIO_1;
- else if ((piospeed & 0x5d) == 0x5d)
+ break;
+ case 0x5d:
piospeed = XFER_PIO_0;
- else
+ break;
+ default:
goto oem_setup_failed;
+ }
+
drive->current_speed = drive->init_speed = piospeed;
return 0;
}
@@ -214,8 +227,8 @@ dma_pio:
oem_setup_failed:
- pio_timing &= ~0xFFU;
- dma_timing &= ~0xFFU;
+ pio_timing = 0;
+ dma_timing = 0;
ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn);
csb5_pio &= ~(0x0F << (4*drive->dn));
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 58bc272bd40..0aecea67f3e 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -672,7 +672,7 @@ static int c2_up(struct net_device *netdev)
* rdma interface.
*/
in_dev = in_dev_get(netdev);
- in_dev->cnf.arp_ignore = 1;
+ IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1);
in_dev_put(in_dev);
return 0;
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index 06eaf766d9d..f9e82c9ca42 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -104,7 +104,7 @@ static int pxakbd_open(struct input_dev *dev)
KPREC = 0x7F;
/* Enable unit clock */
- pxa_set_cken(CKEN19_KEYPAD, 1);
+ pxa_set_cken(CKEN_KEYPAD, 1);
return 0;
}
@@ -112,7 +112,7 @@ static int pxakbd_open(struct input_dev *dev)
static void pxakbd_close(struct input_dev *dev)
{
/* Disable clock unit */
- pxa_set_cken(CKEN19_KEYPAD, 0);
+ pxa_set_cken(CKEN_KEYPAD, 0);
}
#ifdef CONFIG_PM
@@ -185,7 +185,7 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
DRIVER_NAME, pdev);
if (error) {
printk(KERN_ERR "Cannot request keypad IRQ\n");
- pxa_set_cken(CKEN19_KEYPAD, 0);
+ pxa_set_cken(CKEN_KEYPAD, 0);
goto err_free_dev;
}
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index 46fc21a3f8f..d36a4c09e25 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -195,7 +195,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
/*
* disconnect from didd
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void disconnect_didd(void)
{
IDI_SYNC_REQ req;
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index c120114c241..5c63c8e24ee 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -4,5 +4,6 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV
tristate
+ depends on VIDEO_DEV
select VIDEO_BUF
select VIDEO_SAA7146
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index 1a1c3bca55f..bff00b58bf6 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -1,8 +1,11 @@
b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
- flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \
- flexcop-dma.o
+ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+b2c2-flexcop-objs += flexcop-dma.o
+endif
+
b2c2-flexcop-pci-objs = flexcop-pci.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 34d7abc900d..6aba5b39ed1 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -519,8 +519,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
+ mutex_lock(&cinergyt2->sem);
if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work);
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index ccc429cbbad..0f2d4b41556 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -41,6 +41,7 @@ struct tda10086_state {
/* private demod data */
u32 frequency;
u32 symbol_rate;
+ bool has_lock;
};
static int debug = 0;
@@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// misc setup
tda10086_write_byte(state, 0x01, 0x94);
tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
- tda10086_write_byte(state, 0x03, 0x64);
+ tda10086_write_byte(state, 0x03, 0xe4);
tda10086_write_byte(state, 0x04, 0x43);
tda10086_write_byte(state, 0x0c, 0x0c);
tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
@@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// setup AGC
tda10086_write_byte(state, 0x05, 0x0B);
tda10086_write_byte(state, 0x37, 0x63);
- tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it
+ tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
tda10086_write_byte(state, 0x40, 0x64);
tda10086_write_byte(state, 0x41, 0x4f);
tda10086_write_byte(state, 0x42, 0x43);
@@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
dprintk ("%s\n", __FUNCTION__);
+ // modify parameters for tuning
+ tda10086_write_byte(state, 0x02, 0x35);
+ state->has_lock = false;
+
// set params
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fe_params);
@@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
*fe_status |= FE_HAS_VITERBI;
if (val & 0x08)
*fe_status |= FE_HAS_SYNC;
- if (val & 0x10)
+ if (val & 0x10) {
*fe_status |= FE_HAS_LOCK;
+ if (!state->has_lock) {
+ state->has_lock = true;
+ // modify parameters for stable reception
+ tda10086_write_byte(state, 0x02, 0x00);
+ }
+ }
return 0;
}
@@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
dprintk ("%s\n", __FUNCTION__);
- _str = tda10086_read_byte(state, 0x43);
+ _str = 0xff - tda10086_read_byte(state, 0x43);
*signal = (_str << 8) | _str;
return 0;
@@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
dprintk ("%s\n", __FUNCTION__);
- _snr = tda10086_read_byte(state, 0x1c);
+ _snr = 0xff - tda10086_read_byte(state, 0x1c);
*snr = (_snr << 8) | _snr;
return 0;
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
index 79f971dc52b..bd3ebc28483 100644
--- a/drivers/media/dvb/frontends/tda826x.c
+++ b/drivers/media/dvb/frontends/tda826x.c
@@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
buf[3] = div >> 7;
buf[4] = div << 1;
- buf[5] = 0xff; // basedband filter to max
- buf[6] = 0xfe; // gains at max + no RF attenuation
+ buf[5] = 0x77; // baseband cut-off 19 MHz
+ buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
buf[7] = 0x83; // charge pumps at high, tests off
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 5cb3f54b548..4cca55170e2 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -347,7 +347,7 @@ endmenu # encoder / decoder chips
config VIDEO_VIVI
tristate "Virtual Video Driver"
- depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
+ depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI && VIDEO_DEV
select VIDEO_BUF
default n
---help---
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 15012f88b80..91e9e90c14a 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -86,7 +86,7 @@
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
V4L2_CAP_SLICED_VBI_CAPTURE)
#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
- V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS)
+ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
struct ivtv_card_video_input {
u8 video_type; /* video input type */
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index e29f949adf5..efc66355339 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->dma_timer.data = (unsigned long)itv;
itv->cur_dma_stream = -1;
+ itv->cur_pio_stream = -1;
itv->audio_stereo_mode = AUDIO_STEREO;
itv->audio_bilingual_mode = AUDIO_MONO_LEFT;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 552f04511ea..e6e56f175f3 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -237,6 +237,7 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29)
#define IVTV_IRQ_ENC_VIM_RST (0x1 << 28)
#define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27)
+#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25)
#define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24)
#define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22)
#define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20)
@@ -247,7 +248,8 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_DEC_VSYNC (0x1 << 10)
/* IRQ Masks */
-#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ)
+#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
+ IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
#define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
@@ -374,6 +376,9 @@ struct ivtv_mailbox_data {
#define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */
#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */
+#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */
+#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */
+
/* per-ivtv, i_flags */
#define IVTV_F_I_DMA 0 /* DMA in progress */
#define IVTV_F_I_UDMA 1 /* UDMA in progress */
@@ -390,8 +395,11 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */
#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */
#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */
-#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */
-#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */
+#define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */
+#define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */
+#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */
+#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */
+#define IVTV_F_I_PIO 19 /* PIO in progress */
/* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@@ -484,6 +492,7 @@ struct ivtv_stream {
/* Base Dev SG Array for cx23415/6 */
struct ivtv_SG_element *SGarray;
+ struct ivtv_SG_element *PIOarray;
dma_addr_t SG_handle;
int SG_length;
@@ -706,6 +715,7 @@ struct ivtv {
atomic_t decoding; /* count number of active decoding streams */
u32 irq_rr_idx; /* Round-robin stream index */
int cur_dma_stream; /* index of stream doing DMA */
+ int cur_pio_stream; /* index of stream doing PIO */
u32 dma_data_req_offset;
u32 dma_data_req_size;
int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 8976487a65f..555d5e6369c 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -32,6 +32,8 @@
#include "ivtv-yuv.h"
#include "ivtv-controls.h"
#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include <media/saa7115.h>
/* This function tries to claim the stream for a specific file descriptor.
If no one else is using this stream then the stream is claimed and
@@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
/* Select correct audio input (i.e. TV tuner or Line in) */
ivtv_audio_set_io(itv);
+ if (itv->hw_flags & IVTV_HW_SAA711X)
+ {
+ struct v4l2_crystal_freq crystal_freq;
+ crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+ crystal_freq.flags = 0;
+ ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+ }
/* Done! Unmute and continue. */
ivtv_unmute(itv);
ivtv_release_stream(s);
@@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv);
+ if (itv->hw_flags & IVTV_HW_SAA711X)
+ {
+ struct v4l2_crystal_freq crystal_freq;
+ crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+ crystal_freq.flags = SAA7115_FREQ_FL_APLL;
+ ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+ }
/* Done! Unmute and continue. */
ivtv_unmute(itv);
}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 1989ec1cb97..57af1762de1 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
itv->yuv_info.yuv_forced_update = 1;
return 0;
}
- if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
- r.width, r.height, r.left, r.top))
- itv->main_rect = r;
- else
- return -EINVAL;
}
return 0;
}
@@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return ivtv_get_fmt(itv, id->type, fmt);
}
+ case VIDIOC_CROPCAP: {
+ struct v4l2_cropcap *cropcap = arg;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+ cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ cropcap->bounds.height = itv->is_50hz ? 576 : 480;
+ cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+ } else {
+ cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
+ cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+ }
+ cropcap->defrect = cropcap->bounds;
+ return 0;
+ }
+
case VIDIOC_S_CROP: {
struct v4l2_crop *crop = arg;
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+ crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
+ itv->main_rect = crop->c;
+ return 0;
+ }
+ return -EINVAL;
+ }
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
@@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_CROP: {
struct v4l2_crop *crop = arg;
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ crop->c = itv->main_rect;
+ return 0;
+ }
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
@@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (itv->hw_flags & IVTV_HW_CX25840) {
itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
}
- IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std);
+ IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
/* Tuner */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
@@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(s->buffers - s->q_free.buffers) * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
- IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted);
+ IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
break;
}
@@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
case VIDIOC_ENUM_FMT:
+ case VIDIOC_CROPCAP:
case VIDIOC_G_CROP:
case VIDIOC_S_CROP:
case VIDIOC_G_FREQUENCY:
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index c3a047b381b..ba98bf054f2 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -31,8 +31,6 @@
#define DMA_MAGIC_COOKIE 0x000001fe
-#define SLICED_VBI_PIO 1
-
static void ivtv_dma_dec_start(struct ivtv_stream *s);
static const int ivtv_stream_map[] = {
@@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = {
IVTV_ENC_STREAM_TYPE_VBI,
};
-static inline int ivtv_use_pio(struct ivtv_stream *s)
+
+static void ivtv_pio_work_handler(struct ivtv *itv)
{
- struct ivtv *itv = s->itv;
+ struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
+ struct ivtv_buffer *buf;
+ struct list_head *p;
+ int i = 0;
+
+ IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
+ if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
+ s->v4l2dev == NULL || !ivtv_use_pio(s)) {
+ itv->cur_pio_stream = -1;
+ /* trigger PIO complete user interrupt */
+ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+ return;
+ }
+ IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
+ buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
+ list_for_each(p, &s->q_dma.list) {
+ struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
+ u32 size = s->PIOarray[i].size & 0x3ffff;
- return s->dma == PCI_DMA_NONE ||
- (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+ /* Copy the data from the card to the buffer */
+ if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+ memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
+ }
+ else {
+ memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size);
+ }
+ if (s->PIOarray[i].size & 0x80000000)
+ break;
+ i++;
+ }
+ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
}
void ivtv_irq_work_handler(struct work_struct *work)
@@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work)
DEFINE_WAIT(wait);
+ if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
+ ivtv_pio_work_handler(itv);
+
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
- vbi_work_handler(itv);
+ ivtv_vbi_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
ivtv_yuv_work_handler(itv);
@@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
}
s->buffers_stolen = rc;
- /* got the buffers, now fill in SGarray (DMA) or copy the data from the card
- to the buffers (PIO). */
+ /* got the buffers, now fill in SGarray (DMA) */
buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
memset(buf->buf, 0, 128);
list_for_each(p, &s->q_predma.list) {
@@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
if (skip_bufs-- > 0)
continue;
- if (!ivtv_use_pio(s)) {
- s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
- s->SGarray[idx].src = cpu_to_le32(offset);
- s->SGarray[idx].size = cpu_to_le32(s->buf_size);
- }
+ s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
+ s->SGarray[idx].src = cpu_to_le32(offset);
+ s->SGarray[idx].size = cpu_to_le32(s->buf_size);
buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
- /* If PIO, then copy the data from the card to the buffer */
- if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
- memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused);
- }
- else if (ivtv_use_pio(s)) {
- memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused);
- }
-
s->q_predma.bytesused += buf->bytesused;
size -= buf->bytesused;
offset += s->buf_size;
@@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s)
u32 *u32buf;
int x = 0;
- if (ivtv_use_pio(s)) {
- if (s->q_predma.bytesused)
- ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- s->SG_length = 0;
- }
IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) {
@@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s)
if (buf)
buf->bytesused += s->dma_last_offset;
if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
- /* Parse and Groom VBI Data */
- s->q_dma.bytesused -= buf->bytesused;
- ivtv_process_vbi_data(itv, buf, 0, s->type);
- s->q_dma.bytesused += buf->bytesused;
+ list_for_each(p, &s->q_dma.list) {
+ buf = list_entry(p, struct ivtv_buffer, list);
+
+ /* Parse and Groom VBI Data */
+ s->q_dma.bytesused -= buf->bytesused;
+ ivtv_process_vbi_data(itv, buf, 0, s->type);
+ s->q_dma.bytesused += buf->bytesused;
+ }
if (s->id == -1) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return;
@@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
int i;
+ IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
- s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
+
+ if (ivtv_use_dma(s))
+ s->SGarray[s->SG_length - 1].size =
+ cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
/* If this is an MPEG stream, and VBI data is also pending, then append the
VBI DMA to the MPEG DMA and transfer both sets of data at once.
@@ -368,7 +389,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
s->SG_length + s_vbi->SG_length <= s->buffers) {
ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
- s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
+ if (ivtv_use_dma(s_vbi))
+ s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
for (i = 0; i < s_vbi->SG_length; i++) {
s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
}
@@ -381,14 +403,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
/* Mark last buffer size for Interrupt flag */
s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
- /* Sync Hardware SG List of buffers */
- ivtv_stream_sync_for_device(s);
- write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
- write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
- set_bit(IVTV_F_I_DMA, &itv->i_flags);
- itv->cur_dma_stream = s->type;
- itv->dma_timer.expires = jiffies + HZ / 10;
- add_timer(&itv->dma_timer);
+ if (ivtv_use_pio(s)) {
+ for (i = 0; i < s->SG_length; i++) {
+ s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
+ s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
+ }
+ set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+ set_bit(IVTV_F_I_PIO, &itv->i_flags);
+ itv->cur_pio_stream = s->type;
+ }
+ else {
+ /* Sync Hardware SG List of buffers */
+ ivtv_stream_sync_for_device(s);
+ write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
+ write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+ set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = s->type;
+ itv->dma_timer.expires = jiffies + HZ / 10;
+ add_timer(&itv->dma_timer);
+ }
}
static void ivtv_dma_dec_start(struct ivtv_stream *s)
@@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
wake_up(&itv->dma_waitq);
}
+static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
+{
+ struct ivtv_stream *s;
+
+ if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
+ itv->cur_pio_stream = -1;
+ return;
+ }
+ s = &itv->streams[itv->cur_pio_stream];
+ IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
+ s->SG_length = 0;
+ clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
+ clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+ itv->cur_pio_stream = -1;
+ dma_post(s);
+ if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
+ else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
+ else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
+ clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+ if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+ u32 tmp;
+
+ s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+ tmp = s->dma_offset;
+ s->dma_offset = itv->vbi.dma_offset;
+ dma_post(s);
+ s->dma_offset = tmp;
+ }
+ wake_up(&itv->dma_waitq);
+}
+
static void ivtv_irq_dma_err(struct ivtv *itv)
{
u32 data[CX2341X_MBOX_MAX_DATA];
@@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
s = &itv->streams[ivtv_stream_map[data[0]]];
if (!stream_enc_dma_append(s, data)) {
- if (ivtv_use_pio(s)) {
- dma_post(s);
- ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]);
- }
- else {
- set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
- }
+ set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
}
}
@@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
- if (ivtv_use_pio(s)) {
- if (stream_enc_dma_append(s, data))
- return;
- if (s->q_predma.bytesused)
- ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- s->SG_length = 0;
- dma_post(s);
- return;
- }
/* If more than two VBI buffers are pending, then
clear the old ones and start with this new one.
This can happen during transition stages when MPEG capturing is
@@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
if (!stream_enc_dma_append(s, data) &&
!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
- set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+ set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
}
}
-static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
+static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
{
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
@@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
IVTV_DEBUG_IRQ("DEC VBI REINSERT\n");
if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
!stream_enc_dma_append(s, data)) {
- dma_post(s);
+ set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
}
}
@@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
if (frame != (itv->lastVsyncFrame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv);
- int work = 0;
itv->lastVsyncFrame += 1;
if (frame == 0) {
@@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
/* Send VBI to saa7127 */
if (frame) {
set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
- work = 1;
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
/* Check if we need to update the yuv registers */
@@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv)
itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
itv->yuv_info.yuv_forced_update = 0;
set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
- work = 1;
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
}
- if (work)
- queue_work(itv->irq_work_queues, &itv->irq_work_queue);
}
}
@@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
ivtv_irq_enc_dma_complete(itv);
}
+ if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
+ ivtv_irq_enc_pio_complete(itv);
+ }
+
if (combo & IVTV_IRQ_DMA_ERR) {
ivtv_irq_dma_err(itv);
}
@@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
- ivtv_irq_dev_vbi_reinsert(itv);
+ ivtv_irq_dec_vbi_reinsert(itv);
}
if (combo & IVTV_IRQ_ENC_EOS) {
@@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
}
+ if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
+ for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+ int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS;
+ struct ivtv_stream *s = &itv->streams[idx];
+
+ if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
+ continue;
+ if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
+ ivtv_dma_enc_start(s);
+ break;
+ }
+ }
+
+ if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
+ queue_work(itv->irq_work_queues, &itv->irq_work_queue);
+
spin_unlock(&itv->dma_reg_lock);
/* If we've just handled a 'forced' vsync, it's safest to say it
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index ccfcef1ad91..a04f9387f63 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
s->dma != PCI_DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
- /* Allocate DMA SG Arrays */
- if (s->dma != PCI_DMA_NONE) {
- s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
- if (s->SGarray == NULL) {
- IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+ if (ivtv_might_use_pio(s)) {
+ s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+ if (s->PIOarray == NULL) {
+ IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
return -ENOMEM;
}
- s->SG_length = 0;
+ }
+
+ /* Allocate DMA SG Arrays */
+ s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+ if (s->SGarray == NULL) {
+ IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+ if (ivtv_might_use_pio(s)) {
+ kfree(s->PIOarray);
+ s->PIOarray = NULL;
+ }
+ return -ENOMEM;
+ }
+ s->SG_length = 0;
+ if (ivtv_might_use_dma(s)) {
s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
ivtv_stream_sync_for_cpu(s);
}
@@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
break;
}
INIT_LIST_HEAD(&buf->list);
- if (s->dma != PCI_DMA_NONE) {
+ if (ivtv_might_use_dma(s)) {
buf->dma_handle = pci_map_single(s->itv->dev,
buf->buf, s->buf_size + 256, s->dma);
ivtv_buf_sync_for_cpu(s, buf);
@@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* empty q_free */
while ((buf = ivtv_dequeue(s, &s->q_free))) {
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_might_use_dma(s))
pci_unmap_single(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
kfree(buf->buf);
@@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s)
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
s->SG_handle = IVTV_DMA_UNMAPPED;
}
+ kfree(s->SGarray);
+ kfree(s->PIOarray);
+ s->PIOarray = NULL;
s->SGarray = NULL;
s->SG_length = 0;
}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
index 903edd4b438..2ed8d548255 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -20,18 +20,43 @@
*/
#define IVTV_DMA_UNMAPPED ((u32) -1)
+#define SLICED_VBI_PIO 1
/* ivtv_buffer utility functions */
+
+static inline int ivtv_might_use_pio(struct ivtv_stream *s)
+{
+ return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
+}
+
+static inline int ivtv_use_pio(struct ivtv_stream *s)
+{
+ struct ivtv *itv = s->itv;
+
+ return s->dma == PCI_DMA_NONE ||
+ (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+}
+
+static inline int ivtv_might_use_dma(struct ivtv_stream *s)
+{
+ return s->dma != PCI_DMA_NONE;
+}
+
+static inline int ivtv_use_dma(struct ivtv_stream *s)
+{
+ return !ivtv_use_pio(s);
+}
+
static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
{
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_use_dma(s))
pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
}
static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
{
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_use_dma(s))
pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
}
@@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s);
static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
{
- pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ if (ivtv_use_dma(s))
+ pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
+ sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
}
static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
{
- pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ if (ivtv_use_dma(s))
+ pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
+ sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 01a41a844a3..6af88ae9295 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
return 0;
- IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags);
+ IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
/* Stop Decoder */
if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) {
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index 5efa5a86781..3ba46e07ea1 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv)
}
-void vbi_work_handler(struct ivtv *itv)
+void ivtv_vbi_work_handler(struct ivtv *itv)
{
struct v4l2_sliced_vbi_data data;
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
index cdaea697b3e..ec211b49702 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.h
+++ b/drivers/media/video/ivtv/ivtv-vbi.h
@@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg);
-void vbi_work_handler(struct ivtv *itv);
+void ivtv_vbi_work_handler(struct ivtv *itv);
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 74839f98b7c..c1a392e4717 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -75,10 +75,6 @@ struct saa7111 {
int norm;
int input;
int enable;
- int bright;
- int contrast;
- int hue;
- int sat;
};
#define I2C_SAA7111 0x48
@@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
+static inline void
+saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
+{
+ struct saa7111 *decoder = i2c_get_clientdata(client);
+
+ if (decoder->reg[reg] != value) {
+ decoder->reg[reg] = value;
+ i2c_smbus_write_byte_data(client, reg, value);
+ }
+}
+
static int
saa7111_write_block (struct i2c_client *client,
const u8 *data,
@@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client,
{
struct video_picture *pic = arg;
- if (decoder->bright != pic->brightness) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->bright = pic->brightness;
- saa7111_write(client, 0x0a, decoder->bright >> 8);
- }
- if (decoder->contrast != pic->contrast) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->contrast = pic->contrast;
- saa7111_write(client, 0x0b,
- decoder->contrast >> 9);
- }
- if (decoder->sat != pic->colour) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->sat = pic->colour;
- saa7111_write(client, 0x0c, decoder->sat >> 9);
- }
- if (decoder->hue != pic->hue) {
- /* We want -128 to 127 we get 0-65535 */
- decoder->hue = pic->hue;
- saa7111_write(client, 0x0d,
- (decoder->hue - 32768) >> 8);
- }
+ /* We want 0 to 255 we get 0-65535 */
+ saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
+ /* We want 0 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0b, pic->contrast >> 9);
+ /* We want 0 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0c, pic->colour >> 9);
+ /* We want -128 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
}
break;
@@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter,
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
- decoder->bright = 32768;
- decoder->contrast = 32768;
- decoder->hue = 32768;
- decoder->sat = 32768;
i2c_set_clientdata(client, decoder);
i = i2c_attach_client(client);
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 9118a6227ea..7df071eb0a3 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb)
if (!USBVISION_IS_OPERATIONAL(usbvision))
return;
+ /* any urb with wrong status is ignored without acknowledgement */
+ if (urb->status == -ENOENT) {
+ return;
+ }
+
f = &usbvision->curFrame;
/* Manage streaming interruption */
@@ -1436,18 +1441,21 @@ static void usbvision_isocIrq(struct urb *urb)
if (usbvision->streaming == Stream_On) {
/* If we collected enough data let's parse! */
- if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */
- /*If we don't have a frame we're current working on, complain */
- if(!list_empty(&(usbvision->inqueue))) {
- if (!(*f)) {
- (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
- }
- usbvision_parse_data(usbvision);
- }
- else {
- PDEBUG(DBG_IRQ, "received data, but no one needs it");
- scratch_reset(usbvision);
+ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
+ (!list_empty(&(usbvision->inqueue))) ) {
+ if (!(*f)) {
+ (*f) = list_entry(usbvision->inqueue.next,
+ struct usbvision_frame,
+ frame);
}
+ usbvision_parse_data(usbvision);
+ }
+ else {
+ /*If we don't have a frame
+ we're current working on, complain */
+ PDEBUG(DBG_IRQ,
+ "received data, but no one needs it");
+ scratch_reset(usbvision);
}
}
else {
@@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb)
urb->dev = usbvision->dev;
errCode = usb_submit_urb (urb, GFP_ATOMIC);
- /* Disable this warning. By design of the driver. */
- // if(errCode) {
- // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
- // }
+ if(errCode) {
+ err("%s: usb_submit_urb failed: error %d",
+ __FUNCTION__, errCode);
+ }
return;
}
@@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
{
struct usb_device *dev = usbvision->dev;
int bufIdx, errCode, regValue;
- const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+ int sb_size;
if (!USBVISION_IS_OPERATIONAL(usbvision))
return -EFAULT;
@@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
usbvision->last_error = errCode;
return -EBUSY;
}
+ sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
- regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ regValue = (16 - usbvision_read_reg(usbvision,
+ USBVISION_ALTER_REG)) & 0x0F;
usbvision->usb_bandwidth = regValue >> 1;
- PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+ usbvision->usb_bandwidth);
@@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
return -ENOMEM;
}
usbvision->sbuf[bufIdx].urb = urb;
- usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma);
+ usbvision->sbuf[bufIdx].data =
+ usb_buffer_alloc(usbvision->dev,
+ sb_size,
+ GFP_KERNEL,
+ &urb->transfer_dma);
urb->dev = dev;
urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
k += usbvision->isocPacketSize) {
urb->iso_frame_desc[j].offset = k;
- urb->iso_frame_desc[j].length = usbvision->isocPacketSize;
+ urb->iso_frame_desc[j].length =
+ usbvision->isocPacketSize;
}
}
/* Submit all URBs */
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
- errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL);
+ errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
+ GFP_KERNEL);
if (errCode) {
- err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode);
+ err("%s: usb_submit_urb(%d) failed: error %d",
+ __FUNCTION__, bufIdx, errCode);
}
}
usbvision->streaming = Stream_Idle;
- PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
+ PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+ __FUNCTION__,
+ usbvision->video_endp);
return 0;
}
@@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
void usbvision_stop_isoc(struct usb_usbvision *usbvision)
{
int bufIdx, errCode, regValue;
- const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+ int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
return;
@@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
errCode = usb_set_interface(usbvision->dev, usbvision->iface,
usbvision->ifaceAlt);
if (errCode < 0) {
- err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
+ err("%s: usb_set_interface() failed: error %d",
+ __FUNCTION__, errCode);
usbvision->last_error = errCode;
}
- regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
- usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
- PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+ regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ usbvision->isocPacketSize =
+ (regValue == 0) ? 0 : (regValue * 64) - 1;
+ PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
+ usbvision->isocPacketSize);
usbvision->usb_bandwidth = regValue >> 1;
- PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+ usbvision->usb_bandwidth);
}
}
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index bd6f6422ed5..c759d00d701 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -146,7 +146,6 @@
#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
#define USBVISION_URB_FRAMES 32
-#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
#define USBVISION_NUM_HEADERMARKER 20
#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c1dfd03d559..41bfb5dfe6f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -15,6 +15,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
#include "core.h"
#include "sysfs.h"
@@ -192,6 +193,16 @@ static int mmc_read_switch(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH)) {
+ printk(KERN_WARNING "%s: card lacks mandatory switch "
+ "function, performance might suffer.\n",
+ mmc_hostname(card->host));
+ return MMC_ERR_NONE;
+ }
+
err = MMC_ERR_FAILED;
status = kmalloc(64, GFP_KERNEL);
@@ -204,10 +215,9 @@ static int mmc_read_switch(struct mmc_card *card)
err = mmc_sd_switch(card, 0, 0, 1, status);
if (err != MMC_ERR_NONE) {
- /*
- * Card not supporting high-speed will ignore the
- * command.
- */
+ printk(KERN_WARNING "%s: problem reading switch "
+ "capabilities, performance might suffer.\n",
+ mmc_hostname(card->host));
err = MMC_ERR_NONE;
goto out;
}
@@ -229,6 +239,12 @@ static int mmc_switch_hs(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH))
+ return MMC_ERR_NONE;
+
if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
return MMC_ERR_NONE;
@@ -402,7 +418,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
/*
* Switch to wider bus (if supported).
*/
- if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+ if ((host->caps & MMC_CAP_4_BIT_DATA) &&
(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
if (err != MMC_ERR_NONE)
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index e37943c314c..5b00c194b62 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -417,7 +417,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
blocks = 0;
}
- if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ if (host->flags & FL_SENT_STOP)
cmdr |= AT91_MCI_TRCMD_STOP;
if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -563,8 +563,7 @@ static void at91mci_completed_command(struct at91mci_host *host)
if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
- if ((status & AT91_MCI_RCRCE) &&
- ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+ if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
cmd->error = MMC_ERR_NONE;
}
else {
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f967226d750..52b63f11ddd 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -76,8 +76,7 @@ const struct {
#endif
};
-#define AU1XMMC_CONTROLLER_COUNT \
- (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
/* This array stores pointers for the hosts (used by the IRQ handler) */
struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index da7c3b0c533..ce3ed67a878 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -54,8 +54,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.5.10"
-#define DRV_MODULE_RELDATE "May 1, 2007"
+#define DRV_MODULE_VERSION "1.5.11"
+#define DRV_MODULE_RELDATE "June 4, 2007"
#define RUN_AT(x) (jiffies + (x))
@@ -1778,6 +1778,15 @@ bnx2_init_5709_context(struct bnx2 *bp)
val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
val |= (BCM_PAGE_BITS - 8) << 16;
REG_WR(bp, BNX2_CTX_COMMAND, val);
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_CTX_COMMAND);
+ if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
+ break;
+ udelay(2);
+ }
+ if (val & BNX2_CTX_COMMAND_MEM_INIT)
+ return -EBUSY;
+
for (i = 0; i < bp->ctx_pages; i++) {
int j;
@@ -1811,6 +1820,7 @@ bnx2_init_context(struct bnx2 *bp)
vcid = 96;
while (vcid) {
u32 vcid_addr, pcid_addr, offset;
+ int i;
vcid--;
@@ -1831,16 +1841,20 @@ bnx2_init_context(struct bnx2 *bp)
pcid_addr = vcid_addr;
}
- REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
- REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
+ vcid_addr += (i << PHY_CTX_SHIFT);
+ pcid_addr += (i << PHY_CTX_SHIFT);
- /* Zero out the context. */
- for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
- CTX_WR(bp, 0x00, offset, 0);
- }
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+ /* Zero out the context. */
+ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
+ CTX_WR(bp, 0x00, offset, 0);
- REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
- REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ }
}
}
@@ -3691,9 +3705,11 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize context mapping and zero out the quick contexts. The
* context block must have already been enabled. */
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- bnx2_init_5709_context(bp);
- else
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ rc = bnx2_init_5709_context(bp);
+ if (rc)
+ return rc;
+ } else
bnx2_init_context(bp);
if ((rc = bnx2_init_cpus(bp)) != 0)
@@ -3772,7 +3788,10 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_CMD_TICKS,
(bp->cmd_ticks_int << 16) | bp->cmd_ticks);
- REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+ if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
+ else
+ REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
if (CHIP_ID(bp) == CHIP_ID_5706_A1)
@@ -3799,6 +3818,11 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize the receive filter. */
bnx2_set_rx_mode(bp->dev);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+ val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
+ REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+ }
rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
0);
@@ -4620,6 +4644,11 @@ bnx2_timer(unsigned long data)
bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+ /* workaround occasional corrupted counters */
+ if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
+ BNX2_HC_COMMAND_STATS_NOW);
+
if (bp->phy_flags & PHY_SERDES_FLAG) {
if (CHIP_NUM(bp) == CHIP_NUM_5706)
bnx2_5706_serdes_timer(bp);
@@ -5417,6 +5446,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
0xff;
bp->stats_ticks = coal->stats_block_coalesce_usecs;
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
+ bp->stats_ticks = USEC_PER_SEC;
+ }
if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
bp->stats_ticks &= 0xffff00;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index bd6288d6350..49a5de253b1 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1373,6 +1373,7 @@ struct l2_fhdr {
#define BNX2_MISC_NEW_CORE_CTL 0x000008c8
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0)
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1)
+#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16)
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 00d1255e4c1..e88da72f830 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -167,9 +167,9 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
ignore_char:
status = readb(uap->port.membase + UART01x_FR);
}
- spin_unlock(&port->lock);
+ spin_unlock(&uap->port.lock);
tty_flip_buffer_push(tty);
- spin_lock(&port->lock);
+ spin_lock(&uap->port.lock);
}
static void pl010_tx_chars(struct uart_amba_port *uap)
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 3524e3fc08b..61de78a9f6e 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -2182,7 +2182,7 @@ struct dec_serial_hook zs_kgdbhook = {
.init_info = kgdbhook_init_info,
.rx_char = kgdbhook_rx_char,
.cflags = B38400 | CS8 | CLOCAL,
-}
+};
void __init zs_kgdb_hook(int tty_num)
{
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 30b7bfbc985..8bcf7fe1dd8 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -476,8 +476,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
add_timer(&timer);
wait_for_completion(done);
status = urb->status;
- if (status == -ECONNRESET)
- status = -ETIMEDOUT;
del_timer_sync(&timer);
if (actual_length)
@@ -629,10 +627,22 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0;
}
+static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
+ struct atm_dev *atm_dev)
+{
+ struct usb_interface *intf = usbatm_instance->usb_intf;
+
+ #define CXACRU_DEVICE_REMOVE_FILE(_name) \
+ device_remove_file(&intf->dev, &dev_attr_##_name);
+ CXACRU_ALL_FILES(REMOVE);
+ #undef CXACRU_DEVICE_REMOVE_FILE
+}
+
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
struct cxacru_data *instance = usbatm_instance->driver_data;
+ struct usb_interface *intf = usbatm_instance->usb_intf;
/*
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/
@@ -649,14 +659,18 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
return ret;
}
+ #define CXACRU_DEVICE_CREATE_FILE(_name) \
+ ret = device_create_file(&intf->dev, &dev_attr_##_name); \
+ if (unlikely(ret)) \
+ goto fail_sysfs;
+ CXACRU_ALL_FILES(CREATE);
+ #undef CXACRU_DEVICE_CREATE_FILE
+
/* start ADSL */
mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
- if (ret < 0) {
+ if (ret < 0)
atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
- mutex_unlock(&instance->adsl_state_serialize);
- return ret;
- }
/* Start status polling */
mutex_lock(&instance->poll_state_serialize);
@@ -680,6 +694,11 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
if (start_polling)
cxacru_poll_status(&instance->poll_work.work);
return 0;
+
+fail_sysfs:
+ usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
+ cxacru_remove_device_files(usbatm_instance, atm_dev);
+ return ret;
}
static void cxacru_poll_status(struct work_struct *work)
@@ -1065,13 +1084,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail;
}
- #define CXACRU_DEVICE_CREATE_FILE(_name) \
- ret = device_create_file(&intf->dev, &dev_attr_##_name); \
- if (unlikely(ret)) \
- goto fail_sysfs;
- CXACRU_ALL_FILES(CREATE);
- #undef CXACRU_DEVICE_CREATE_FILE
-
usb_fill_int_urb(instance->rcv_urb,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE,
@@ -1092,14 +1104,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
return 0;
- fail_sysfs:
- dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
-
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
fail:
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
@@ -1146,11 +1150,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
kfree(instance);
usbatm_instance->driver_data = NULL;
@@ -1231,6 +1230,7 @@ static struct usbatm_driver cxacru_driver = {
.heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind,
.atm_start = cxacru_atm_start,
+ .atm_stop = cxacru_remove_device_files,
.bulk_in = CXACRU_EP_DATA,
.bulk_out = CXACRU_EP_DATA,
.rx_padding = 3,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 7b1edfe46b2..6778f9af794 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -347,10 +347,8 @@ static int handle_bidir (struct usblp *usblp)
if (usblp->bidir && usblp->used && !usblp->sleeping) {
usblp->readcount = 0;
usblp->readurb->dev = usblp->dev;
- if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
- usblp->used = 0;
+ if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
return -EIO;
- }
}
return 0;
@@ -412,6 +410,7 @@ static int usblp_open(struct inode *inode, struct file *file)
usblp->readurb->status = 0;
if (handle_bidir(usblp) < 0) {
+ usblp->used = 0;
file->private_data = NULL;
retval = -EIO;
}
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f493fb1eaa2..346fc030c92 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -40,21 +40,25 @@ config USB_DEVICEFS
config USB_DEVICE_CLASS
bool "USB device class-devices (DEPRECATED)"
depends on USB
- default n
+ default y
---help---
Userspace access to USB devices is granted by device-nodes exported
directly from the usbdev in sysfs. Old versions of the driver
core and udev needed additional class devices to export device nodes.
These additional devices are difficult to handle in userspace, if
- information about USB interfaces must be available. One device contains
- the device node, the other device contains the interface data. Both
- devices are at the same level in sysfs (siblings) and one can't access
- the other. The device node created directly by the usbdev is the parent
- device of the interface and therefore easily accessible from the interface
- event.
-
- This option provides backward compatibility if needed.
+ information about USB interfaces must be available. One device
+ contains the device node, the other device contains the interface
+ data. Both devices are at the same level in sysfs (siblings) and one
+ can't access the other. The device node created directly by the
+ usb device is the parent device of the interface and therefore
+ easily accessible from the interface event.
+
+ This option provides backward compatibility for libusb device
+ nodes (lsusb) when usbfs is not used, and the following udev rule
+ doesn't exist:
+ SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
+ NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation (EXPERIMENTAL)"
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 2d4fd530e5e..dd3482328ad 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1,4 +1,5 @@
#include <linux/usb.h>
+#include <linux/usb/ch9.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
struct usb_host_endpoint *endpoint;
- int n, i;
+ int n, i, j;
d = (struct usb_endpoint_descriptor *) buffer;
buffer += d->bLength;
@@ -84,6 +85,45 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
memcpy(&endpoint->desc, d, n);
INIT_LIST_HEAD(&endpoint->urb_list);
+ /* If the bInterval value is outside the legal range,
+ * set it to a default value: 32 ms */
+ i = 0; /* i = min, j = max, n = default */
+ j = 255;
+ if (usb_endpoint_xfer_int(d)) {
+ i = 1;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ j = 16;
+ break;
+ default: /* USB_SPEED_FULL or _LOW */
+ /* For low-speed, 10 ms is the official minimum.
+ * But some "overclocked" devices might want faster
+ * polling so we'll allow it. */
+ n = 32;
+ break;
+ }
+ } else if (usb_endpoint_xfer_isoc(d)) {
+ i = 1;
+ j = 16;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ break;
+ default: /* USB_SPEED_FULL */
+ n = 6; /* 32 ms = 2^(6-1) frames */
+ break;
+ }
+ }
+ if (d->bInterval < i || d->bInterval > j) {
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X has an invalid bInterval %d, "
+ "changing to %d\n",
+ cfgno, inum, asnum,
+ d->bEndpointAddress, d->bInterval, n);
+ endpoint->desc.bInterval = n;
+ }
+
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index f28af06905a..6042364402b 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -132,7 +132,7 @@ ep_matches (
* where it's an output parameter representing the full speed limit.
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
*/
- max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
+ max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high speed */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 188c74a9521..46d0e525274 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1369,12 +1369,12 @@ config_buf (struct dev_data *dev, u8 type, unsigned index)
hs = !hs;
if (hs) {
dev->req->buf = dev->hs_config;
- len = le16_to_cpup (&dev->hs_config->wTotalLength);
+ len = le16_to_cpu(dev->hs_config->wTotalLength);
} else
#endif
{
dev->req->buf = dev->config;
- len = le16_to_cpup (&dev->config->wTotalLength);
+ len = le16_to_cpu(dev->config->wTotalLength);
}
((u8 *)dev->req->buf) [1] = type;
return len;
@@ -1885,7 +1885,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* full or low speed config */
dev->config = (void *) kbuf;
- total = le16_to_cpup (&dev->config->wTotalLength);
+ total = le16_to_cpu(dev->config->wTotalLength);
if (!is_valid_config (dev->config) || total >= length)
goto fail;
kbuf += total;
@@ -1894,7 +1894,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* optional high speed config */
if (kbuf [1] == USB_DT_CONFIG) {
dev->hs_config = (void *) kbuf;
- total = le16_to_cpup (&dev->hs_config->wTotalLength);
+ total = le16_to_cpu(dev->hs_config->wTotalLength);
if (!is_valid_config (dev->hs_config) || total >= length)
goto fail;
kbuf += total;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 52779c52b56..d975ecf18e0 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2440,9 +2440,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
tmp = 0;
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* ack the irq */
writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b394e63894d..c4975a6cf77 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1651,9 +1651,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
UDC_EP_NUM_REG = 0;
} while (UDC_IRQ_SRC_REG & UDC_SETUP);
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* Delegate almost all control requests to the gadget driver,
* except for a handful of ch9 status/feature requests that
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 6ec8cf1a3cc..708657c8913 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -186,10 +186,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -665,7 +669,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_PNP_QUERY_POWER:
DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
- le32_to_cpup((__le32 *) buf) - 1);
+ le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
/* only suspend is a real power state, and
* it can't be entered by OID_PNP_SET_POWER...
*/
@@ -704,10 +708,14 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -721,7 +729,8 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
- *params->filter = (u16) le32_to_cpup((__le32 *)buf);
+ *params->filter = (u16) le32_to_cpu(get_unaligned(
+ (__le32 *)buf));
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__FUNCTION__, *params->filter);
@@ -771,7 +780,7 @@ update_linkstate:
* resuming, Windows forces a reset, and then SET_POWER D0.
* FIXME ... then things go batty; Windows wedges itself.
*/
- i = le32_to_cpup((__force __le32 *)buf);
+ i = le32_to_cpu(get_unaligned((__le32 *)buf));
DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
switch (i) {
case NdisDeviceStateD0:
@@ -1058,8 +1067,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
return -ENOMEM;
tmp = (__le32 *) buf;
- MsgType = le32_to_cpup(tmp++);
- MsgLength = le32_to_cpup(tmp++);
+ MsgType = le32_to_cpu(get_unaligned(tmp++));
+ MsgLength = le32_to_cpu(get_unaligned(tmp++));
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 216c9c9d4d6..bb9cc595219 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -417,6 +417,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ goto done;
/* undocumented erratum seen on at least rev D */
if ((ohci->flags & OHCI_QUIRK_AMD756)
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d230ee72f9c..54979c239c6 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1179,8 +1179,8 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
-/* These are virtual windows driver CDs, which the zd1211rw driver automatically
- * converts into a WLAN devices. */
+/* These are virtual windows driver CDs, which the zd1211rw driver
+ * automatically converts into WLAN devices. */
UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
"ZyXEL",
"G-220F USB-WLAN Install",
@@ -1193,6 +1193,14 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ),
+/* SanDisk that has a second LUN for a driver ISO, reported by
+ * Ben Collins <bcollins@ubuntu.com> */
+UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff,
+ "SanDisk",
+ "U3 Cruzer Micro driver ISO",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
@@ -1271,6 +1279,15 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Edward Chapman (taken from linux-usb mailing list)
+ Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */
+UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
+ "Netac",
+ "USB Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+
/* Patch by Stephan Walter <stephan.walter@epfl.ch>
* I don't know why, but it works... */
UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 7b0265d7f3a..861141b4f6d 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -558,7 +558,7 @@ static int load_flat_file(struct linux_binprm * bprm,
if (!realdatastart)
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
- (int)-datapos);
+ (int)-realdatastart);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
goto err;
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 6017c465440..07838b2ac1c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -7,16 +7,16 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
char *charptr = data;
char buf[10], line[80];
- printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
+ printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
label, length, data);
for (i = 0; i < length; i += 16) {
line[0] = 0;
@@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length)
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb)
{
- cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
+ cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
- cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
+ cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
}
@@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server)
struct list_head *tmp;
struct mid_q_entry * mid_entry;
- if(server == NULL)
+ if (server == NULL)
return;
- cERROR(1,("Dump pending requests:"));
+ cERROR(1, ("Dump pending requests:"));
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
- if(mid_entry) {
- cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
+ if (mid_entry) {
+ cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2
- cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
+ cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
#endif /* STATS2 */
- cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
+ cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
- if(mid_entry->resp_buf) {
+ if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf,
62 /* fixme */);
}
-
}
}
spin_unlock(&GlobalMid_Lock);
@@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
"Display Internal CIFS Data Structures for Debugging\n"
"---------------------------------------------------\n");
buf += length;
- length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
+ length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
buf += length;
- length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
+ length = sprintf(buf,
+ "Active VFS Requests: %d\n", GlobalTotalActiveXid);
buf += length;
length = sprintf(buf, "Servers:");
buf += length;
@@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalSMBSessionList) {
i++;
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
+ if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
(ses->serverNOS == NULL)) {
buf += sprintf(buf, "\nentry for %s not fully "
"displayed\n\t", ses->serverName);
@@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
} else {
length =
sprintf(buf,
- "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
+ "\n%d) Name: %s Domain: %s Mounts: %d OS:"
+ " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
+ " session status: %d\t",
i, ses->serverName, ses->serverDomain,
atomic_read(&ses->inUse),
ses->serverOS, ses->serverNOS,
- ses->capabilities,ses->status);
+ ses->capabilities, ses->status);
buf += length;
}
- if(ses->server) {
- buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
+ if (ses->server) {
+ buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
+ "Server: %d SecMode: 0x%x Req On Wire: %d",
ses->server->tcpStatus,
atomic_read(&ses->server->socketUseCount),
ses->server->secMode,
@@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
#ifdef CONFIG_CIFS_STATS2
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
- atomic_read(&ses->server->inSend),
+ atomic_read(&ses->server->inSend),
atomic_read(&ses->server->num_waiters));
#endif
@@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
mid_entry = list_entry(tmp1, struct
mid_q_entry,
qhead);
- if(mid_entry) {
- length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
- mid_entry->midState,
- (int)mid_entry->command,
- mid_entry->pid,
- mid_entry->tsk,
- mid_entry->mid);
+ if (mid_entry) {
+ length = sprintf(buf,
+ "State: %d com: %d pid:"
+ " %d tsk: %p mid %d\n",
+ mid_entry->midState,
+ (int)mid_entry->command,
+ mid_entry->pid,
+ mid_entry->tsk,
+ mid_entry->mid);
buf += length;
}
}
- spin_unlock(&GlobalMid_Lock);
+ spin_unlock(&GlobalMid_Lock);
}
}
@@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
length =
sprintf(buf,
- "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+ "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
+ "Attributes: 0x%x\nPathComponentMax: %d Status: %d",
i, tcon->treeName,
atomic_read(&tcon->useCount),
tcon->nativeFileSystem,
@@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
tcon->tidStatus);
- buf += length;
+ buf += length;
if (dev_type == FILE_DEVICE_DISK)
length = sprintf(buf, " type: DISK ");
else if (dev_type == FILE_DEVICE_CD_ROM)
@@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
length =
sprintf(buf, " type: %d ", dev_type);
buf += length;
- if(tcon->tidStatus == CifsNeedReconnect) {
+ if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED ");
length += 14;
}
@@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
/* Now calculate total size of returned data */
length = buf - original_buf;
- if(offset + count >= length)
+ if (offset + count >= length)
*eof = 1;
- if(length < offset) {
+ if (length < offset) {
*eof = 1;
return 0;
} else {
@@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
static int
cifs_stats_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
- char c;
- int rc;
+ char c;
+ int rc;
struct list_head *tmp;
struct cifsTconInfo *tcon;
- rc = get_user(c, buffer);
- if (rc)
- return rc;
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
- if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
+ if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2
atomic_set(&totBufAllocCount, 0);
@@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer,
read_unlock(&GlobalSMBSeslock);
}
- return count;
+ return count;
}
static int
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data)
{
- int item_length,i,length;
+ int item_length, i, length;
struct list_head *tmp;
struct cifsTconInfo *tcon;
@@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
"Resources in use\nCIFS Session: %d\n",
sesInfoAllocCount.counter);
buf += length;
- item_length =
- sprintf(buf,"Share (unique mount targets): %d\n",
+ item_length =
+ sprintf(buf, "Share (unique mount targets): %d\n",
tconInfoAllocCount.counter);
length += item_length;
- buf += item_length;
- item_length =
- sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+ buf += item_length;
+ item_length =
+ sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
bufAllocCount.counter,
cifs_min_rcv + tcpSesAllocCount.counter);
length += item_length;
buf += item_length;
- item_length =
- sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
- smBufAllocCount.counter,cifs_min_small);
+ item_length =
+ sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+ smBufAllocCount.counter, cifs_min_small);
length += item_length;
buf += item_length;
#ifdef CONFIG_CIFS_STATS2
- item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+ item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
atomic_read(&totBufAllocCount),
- atomic_read(&totSmBufAllocCount));
+ atomic_read(&totSmBufAllocCount));
length += item_length;
buf += item_length;
#endif /* CONFIG_CIFS_STATS2 */
- item_length =
- sprintf(buf,"Operations (MIDs): %d\n",
+ item_length =
+ sprintf(buf, "Operations (MIDs): %d\n",
midCount.counter);
length += item_length;
buf += item_length;
item_length = sprintf(buf,
"\n%d session %d share reconnects\n",
- tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
+ tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
length += item_length;
buf += item_length;
item_length = sprintf(buf,
"Total vfs operations: %d maximum at one time: %d\n",
- GlobalCurrentXid,GlobalMaxActiveXid);
+ GlobalCurrentXid, GlobalMaxActiveXid);
length += item_length;
buf += item_length;
@@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalTreeConnectionList) {
i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
+ item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
buf += item_length;
length += item_length;
- if(tcon->tidStatus == CifsNeedReconnect) {
+ if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED ");
length += 14;
}
@@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
atomic_read(&tcon->num_writes),
(long long)(tcon->bytes_written));
- buf += item_length;
- length += item_length;
- item_length = sprintf(buf,
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,
"\nLocks: %d HardLinks: %d Symlinks: %d",
- atomic_read(&tcon->num_locks),
+ atomic_read(&tcon->num_locks),
atomic_read(&tcon->num_hardlinks),
atomic_read(&tcon->num_symlinks));
- buf += item_length;
- length += item_length;
+ buf += item_length;
+ length += item_length;
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
atomic_read(&tcon->num_opens),
@@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
}
read_unlock(&GlobalSMBSeslock);
- buf += sprintf(buf,"\n");
+ buf += sprintf(buf, "\n");
length++;
- if(offset + count >= length)
+ if (offset + count >= length)
*eof = 1;
- if(length < offset) {
+ if (length < offset) {
*eof = 1;
return 0;
} else {
@@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
}
if (length > count)
length = count;
-
+
return length;
}
#endif
@@ -547,11 +553,11 @@ cifs_proc_clean(void)
remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs);
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
- remove_proc_entry("SecurityFlags",proc_fs_cifs);
-/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
- remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
- remove_proc_entry("Experimental",proc_fs_cifs);
- remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+ remove_proc_entry("SecurityFlags", proc_fs_cifs);
+/* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
+ remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
+ remove_proc_entry("Experimental", proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
remove_proc_entry("cifs", proc_root_fs);
}
@@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer,
cifsFYI = 0;
else if (c == '1' || c == 'y' || c == 'Y')
cifsFYI = 1;
- else if((c > '1') && (c <= '9'))
+ else if ((c > '1') && (c <= '9'))
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
return count;
@@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
static int
experimEnabled_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
- int len;
+ int len;
- len = sprintf(page, "%d\n", experimEnabled);
+ len = sprintf(page, "%d\n", experimEnabled);
- len -= off;
- *start = page + off;
+ len -= off;
+ *start = page + off;
- if (len > count)
- len = count;
- else
- *eof = 1;
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
- if (len < 0)
- len = 0;
+ if (len < 0)
+ len = 0;
- return len;
+ return len;
}
static int
experimEnabled_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
char c;
int rc;
@@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer,
static int
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
- int len;
+ int len;
- len = sprintf(page, "%d\n", linuxExtEnabled);
- len -= off;
- *start = page + off;
+ len = sprintf(page, "%d\n", linuxExtEnabled);
+ len -= off;
+ *start = page + off;
- if (len > count)
- len = count;
- else
- *eof = 1;
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
- if (len < 0)
- len = 0;
+ if (len < 0)
+ len = 0;
- return len;
+ return len;
}
static int
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
- char c;
- int rc;
-
- rc = get_user(c, buffer);
- if (rc)
- return rc;
- if (c == '0' || c == 'n' || c == 'N')
- linuxExtEnabled = 0;
- else if (c == '1' || c == 'y' || c == 'Y')
- linuxExtEnabled = 1;
-
- return count;
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ linuxExtEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ linuxExtEnabled = 1;
+
+ return count;
}
static int
lookupFlag_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
int len;
@@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer,
char flags_string[12];
char c;
- if((count < 1) || (count > 11))
+ if ((count < 1) || (count > 11))
return -EINVAL;
memset(flags_string, 0, 12);
- if(copy_from_user(flags_string, buffer, count))
+ if (copy_from_user(flags_string, buffer, count))
return -EFAULT;
- if(count < 3) {
+ if (count < 3) {
/* single char or single char followed by null */
c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N')
@@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer,
flags = simple_strtoul(flags_string, NULL, 0);
- cFYI(1,("sec flags 0x%x", flags));
+ cFYI(1, ("sec flags 0x%x", flags));
- if(flags <= 0) {
- cERROR(1,("invalid security flags %s",flags_string));
+ if (flags <= 0) {
+ cERROR(1, ("invalid security flags %s", flags_string));
return -EINVAL;
}
- if(flags & ~CIFSSEC_MASK) {
- cERROR(1,("attempt to set unsupported security flags 0x%x",
+ if (flags & ~CIFSSEC_MASK) {
+ cERROR(1, ("attempt to set unsupported security flags 0x%x",
flags & ~CIFSSEC_MASK));
return -EINVAL;
}
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 793c4b95c16..701e9a9185f 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -6,16 +6,16 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
@@ -32,7 +32,7 @@
*
*/
int
-cifs_strfromUCS_le(char *to, const __le16 * from,
+cifs_strfromUCS_le(char *to, const __le16 * from,
int len, const struct nls_table *codepage)
{
int i;
@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
{
int charlen;
int i;
- wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
+ wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
@@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
/* A question mark */
to[i] = cpu_to_le16(0x003f);
charlen = 1;
- } else
+ } else
to[i] = cpu_to_le16(wchar_to[i]);
}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d38c69b591c..7c04752b76c 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -825,8 +825,8 @@ cifs_init_mids(void)
sizeof (struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_oplock_cachep == NULL) {
- kmem_cache_destroy(cifs_mid_cachep);
mempool_destroy(cifs_mid_poolp);
+ kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM;
}
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 14de58fa143..57419a17668 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cFYI(1,("secFlags 0x%x",secFlags));
pSMB->hdr.Mid = GetNextMid(server);
- pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
- if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+ pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+ if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
count = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 216fb625843..f4e92661b22 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
srvTcp->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
if (srvTcp->tsk) {
+ struct task_struct *tsk;
+ /* If we could verify that kthread_stop would
+ always wake up processes blocked in
+ tcp in recv_mesg then we could remove the
+ send_sig call */
send_sig(SIGKILL,srvTcp->tsk,1);
- kthread_stop(srvTcp->tsk);
+ tsk = srvTcp->tsk;
+ if(tsk)
+ kthread_stop(tsk);
}
}
/* If find_unc succeeded then rc == 0 so we can not end */
@@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* if the socketUseCount is now zero */
if ((temp_rc == -ESHUTDOWN) &&
(pSesInfo->server) && (pSesInfo->server->tsk)) {
+ struct task_struct *tsk;
send_sig(SIGKILL,pSesInfo->server->tsk,1);
- kthread_stop(pSesInfo->server->tsk);
+ tsk = pSesInfo->server->tsk;
+ if (tsk)
+ kthread_stop(tsk);
}
} else
cFYI(1, ("No session or bad tcon"));
@@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
return 0;
} else if (rc == -ESHUTDOWN) {
cFYI(1,("Waking up socket by sending it signal"));
- if(cifsd_task) {
+ if (cifsd_task) {
send_sig(SIGKILL,cifsd_task,1);
kthread_stop(cifsd_task);
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e5210519ac4..8e86aaceb68 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -2,7 +2,7 @@
* fs/cifs/dir.c
*
* vfs operations that deal with dentries
- *
+ *
* Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
@@ -34,11 +34,12 @@
static void
renew_parental_timestamps(struct dentry *direntry)
{
- /* BB check if there is a way to get the kernel to do this or if we really need this */
+ /* BB check if there is a way to get the kernel to do this or if we
+ really need this */
do {
direntry->d_time = jiffies;
direntry = direntry->d_parent;
- } while (!IS_ROOT(direntry));
+ } while (!IS_ROOT(direntry));
}
/* Note: caller must free return buffer */
@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry)
char *full_path;
char dirsep;
- if(direntry == NULL)
+ if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry)
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
cifs_bp_rename_retry:
- namelen = pplen;
+ namelen = pplen;
for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
- if(temp == NULL) {
- cERROR(1,("corrupt dentry"));
+ if (temp == NULL) {
+ cERROR(1, ("corrupt dentry"));
return NULL;
}
}
full_path = kmalloc(namelen+1, GFP_KERNEL);
- if(full_path == NULL)
+ if (full_path == NULL)
return full_path;
full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) {
@@ -84,8 +85,8 @@ cifs_bp_rename_retry:
cFYI(0, ("name: %s", full_path + namelen));
}
temp = temp->d_parent;
- if(temp == NULL) {
- cERROR(1,("corrupt dentry"));
+ if (temp == NULL) {
+ cERROR(1, ("corrupt dentry"));
kfree(full_path);
return NULL;
}
@@ -94,7 +95,7 @@ cifs_bp_rename_retry:
cERROR(1,
("did not end path lookup where expected namelen is %d",
namelen));
- /* presumably this is only possible if racing with a rename
+ /* presumably this is only possible if racing with a rename
of one of the parent directories (we can not lock the dentries
above us to prevent this, but retrying should be harmless) */
kfree(full_path);
@@ -106,7 +107,7 @@ cifs_bp_rename_retry:
since the '\' is a valid posix character so we can not switch
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
- strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
+ strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
return full_path;
}
@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- if(nd && (nd->flags & LOOKUP_OPEN)) {
+ if (nd && (nd->flags & LOOKUP_OPEN)) {
int oflags = nd->intent.open.flags;
desiredAccess = 0;
@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
write_only = TRUE;
}
- if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
disposition = FILE_CREATE;
- else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
disposition = FILE_OVERWRITE_IF;
- else if((oflags & O_CREAT) == O_CREAT)
+ else if ((oflags & O_CREAT) == O_CREAT)
disposition = FILE_OPEN_IF;
else {
- cFYI(1,("Create flag not set in create function"));
+ cFYI(1, ("Create flag not set in create function"));
}
}
- /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
+ /* BB add processing to set equivalent of mode - e.g. via CreateX with
+ ACLs */
if (oplockEnabled)
oplock = REQ_OPLOCK;
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf == NULL) {
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
- if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+ if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else
rc = -EIO; /* no NT SMB support fall into legacy open below */
- if(rc == -EIO) {
+ if (rc == -EIO) {
/* old server, retry the open legacy style */
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- }
+ }
if (rc) {
cFYI(1, ("cifs_create returned 0x%x", rc));
} else {
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
- (oplock & CIFS_CREATE_ACTION))
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ (oplock & CIFS_CREATE_ACTION)) {
+ mode &= ~current->fs->umask;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)current->fsuid,
(__u64)current->fsgid,
0 /* dev */,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
@@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- else {
- /* BB implement mode setting via Windows security descriptors */
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
- /* could set r/o dos attribute if mode & 0222 == 0 */
+ } else {
+ /* BB implement mode setting via Windows security
+ descriptors e.g. */
+ /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
+
+ /* Could set r/o dos attribute if mode & 0222 == 0 */
}
/* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb,xid);
+ inode->i_sb, xid);
else {
rc = cifs_get_inode_info(&newinode, full_path,
- buf, inode->i_sb,xid);
- if(newinode) {
+ buf, inode->i_sb, xid);
+ if (newinode) {
newinode->i_mode = mode;
- if((oplock & CIFS_CREATE_ACTION) &&
- (cifs_sb->mnt_cifs_flags &
+ if ((oplock & CIFS_CREATE_ACTION) &&
+ (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID)) {
newinode->i_uid = current->fsuid;
newinode->i_gid = current->fsgid;
@@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
- if((nd->flags & LOOKUP_OPEN) == FALSE) {
+ if ((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle);
- } else if(newinode) {
+ } else if (newinode) {
pCifsFile =
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
-
- if(pCifsFile == NULL)
+
+ if (pCifsFile == NULL)
goto cifs_create_out;
pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid;
@@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
init_MUTEX(&pCifsFile->fh_sem);
mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist);
- atomic_set(&pCifsFile->wrtPending,0);
+ atomic_set(&pCifsFile->wrtPending, 0);
- /* set the following in open now
+ /* set the following in open now
pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist,&pTcon->openFileList);
+ list_add(&pCifsFile->tlist, &pTcon->openFileList);
pCifsInode = CIFS_I(newinode);
- if(pCifsInode) {
+ if (pCifsInode) {
/* if readable file instance put first in list*/
if (write_only == TRUE) {
- list_add_tail(&pCifsFile->flist,
+ list_add_tail(&pCifsFile->flist,
&pCifsInode->openFileList);
} else {
list_add(&pCifsFile->flist,
&pCifsInode->openFileList);
}
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock for inode %p",
+ cFYI(1, ("Exclusive Oplock inode %p",
newinode));
- } else if((oplock & 0xF) == OPLOCK_READ)
+ } else if ((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
write_unlock(&GlobalSMBSeslock);
}
- }
+ }
cifs_create_out:
kfree(buf);
kfree(full_path);
@@ -310,8 +315,8 @@ cifs_create_out:
return rc;
}
-int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
- dev_t device_number)
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
+ dev_t device_number)
{
int rc = -EPERM;
int xid;
@@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL)
+ if (full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ mode &= ~current->fs->umask;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
- mode,(__u64)current->fsuid,(__u64)current->fsgid,
+ mode, (__u64)current->fsuid,
+ (__u64)current->fsgid,
device_number, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, (__u64)-1, (__u64)-1,
device_number, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- if(!rc) {
+ if (!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb,xid);
+ inode->i_sb, xid);
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
else
direntry->d_op = &cifs_dentry_ops;
- if(rc == 0)
+ if (rc == 0)
d_instantiate(direntry, newinode);
}
} else {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO * buf;
- cFYI(1,("sfu compat create special file"));
+ cFYI(1, ("sfu compat create special file"));
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf == NULL) {
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
@@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_CREATE, /* fail if exists */
- GENERIC_WRITE /* BB would
+ GENERIC_WRITE /* BB would
WRITE_OWNER | WRITE_DAC be better? */,
/* Create a file and set the
file attribute to SYSTEM */
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
&fileHandle, &oplock, buf,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB FIXME - add handling for backlevel servers
which need legacy open and check for all
- calls to SMBOpen for fallback to
- SMBLeagcyOpen */
- if(!rc) {
+ calls to SMBOpen for fallback to SMBLeagcyOpen */
+ if (!rc) {
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
- if(S_ISCHR(mode)) {
+ if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
- pdev->minor =
+ pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
- } else if(S_ISBLK(mode)) {
+ } else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
@@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
+ struct nameidata *nd)
{
int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
@@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry));
- /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
-
/* check whether path exists */
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
@@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
}
@@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path,
- parent_dir_inode->i_sb,xid);
+ parent_dir_inode->i_sb, xid);
else
rc = cifs_get_inode_info(&newInode, full_path, NULL,
- parent_dir_inode->i_sb,xid);
+ parent_dir_inode->i_sb, xid);
if ((rc == 0) && (newInode != NULL)) {
if (pTcon->nocase)
@@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode);
- /* since paths are not looked up by component - the parent
+ /* since paths are not looked up by component - the parent
directories are presumed to be good here */
renew_parental_timestamps(direntry);
@@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
else
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, NULL);
- /* if it was once a directory (but how can we tell?) we could do
- shrink_dcache_parent(direntry); */
+ /* if it was once a directory (but how can we tell?) we could do
+ shrink_dcache_parent(direntry); */
} else {
- cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
- rc,full_path));
- /* BB special case check for Access Denied - watch security
- exposure of returning dir info implicitly via different rc
+ cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",
+ rc, full_path));
+ /* BB special case check for Access Denied - watch security
+ exposure of returning dir info implicitly via different rc
if file exists or not but no access BB */
}
@@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
} else {
cFYI(1, ("neg dentry 0x%p name = %s",
direntry, direntry->d_name.name));
- if(time_after(jiffies, direntry->d_time + HZ) ||
+ if (time_after(jiffies, direntry->d_time + HZ) ||
!lookupCacheEnabled) {
d_drop(direntry);
isValid = 0;
- }
+ }
}
return isValid;
@@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
struct dentry_operations cifs_dentry_ops = {
.d_revalidate = cifs_d_revalidate,
-/* d_delete: cifs_d_delete, *//* not needed except for debugging */
- /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
};
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index da12b482ebe..8e375bb4b37 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -2,7 +2,7 @@
* fs/cifs/fcntl.c
*
* vfs operations that deal with the file control API
- *
+ *
* Copyright (C) International Business Machines Corp., 2003,2004
* Author(s): Steve French (sfrench@us.ibm.com)
*
@@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
/* No way on Linux VFS to ask to monitor xattr
changes (and no stream support either */
- if(fcntl_notify_flags & DN_ACCESS) {
+ if (fcntl_notify_flags & DN_ACCESS) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if(fcntl_notify_flags & DN_MODIFY) {
+ if (fcntl_notify_flags & DN_MODIFY) {
/* What does this mean on directories? */
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SIZE;
}
- if(fcntl_notify_flags & DN_CREATE) {
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
+ if (fcntl_notify_flags & DN_CREATE) {
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- if(fcntl_notify_flags & DN_DELETE) {
+ if (fcntl_notify_flags & DN_DELETE) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- if(fcntl_notify_flags & DN_RENAME) {
+ if (fcntl_notify_flags & DN_RENAME) {
/* BB review this - checking various server behaviors */
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_FILE_NAME;
}
- if(fcntl_notify_flags & DN_ATTRIB) {
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
+ if (fcntl_notify_flags & DN_ATTRIB) {
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
FILE_NOTIFY_CHANGE_ATTRIBUTES;
}
-/* if(fcntl_notify_flags & DN_MULTISHOT) {
+/* if (fcntl_notify_flags & DN_MULTISHOT) {
cifs_ntfy_flags |= ;
} */ /* BB fixme - not sure how to handle this with CIFS yet */
-
return cifs_ntfy_flags;
}
@@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
__u16 netfid;
-
- if(experimEnabled == 0)
+ if (experimEnabled == 0)
return 0;
xid = GetXid();
@@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
full_path = build_path_from_dentry(file->f_path.dentry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
rc = -ENOMEM;
} else {
- cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+ cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
- &netfid, &oplock,NULL, cifs_sb->local_nls,
+ &netfid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB fixme - add this handle to a notify handle list */
- if(rc) {
- cFYI(1,("Could not open directory for notify"));
+ if (rc) {
+ cFYI(1, ("Could not open directory for notify"));
} else {
filter = convert_to_cifs_notify_flags(arg);
- if(filter != 0) {
- rc = CIFSSMBNotify(xid, pTcon,
+ if (filter != 0) {
+ rc = CIFSSMBNotify(xid, pTcon,
0 /* no subdirs */, netfid,
filter, file, arg & DN_MULTISHOT,
cifs_sb->local_nls);
@@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
it would close automatically but may be a way
to do it easily when inode freed or when
notify info is cleared/changed */
- cFYI(1,("notify rc %d",rc));
+ cFYI(1, ("notify rc %d", rc));
}
}
-
+
FreeXid(xid);
return rc;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3e87dad3367..f0ff12b3f39 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -986,7 +986,8 @@ mkdir_get_info:
* failed to get it from the server or was set bogus */
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
direntry->d_inode->i_nlink = 2;
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
@@ -1004,7 +1005,7 @@ mkdir_get_info:
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- else {
+ } else {
/* BB to be implemented via Windows secrty descriptors
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls); */
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index e34c7db00f6..a414f1775ae 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -30,7 +30,7 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
-int cifs_ioctl (struct inode * inode, struct file * filep,
+int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg)
{
int rc = -ENOTTY; /* strange error - but the precedent */
@@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
xid = GetXid();
- cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
+ cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg));
cifs_sb = CIFS_SB(inode->i_sb);
#ifdef CONFIG_CIFS_POSIX
tcon = cifs_sb->tcon;
- if(tcon)
+ if (tcon)
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
else {
rc = -EIO;
@@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
}
#endif /* CONFIG_CIFS_POSIX */
- switch(command) {
+ switch (command) {
case CIFS_IOC_CHECKUMOUNT:
- cFYI(1,("User unmount attempted"));
- if(cifs_sb->mnt_uid == current->uid)
+ cFYI(1, ("User unmount attempted"));
+ if (cifs_sb->mnt_uid == current->uid)
rc = 0;
else {
rc = -EACCES;
- cFYI(1,("uids do not match"));
+ cFYI(1, ("uids do not match"));
}
break;
#ifdef CONFIG_CIFS_POSIX
case FS_IOC_GETFLAGS:
- if(CIFS_UNIX_EXTATTR_CAP & caps) {
+ if (CIFS_UNIX_EXTATTR_CAP & caps) {
if (pSMBFile == NULL)
break;
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
&ExtAttrBits, &ExtAttrMask);
- if(rc == 0)
+ if (rc == 0)
rc = put_user(ExtAttrBits &
FS_FL_USER_VISIBLE,
(int __user *)arg);
@@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break;
case FS_IOC_SETFLAGS:
- if(CIFS_UNIX_EXTATTR_CAP & caps) {
- if(get_user(ExtAttrBits,(int __user *)arg)) {
+ if (CIFS_UNIX_EXTATTR_CAP & caps) {
+ if (get_user(ExtAttrBits, (int __user *)arg)) {
rc = -EFAULT;
break;
}
@@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break;
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
extAttrBits, &ExtAttrMask);*/
-
}
- cFYI(1,("set flags not implemented yet"));
+ cFYI(1, ("set flags not implemented yet"));
break;
#endif /* CONFIG_CIFS_POSIX */
default:
- cFYI(1,("unsupported ioctl"));
+ cFYI(1, ("unsupported ioctl"));
break;
}
FreeXid(xid);
return rc;
-}
+}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index aede606132a..8b69fcceb59 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 0023b31e48a..a480b09c79b 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -798,6 +798,11 @@ int ocfs2_map_and_write_splice_data(struct inode *inode,
}
to = from + bytes;
+ BUG_ON(from > PAGE_CACHE_SIZE);
+ BUG_ON(to > PAGE_CACHE_SIZE);
+ BUG_ON(from < cluster_start);
+ BUG_ON(to > cluster_end);
+
if (wc->w_this_page_new)
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
cluster_start, cluster_end, 1);
@@ -809,11 +814,6 @@ int ocfs2_map_and_write_splice_data(struct inode *inode,
goto out;
}
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from > osb->s_clustersize);
- BUG_ON(to > osb->s_clustersize);
-
src = buf->ops->map(sp->s_pipe, buf, 1);
dst = kmap_atomic(wc->w_this_page, KM_USER1);
memcpy(dst + from, src + src_from, bytes);
@@ -890,6 +890,11 @@ int ocfs2_map_and_write_user_data(struct inode *inode,
to = from + bytes;
+ BUG_ON(from > PAGE_CACHE_SIZE);
+ BUG_ON(to > PAGE_CACHE_SIZE);
+ BUG_ON(from < cluster_start);
+ BUG_ON(to > cluster_end);
+
if (wc->w_this_page_new)
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
cluster_start, cluster_end, 1);
@@ -901,11 +906,6 @@ int ocfs2_map_and_write_user_data(struct inode *inode,
goto out;
}
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from > osb->s_clustersize);
- BUG_ON(to > osb->s_clustersize);
-
dst = kmap(wc->w_this_page);
memcpy(dst + from, bp->b_src_buf + src_from, bytes);
kunmap(wc->w_this_page);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index a93620ce4ac..2b205f5d579 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -144,8 +144,7 @@ static struct kobj_type mlog_ktype = {
};
static struct kset mlog_kset = {
- .kobj = {.name = "logmask"},
- .ktype = &mlog_ktype
+ .kobj = {.name = "logmask", .ktype = &mlog_ktype},
};
int mlog_sys_init(struct kset *o2cb_subsys)
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 9345a46ffb3..5d258c40a2f 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -195,6 +195,11 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
unsigned int old_ia_valid = ia->ia_valid;
int ret = 0;
+ /* POSIX UID/GID verification for setting inode attributes */
+ ret = inode_change_ok(inode, ia);
+ if (ret)
+ return ret;
+
/* by providing our own setattr() method, we skip this quotaism */
if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) ||
(old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid))
diff --git a/fs/splice.c b/fs/splice.c
index 12f28281d2b..cb211360273 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
struct page *page;
pgoff_t index, end_index;
loff_t isize;
- size_t total_len;
int error, page_nr;
struct splice_pipe_desc spd = {
.pages = pages,
@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
* Now fill in the holes:
*/
error = 0;
- total_len = 0;
/*
* Lookup the (hopefully) full range of pages we need.
@@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
break;
}
+ }
+fill_it:
+ /*
+ * i_size must be checked after PageUptodate.
+ */
+ isize = i_size_read(mapping->host);
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+ if (unlikely(!isize || index > end_index))
+ break;
+
+ /*
+ * if this is the last page, see if we need to shrink
+ * the length and stop
+ */
+ if (end_index == index) {
+ unsigned int plen;
/*
- * i_size must be checked after ->readpage().
+ * max good bytes in this page
*/
- isize = i_size_read(mapping->host);
- end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
- if (unlikely(!isize || index > end_index))
+ plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+ if (plen <= loff)
break;
/*
- * if this is the last page, see if we need to shrink
- * the length and stop
+ * force quit after adding this page
*/
- if (end_index == index) {
- loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
- if (total_len + loff > isize)
- break;
- /*
- * force quit after adding this page
- */
- len = this_len;
- this_len = min(this_len, loff);
- loff = 0;
- }
+ this_len = min(this_len, plen - loff);
+ len = this_len;
}
-fill_it:
+
partial[page_nr].offset = loff;
partial[page_nr].len = this_len;
len -= this_len;
- total_len += this_len;
loff = 0;
spd.nr_pages++;
index++;
}
/*
- * Release any pages at the end, if we quit early. 'i' is how far
+ * Release any pages at the end, if we quit early. 'page_nr' is how far
* we got, 'nr_pages' is how many pages are in the map.
*/
while (page_nr < nr_pages)
@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
{
ssize_t spliced;
int ret;
+ loff_t isize, left;
+
+ isize = i_size_read(in->f_mapping->host);
+ if (unlikely(*ppos >= isize))
+ return 0;
+
+ left = isize - *ppos;
+ if (unlikely(left < len))
+ len = left;
ret = 0;
spliced = 0;
-
while (len) {
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
@@ -644,7 +654,6 @@ find_page:
* accessed, we are now done!
*/
mark_page_accessed(page);
- balance_dirty_pages_ratelimited(mapping);
out:
page_cache_release(page);
unlock_page(page);
@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
if (err)
ret = err;
}
+ balance_dirty_pages_ratelimited(mapping);
}
return ret;
@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
if (err)
ret = err;
}
+ balance_dirty_pages_ratelimited(mapping);
}
return ret;
@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
- loff_t isize, left;
int ret;
if (unlikely(!in->f_op || !in->f_op->splice_read))
@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
if (unlikely(ret < 0))
return ret;
- isize = i_size_read(in->f_mapping->host);
- if (unlikely(*ppos >= isize))
- return 0;
-
- left = isize - *ppos;
- if (unlikely(left < len))
- len = left;
-
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
@@ -1058,8 +1060,6 @@ out_release:
return ret;
}
-EXPORT_SYMBOL(do_splice_direct);
-
/*
* After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
* location, so checking ->i_pipe is not enough to verify that this is a
diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
index 795fcc26622..01b433de227 100644
--- a/include/asm-arm/arch-at91/at91_shdwc.h
+++ b/include/asm-arm/arch-at91/at91_shdwc.h
@@ -14,8 +14,8 @@
#define AT91_SHDWC_H
#define AT91_SHDW_CR (AT91_SHDWC + 0x00) /* Shut Down Control Register */
-#define AT91_SHDW_SHDW (1 << 0) /* Processor Reset */
-#define AT91_SHDW_KEY (0xff << 24) /* KEY Password */
+#define AT91_SHDW_SHDW (1 << 0) /* Shut Down command */
+#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
#define AT91_SHDW_MR (AT91_SHDWC + 0x04) /* Shut Down Mode Register */
#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */
diff --git a/include/asm-arm/arch-at91/at91_wdt.h b/include/asm-arm/arch-at91/at91_wdt.h
index 7251a344c74..1014e9bf181 100644
--- a/include/asm-arm/arch-at91/at91_wdt.h
+++ b/include/asm-arm/arch-at91/at91_wdt.h
@@ -15,7 +15,7 @@
#define AT91_WDT_CR (AT91_WDT + 0x00) /* Watchdog Control Register */
#define AT91_WDT_WDRSTT (1 << 0) /* Restart */
-#define AT91_WDT_KEY (0xff << 24) /* KEY Password */
+#define AT91_WDT_KEY (0xa5 << 24) /* KEY Password */
#define AT91_WDT_MR (AT91_WDT + 0x04) /* Watchdog Mode Register */
#define AT91_WDT_WDV (0xfff << 0) /* Counter Value */
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
index aeba24347f8..9e99241f3ed 100644
--- a/include/asm-arm/arch-pxa/gpio.h
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -45,7 +45,8 @@ static inline int gpio_direction_input(unsigned gpio)
static inline int gpio_direction_output(unsigned gpio, int value)
{
- return pxa_gpio_mode(gpio | GPIO_OUT | (value ? 0 : GPIO_DFLT_LOW));
+ return pxa_gpio_mode(gpio | GPIO_OUT |
+ (value ? GPIO_DFLT_HIGH : GPIO_DFLT_LOW));
}
static inline int __gpio_get_value(unsigned gpio)
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index be303b3eef4..6931af525da 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -12,6 +12,7 @@
#ifndef _ASM_SYSTEM_H
#define _ASM_SYSTEM_H
+#include <linux/types.h>
#include <linux/linkage.h>
struct thread_struct;
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 92e62ef711e..c5f20df780e 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -52,21 +52,6 @@
.endm
#endif /* CONFIG_MIPS_MT_SMTC */
-#ifdef CONFIG_CPU_SB1
- .macro fpu_enable_hazard
- .set push
- .set noreorder
- .set mips2
- SSNOP
- bnezl $0, .+4
- SSNOP
- .set pop
- .endm
-#else
- .macro fpu_enable_hazard
- .endm
-#endif
-
/*
* Temporary until all gas have MT ASE support
*/
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index d995413e11f..ffe245b4258 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -238,10 +238,11 @@ static inline int test_and_set_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -254,11 +255,9 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -277,25 +276,22 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- int retval;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a |= mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
/*
@@ -310,6 +306,7 @@ static inline int test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -327,12 +324,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
#ifdef CONFIG_CPU_MIPSR2
} else if (__builtin_constant_p(nr)) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
"1: " __LL "%0, %1 # test_and_clear_bit \n"
@@ -346,12 +341,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "ri" (bit), "m" (*m)
: "memory");
-
- return res;
#endif
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -371,25 +364,22 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- int retval;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a &= ~mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
/*
@@ -404,10 +394,11 @@ static inline int test_and_change_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -420,11 +411,9 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -443,24 +432,22 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
- unsigned long mask, retval;
+ unsigned long mask;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a ^= mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
#include <asm-generic/bitops/non-atomic.h>
diff --git a/include/asm-mips/mips-boards/prom.h b/include/asm-mips/mips-boards/prom.h
index daaf9f98fc6..a9db576a976 100644
--- a/include/asm-mips/mips-boards/prom.h
+++ b/include/asm-mips/mips-boards/prom.h
@@ -33,6 +33,7 @@ extern void prom_meminit(void);
extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
extern void mips_display_message(const char *str);
extern void mips_display_word(unsigned int num);
+extern void mips_scroll_message(void);
extern int get_ethernet_addr(char *ethernet_addr);
/* Memory descriptor management. */
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 7afa1fdf70c..ed33366b85b 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -17,6 +17,18 @@
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#define STATMASK 0x3f
+#else
+#define STATMASK 0x1f
+#endif
+
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -236,10 +248,10 @@
.set reorder
.set noat
mfc0 a0, CP0_STATUS
- ori a0, 0x1f
- xori a0, 0x1f
- mtc0 a0, CP0_STATUS
li v1, 0xff00
+ ori a0, STATMASK
+ xori a0, STATMASK
+ mtc0 a0, CP0_STATUS
and a0, v1
LONG_L v0, PT_STATUS(sp)
nor v1, $0, v1
@@ -249,10 +261,6 @@
LONG_L $31, PT_R31(sp)
LONG_L $28, PT_R28(sp)
LONG_L $25, PT_R25(sp)
-#ifdef CONFIG_64BIT
- LONG_L $8, PT_R8(sp)
- LONG_L $9, PT_R9(sp)
-#endif
LONG_L $7, PT_R7(sp)
LONG_L $6, PT_R6(sp)
LONG_L $5, PT_R5(sp)
@@ -273,16 +281,6 @@
.endm
#else
-/*
- * For SMTC kernel, global IE should be left set, and interrupts
- * controlled exclusively via IXMT.
- */
-
-#ifdef CONFIG_MIPS_MT_SMTC
-#define STATMASK 0x1e
-#else
-#define STATMASK 0x1f
-#endif
.macro RESTORE_SOME
.set push
.set reorder
@@ -385,9 +383,9 @@
.macro CLI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1f
+ li t1, ST0_CU0 | STATMASK
or t0, t1
- xori t0, 0x1f
+ xori t0, STATMASK
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
@@ -420,9 +418,9 @@
.macro STI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1f
+ li t1, ST0_CU0 | STATMASK
or t0, t1
- xori t0, 0x1e
+ xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
@@ -451,7 +449,8 @@
.endm
/*
- * Just move to kernel mode and leave interrupts as they are.
+ * Just move to kernel mode and leave interrupts as they are. Note
+ * for the R3000 this means copying the previous enable from IEp.
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
@@ -482,9 +481,14 @@
move ra, t0
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1e
+ li t1, ST0_CU0 | (STATMASK & ~1)
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ andi t2, t0, ST0_IEP
+ srl t2, 2
+ or t0, t2
+#endif
or t0, t1
- xori t0, 0x1e
+ xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC
_ehb
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 2f1087b3a20..59d6fec8fbf 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -336,16 +336,20 @@
#define __NR_epoll_pwait (__NR_Linux + 313)
#define __NR_ioprio_set (__NR_Linux + 314)
#define __NR_ioprio_get (__NR_Linux + 315)
+#define __NR_utimensat (__NR_Linux + 316)
+#define __NR_signalfd (__NR_Linux + 317)
+#define __NR_timerfd (__NR_Linux + 318)
+#define __NR_eventfd (__NR_Linux + 319)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 315
+#define __NR_Linux_syscalls 319
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 315
+#define __NR_O32_Linux_syscalls 319
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -628,16 +632,20 @@
#define __NR_epoll_pwait (__NR_Linux + 272)
#define __NR_ioprio_set (__NR_Linux + 273)
#define __NR_ioprio_get (__NR_Linux + 274)
+#define __NR_utimensat (__NR_Linux + 275)
+#define __NR_signalfd (__NR_Linux + 276)
+#define __NR_timerfd (__NR_Linux + 277)
+#define __NR_eventfd (__NR_Linux + 278)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 274
+#define __NR_Linux_syscalls 278
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 274
+#define __NR_64_Linux_syscalls 278
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -924,16 +932,20 @@
#define __NR_epoll_pwait (__NR_Linux + 276)
#define __NR_ioprio_set (__NR_Linux + 277)
#define __NR_ioprio_get (__NR_Linux + 278)
+#define __NR_utimensat (__NR_Linux + 279)
+#define __NR_signalfd (__NR_Linux + 280)
+#define __NR_timerfd (__NR_Linux + 281)
+#define __NR_eventfd (__NR_Linux + 282)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 278
+#define __NR_Linux_syscalls 282
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 278
+#define __NR_N32_Linux_syscalls 282
#ifdef __KERNEL__
@@ -949,7 +961,6 @@
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
#define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE
diff --git a/include/asm-sh/se73180.h b/include/asm-sh/se73180.h
index 3a4acb3e38a..907c062b4c9 100644
--- a/include/asm-sh/se73180.h
+++ b/include/asm-sh/se73180.h
@@ -1,9 +1,7 @@
-#ifndef __ASM_SH_HITACHI_SE73180_H
-#define __ASM_SH_HITACHI_SE73180_H
+#ifndef __ASM_SH_SE73180_H
+#define __ASM_SH_SE73180_H
/*
- * include/asm-sh/se/se73180.h
- *
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
*
* SH-Mobile SolutionEngine 73180 support
@@ -62,4 +60,7 @@
#define __IO_PREFIX sh73180se
#include <asm/io_generic.h>
-#endif /* __ASM_SH_HITACHI_SE73180_H */
+/* arch/sh/boards/se/73180/irq.c */
+int shmse_irq_demux(int irq);
+
+#endif /* __ASM_SH_SE73180_H */
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index d815649617a..1c1e0d933ee 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_BITOPS_H
@@ -31,53 +31,30 @@
#if XCHAL_HAVE_NSA
-static __inline__ int __cntlz (unsigned long x)
+static inline unsigned long __cntlz (unsigned long x)
{
int lz;
asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
- return 31 - lz;
+ return lz;
}
-#else
-
-static __inline__ int __cntlz (unsigned long x)
-{
- unsigned long sum, x1, x2, x4, x8, x16;
- x1 = x & 0xAAAAAAAA;
- x2 = x & 0xCCCCCCCC;
- x4 = x & 0xF0F0F0F0;
- x8 = x & 0xFF00FF00;
- x16 = x & 0xFFFF0000;
- sum = x2 ? 2 : 0;
- sum += (x16 != 0) * 16;
- sum += (x8 != 0) * 8;
- sum += (x4 != 0) * 4;
- sum += (x1 != 0);
-
- return sum;
-}
-
-#endif
-
/*
* ffz: Find first zero in word. Undefined if no zero exists.
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
-static __inline__ int ffz(unsigned long x)
+static inline int ffz(unsigned long x)
{
- if ((x = ~x) == 0)
- return 32;
- return __cntlz(x & -x);
+ return 31 - __cntlz(~x & -~x);
}
/*
* __ffs: Find first bit set in word. Return 0 for bit 0
*/
-static __inline__ int __ffs(unsigned long x)
+static inline int __ffs(unsigned long x)
{
- return __cntlz(x & -x);
+ return 31 - __cntlz(x & -x);
}
/*
@@ -86,9 +63,9 @@ static __inline__ int __ffs(unsigned long x)
* differs in spirit from the above ffz (man ffs).
*/
-static __inline__ int ffs(unsigned long x)
+static inline int ffs(unsigned long x)
{
- return __cntlz(x & -x) + 1;
+ return 32 - __cntlz(x & -x);
}
/*
@@ -96,20 +73,36 @@ static __inline__ int ffs(unsigned long x)
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-static __inline__ int fls (unsigned int x)
+static inline int fls (unsigned int x)
{
- return __cntlz(x);
+ return 32 - __cntlz(x);
}
+
+#else
+
+/* Use the generic implementation if we don't have the nsa/nsau instructions. */
+
+# include <asm-generic/bitops/ffs.h>
+# include <asm-generic/bitops/__ffs.h>
+# include <asm-generic/bitops/ffz.h>
+# include <asm-generic/bitops/fls.h>
+
+#endif
+
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
+# define ext2_set_bit_atomic(lock,nr,addr) \
+ test_and_set_bit((nr), (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) \
+ test_and_clear_bit((nr), (unsigned long*)(addr))
#elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
+# define ext2_set_bit_atomic(lock,nr,addr) \
+ test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) \
+ test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
#else
# error processor byte order undefined!
#endif
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
index 0f540a5f4c0..765edf17a9a 100644
--- a/include/asm-xtensa/byteorder.h
+++ b/include/asm-xtensa/byteorder.h
@@ -12,6 +12,7 @@
#define _XTENSA_BYTEORDER_H
#include <asm/types.h>
+#include <linux/compiler.h>
static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
@@ -78,4 +79,4 @@ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
# error processor byte order undefined!
#endif
-#endif /* __ASM_XTENSA_BYTEORDER_H */
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
index bd09ec02d57..aa212103455 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/include/asm-xtensa/coprocessor.h
@@ -64,6 +64,7 @@ typedef struct {
# define COPROCESSOR_INFO_SIZE 8
# endif
#endif
+#endif /* XCHAL_HAVE_CP */
#ifndef __ASSEMBLY__
@@ -74,8 +75,11 @@ extern void save_coprocessor_registers(void*, int);
# else
# define release_coprocessors(task)
# endif
-#endif
-#endif
+typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE]
+ __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
+
+#endif /* !__ASSEMBLY__ */
+
#endif /* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
index 20965e3af1d..f35678cb0a9 100644
--- a/include/asm-xtensa/div64.h
+++ b/include/asm-xtensa/div64.h
@@ -5,21 +5,12 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_DIV64_H
#define _XTENSA_DIV64_H
-#include <linux/types.h>
+#include <asm-generic/div64.h>
-#define do_div(n,base) ({ \
- int __res = n % ((unsigned int) base); \
- n /= (unsigned int) base; \
- __res; })
-
-static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor)
-{
- return dividend / divisor;
-}
-#endif
+#endif /* _XTENSA_DIV64_H */
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index f0f9fd8560a..1569b53cec9 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -13,7 +13,6 @@
#ifndef _XTENSA_ELF_H
#define _XTENSA_ELF_H
-#include <asm/variant/core.h>
#include <asm/ptrace.h>
/* Xtensa processor ELF architecture-magic number */
@@ -49,7 +48,7 @@ typedef struct {
elf_greg_t lcount;
elf_greg_t sar;
elf_greg_t syscall;
- elf_greg_t ar[XCHAL_NUM_AREGS];
+ elf_greg_t ar[64];
} xtensa_gregset_t;
#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
index 0609fc691b7..46ab12db573 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/include/asm-xtensa/fcntl.h
@@ -1,99 +1 @@
-/*
- * include/asm-xtensa/fcntl.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_FCNTL_H
-#define _XTENSA_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif /* _XTENSA_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index 92f948392eb..c0fd8e5b451 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -14,6 +14,7 @@
#define _XTENSA_MMU_CONTEXT_H
#include <linux/stringify.h>
+#include <linux/sched.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index c631d006194..1213cde7543 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -131,6 +131,6 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#endif /* __KERNEL__ */
#include <asm-generic/memory_model.h>
+#endif /* __KERNEL__ */
#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
index 6f281392e3f..ce3a336cad0 100644
--- a/include/asm-xtensa/param.h
+++ b/include/asm-xtensa/param.h
@@ -11,15 +11,13 @@
#ifndef _XTENSA_PARAM_H
#define _XTENSA_PARAM_H
-#include <asm/variant/core.h>
-
#ifdef __KERNEL__
# define HZ 100 /* internal timer frequency */
# define USER_HZ 100 /* for user interfaces in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */
#endif
-#define EXEC_PAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+#define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index 1b7fe363fad..77ff02d307b 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -11,8 +11,6 @@
#ifndef _XTENSA_PTRACE_H
#define _XTENSA_PTRACE_H
-#include <asm/variant/core.h>
-
/*
* Kernel stack
*
@@ -101,7 +99,8 @@ struct pt_regs {
unsigned long windowbase; /* 48 */
unsigned long windowstart; /* 52 */
unsigned long syscall; /* 56 */
- int reserved[2]; /* 64 */
+ unsigned long icountlevel; /* 60 */
+ int reserved[1]; /* 64 */
/* Make sure the areg field is 16 bytes aligned. */
int align[0] __attribute__ ((aligned(16)));
@@ -113,6 +112,9 @@ struct pt_regs {
};
#ifdef __KERNEL__
+
+#include <asm/variant/core.h>
+
# define task_pt_regs(tsk) ((struct pt_regs*) \
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
index d3b65bfa71c..c8cc16c3da9 100644
--- a/include/asm-xtensa/shmparam.h
+++ b/include/asm-xtensa/shmparam.h
@@ -9,8 +9,6 @@
#ifndef _XTENSA_SHMPARAM_H
#define _XTENSA_SHMPARAM_H
-#include <asm/processor.h>
-
/*
* Xtensa can have variable size caches, and if
* the size of single way is larger than the page size,
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
index a7517729141..e3381cee505 100644
--- a/include/asm-xtensa/sigcontext.h
+++ b/include/asm-xtensa/sigcontext.h
@@ -5,21 +5,12 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 - 2003 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_SIGCONTEXT_H
#define _XTENSA_SIGCONTEXT_H
-#define _ASMLANGUAGE
-#include <asm/processor.h>
-#include <asm/coprocessor.h>
-
-
-struct _cpstate {
- unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
-} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
-
struct sigcontext {
unsigned long oldmask;
@@ -27,18 +18,13 @@ struct sigcontext {
/* CPU registers */
unsigned long sc_pc;
unsigned long sc_ps;
- unsigned long sc_wmask;
- unsigned long sc_windowbase;
- unsigned long sc_windowstart;
unsigned long sc_lbeg;
unsigned long sc_lend;
unsigned long sc_lcount;
unsigned long sc_sar;
- unsigned long sc_depc;
- unsigned long sc_dareg0;
- unsigned long sc_treg[4];
- unsigned long sc_areg[XCHAL_NUM_AREGS];
- struct _cpstate *sc_cpstate;
+ unsigned long sc_acclo;
+ unsigned long sc_acchi;
+ unsigned long sc_a[16];
};
-#endif /* __ASM_XTENSA_SIGCONTEXT_H */
+#endif /* _XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
index 5ae34ab7159..3fa29799b43 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/include/asm-xtensa/thread_info.h
@@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_IRET 5 /* return with iret */
#define TIF_MEMDIE 6
+#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -125,6 +126,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_IRET (1<<TIF_IRET)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
index 8a7fb6964ce..9bd34024431 100644
--- a/include/asm-xtensa/unistd.h
+++ b/include/asm-xtensa/unistd.h
@@ -485,8 +485,8 @@ __SYSCALL(217, sys_sched_get_priority_min, 1)
__SYSCALL(218, sys_sched_rr_get_interval, 2)
#define __NR_sched_yield 219
__SYSCALL(219, sys_sched_yield, 0)
-#define __NR_sigreturn 222
-__SYSCALL(222, xtensa_sigreturn, 0)
+#define __NR_available222 222
+__SYSCALL(222, sys_ni_syscall, 0)
/* Signal Handling */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index edb31bfff68..703febb2df3 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -151,6 +151,7 @@ enum {
ATA_CMD_WRITE_MULTI_EXT = 0x39,
ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
ATA_CMD_SET_FEATURES = 0xEF,
+ ATA_CMD_SET_MULTI = 0xC6,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
@@ -249,7 +250,7 @@ enum ata_tf_protocols {
/* ATA taskfile protocols */
ATA_PROT_UNKNOWN, /* unknown/invalid */
ATA_PROT_NODATA, /* no data */
- ATA_PROT_PIO, /* PIO single sector */
+ ATA_PROT_PIO, /* PIO data xfer */
ATA_PROT_DMA, /* DMA */
ATA_PROT_NCQ, /* NCQ */
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index a461f76fb00..dc77fed7b28 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,9 @@
* to achieve effects such as fast scrolling by changing the origin.
*/
+#ifndef _LINUX_CONSOLE_STRUCT_H
+#define _LINUX_CONSOLE_STRUCT_H
+
#include <linux/wait.h>
#include <linux/vt.h>
#include <linux/workqueue.h>
@@ -130,3 +133,5 @@ extern void vc_SAK(struct work_struct *work);
#define CUR_DEFAULT CUR_UNDERLINE
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
+
+#endif /* _LINUX_CONSOLE_STRUCT_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 07aba87d369..1e365acdd36 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1001,6 +1001,7 @@ struct ide_driver_s {
struct device_driver gen_driver;
int (*probe)(ide_drive_t *);
void (*remove)(ide_drive_t *);
+ void (*resume)(ide_drive_t *);
void (*shutdown)(ide_drive_t *);
#ifdef CONFIG_IDE_PROC_FS
ide_proc_entry_t *proc;
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index c0f7aec331c..ae04901aa09 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -3,6 +3,7 @@
#ifdef __KERNEL__
+#include <linux/bitmap.h>
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
@@ -10,28 +11,9 @@
struct ipv4_devconf
{
- int accept_redirects;
- int send_redirects;
- int secure_redirects;
- int shared_media;
- int accept_source_route;
- int rp_filter;
- int proxy_arp;
- int bootp_relay;
- int log_martians;
- int forwarding;
- int mc_forwarding;
- int tag;
- int arp_filter;
- int arp_announce;
- int arp_ignore;
- int arp_accept;
- int medium_id;
- int no_xfrm;
- int no_policy;
- int force_igmp_version;
- int promote_secondaries;
void *sysctl;
+ int data[__NET_IPV4_CONF_MAX - 1];
+ DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
};
extern struct ipv4_devconf ipv4_devconf;
@@ -60,30 +42,70 @@ struct in_device
struct rcu_head rcu_head;
};
-#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding)
-#define IN_DEV_MFORWARD(in_dev) (ipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)
-#define IN_DEV_RPFILTER(in_dev) (ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
-#define IN_DEV_SOURCE_ROUTE(in_dev) (ipv4_devconf.accept_source_route && (in_dev)->cnf.accept_source_route)
-#define IN_DEV_BOOTP_RELAY(in_dev) (ipv4_devconf.bootp_relay && (in_dev)->cnf.bootp_relay)
-
-#define IN_DEV_LOG_MARTIANS(in_dev) (ipv4_devconf.log_martians || (in_dev)->cnf.log_martians)
-#define IN_DEV_PROXY_ARP(in_dev) (ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp)
-#define IN_DEV_SHARED_MEDIA(in_dev) (ipv4_devconf.shared_media || (in_dev)->cnf.shared_media)
-#define IN_DEV_TX_REDIRECTS(in_dev) (ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
-#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
-#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
-#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id)
-#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
+#define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
+#define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
+
+static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
+{
+ index--;
+ return in_dev->cnf.data[index];
+}
+
+static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
+ int val)
+{
+ index--;
+ set_bit(index, in_dev->cnf.state);
+ in_dev->cnf.data[index] = val;
+}
+
+static inline void ipv4_devconf_setall(struct in_device *in_dev)
+{
+ bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1);
+}
+
+#define IN_DEV_CONF_GET(in_dev, attr) \
+ ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr)
+#define IN_DEV_CONF_SET(in_dev, attr, val) \
+ ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+
+#define IN_DEV_ANDCONF(in_dev, attr) \
+ (IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_ORCONF(in_dev, attr) \
+ (IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_MAXCONF(in_dev, attr) \
+ (max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
+
+#define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
+#define IN_DEV_MFORWARD(in_dev) (IPV4_DEVCONF_ALL(MC_FORWARDING) && \
+ IPV4_DEVCONF((in_dev)->cnf, \
+ MC_FORWARDING))
+#define IN_DEV_RPFILTER(in_dev) IN_DEV_ANDCONF((in_dev), RP_FILTER)
+#define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \
+ ACCEPT_SOURCE_ROUTE)
+#define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
+
+#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
+#define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP)
+#define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA)
+#define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS)
+#define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \
+ SECURE_REDIRECTS)
+#define IN_DEV_IDTAG(in_dev) IN_DEV_CONF_GET(in_dev, TAG)
+#define IN_DEV_MEDIUM_ID(in_dev) IN_DEV_CONF_GET(in_dev, MEDIUM_ID)
+#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
+ IN_DEV_ORCONF((in_dev), \
+ PROMOTE_SECONDARIES)
#define IN_DEV_RX_REDIRECTS(in_dev) \
((IN_DEV_FORWARD(in_dev) && \
- (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
+ IN_DEV_ANDCONF((in_dev), ACCEPT_REDIRECTS)) \
|| (!IN_DEV_FORWARD(in_dev) && \
- (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+ IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
-#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
-#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
-#define IN_DEV_ARP_IGNORE(in_dev) (max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
+#define IN_DEV_ARPFILTER(in_dev) IN_DEV_ORCONF((in_dev), ARPFILTER)
+#define IN_DEV_ARP_ANNOUNCE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
+#define IN_DEV_ARP_IGNORE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
struct in_ifaddr
{
@@ -108,7 +130,6 @@ extern struct net_device *ip_dev_find(__be32 addr);
extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
extern int devinet_ioctl(unsigned int cmd, void __user *);
extern void devinet_init(void);
-extern struct in_device *inetdev_init(struct net_device *dev);
extern struct in_device *inetdev_by_index(int);
extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 45353d757cd..7a485250591 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -218,10 +218,14 @@ enum {
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
-extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen);
-extern void print_hex_dump(const char *level, int prefix_type,
- void *buf, size_t len);
+extern void hex_dump_to_buffer(const void *buf, size_t len,
+ int rowsize, int groupsize,
+ char *linebuf, size_t linebuflen, bool ascii);
+extern void print_hex_dump(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii);
+extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len);
#define hex_asc(x) "0123456789abcdef"[x]
#ifdef DEBUG
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a6a3113120a..745c4f9b4ca 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -753,6 +753,7 @@ extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
+extern int ata_sff_port_start (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 2f46dd728ee..e992cd6b28f 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -264,6 +264,26 @@ ipt_get_target(struct ipt_entry *e)
__ret; \
})
+/* fn returns 0 to continue iteration */
+#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
+({ \
+ unsigned int __i, __n; \
+ int __ret = 0; \
+ struct ipt_entry *__entry; \
+ \
+ for (__i = 0, __n = 0; __i < (size); \
+ __i += __entry->next_offset, __n++) { \
+ __entry = (void *)(entries) + __i; \
+ if (__n < n) \
+ continue; \
+ \
+ __ret = fn(__entry , ## args); \
+ if (__ret != 0) \
+ break; \
+ } \
+ __ret; \
+})
+
/*
* Main firewall chains definitions and global var's definitions.
*/
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 6a115cffea3..9a03b47da60 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1233,6 +1233,8 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E
#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
#define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_TT128 0x9128
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 8bcbc54e1b4..c8884f97122 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -16,6 +16,21 @@ struct pipe_buffer {
unsigned int flags;
};
+struct pipe_inode_info {
+ wait_queue_head_t wait;
+ unsigned int nrbufs, curbuf;
+ struct page *tmp_page;
+ unsigned int readers;
+ unsigned int writers;
+ unsigned int waiting_writers;
+ unsigned int r_counter;
+ unsigned int w_counter;
+ struct fasync_struct *fasync_readers;
+ struct fasync_struct *fasync_writers;
+ struct inode *inode;
+ struct pipe_buffer bufs[PIPE_BUFFERS];
+};
+
/*
* Note on the nesting of these functions:
*
@@ -38,21 +53,6 @@ struct pipe_buf_operations {
void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
-struct pipe_inode_info {
- wait_queue_head_t wait;
- unsigned int nrbufs, curbuf;
- struct page *tmp_page;
- unsigned int readers;
- unsigned int writers;
- unsigned int waiting_writers;
- unsigned int r_counter;
- unsigned int w_counter;
- struct fasync_struct *fasync_readers;
- struct fasync_struct *fasync_writers;
- struct inode *inode;
- struct pipe_buffer bufs[PIPE_BUFFERS];
-};
-
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 7c1ffbab786..a8a6ea809da 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -63,7 +63,7 @@ enum rfkill_state {
* This structure represents a RF switch located on a network device.
*/
struct rfkill {
- char *name;
+ const char *name;
enum rfkill_type type;
enum rfkill_state state;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d58e74b9836..693f0e6c54d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1162,6 +1162,7 @@ static inline void put_task_struct(struct task_struct *t)
/* Not implemented yet, only for 486*/
#define PF_STARTING 0x00000002 /* being created */
#define PF_EXITING 0x00000004 /* getting shut down */
+#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 0764c829d96..a0ad37463d6 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -70,11 +70,8 @@ extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
*/
static inline int kmalloc_index(size_t size)
{
- /*
- * We should return 0 if size == 0 but we use the smallest object
- * here for SLAB legacy reasons.
- */
- WARN_ON_ONCE(size == 0);
+ if (!size)
+ return 0;
if (size > KMALLOC_MAX_SIZE)
return -1;
@@ -153,13 +150,25 @@ static inline struct kmem_cache *kmalloc_slab(size_t size)
#define SLUB_DMA 0
#endif
+
+/*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc(s, flags);
} else
@@ -172,7 +181,7 @@ static inline void *kzalloc(size_t size, gfp_t flags)
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_zalloc(s, flags);
} else
@@ -188,7 +197,7 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc_node(s, flags, node);
} else
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e7560389079..d16a2b57dc8 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -243,8 +243,7 @@ struct v4l2_capability
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
-#define V4L2_CAP_VIDEO_OUTPUT_POS 0x00000200 /* Video output can have x,y coords */
-#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000400 /* Can do video output overlay */
+#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
@@ -616,12 +615,16 @@ struct v4l2_framebuffer
#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
+#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
+#define V4L2_FBUF_CAP_GLOBAL_INV_ALPHA 0x0080
/* Flags for the 'flags' field. */
#define V4L2_FBUF_FLAG_PRIMARY 0x0001
#define V4L2_FBUF_FLAG_OVERLAY 0x0002
#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
+#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
+#define V4L2_FBUF_FLAG_GLOBAL_INV_ALPHA 0x0040
struct v4l2_clip
{
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 4f90f5554fa..a6bb94530cf 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -203,12 +203,10 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb,
#ifdef CONFIG_NETLABEL
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
-int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
-int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_validate(unsigned char **option);
@@ -220,9 +218,9 @@ static inline void cipso_v4_error(struct sk_buff *skb,
return;
}
-static inline int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr)
+static inline int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
@@ -233,12 +231,6 @@ static inline int cipso_v4_sock_getattr(struct sock *sk,
return -ENOSYS;
}
-static inline int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- return -ENOSYS;
-}
-
static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index ed3a8872c6c..83e41dd15cc 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -64,7 +64,7 @@ struct fib_rules_ops
void (*flush_cache)(void);
int nlgroup;
- struct nla_policy *policy;
+ const struct nla_policy *policy;
struct list_head *rules_list;
struct module *owner;
};
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index adff4c898d5..b6eaca122db 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -60,7 +60,7 @@ struct genl_ops
{
u8 cmd;
unsigned int flags;
- struct nla_policy *policy;
+ const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
struct genl_info *info);
int (*dumpit)(struct sk_buff *skb,
diff --git a/include/net/ip.h b/include/net/ip.h
index bb207db0367..abf2820a112 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -143,6 +143,7 @@ struct ip_reply_arg {
__wsum csum;
int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
+ int bound_dev_if;
};
void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 5a4a0366c24..69252cbe05b 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -213,7 +213,7 @@ extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
#endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */
-extern struct nla_policy rtm_ipv4_policy[];
+extern const struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void);
extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
struct net_device *dev, __be32 *spec_dst, u32 *itag);
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 83da7e1f0d3..9b7d6f2ac9a 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -332,17 +332,15 @@ static inline int netlbl_secattr_catmap_setrng(
*/
#ifdef CONFIG_NETLABEL
-int netlbl_socket_setattr(const struct socket *sock,
- const struct netlbl_lsm_secattr *secattr);
+int netlbl_sock_setattr(struct sock *sk,
+ const struct netlbl_lsm_secattr *secattr);
int netlbl_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr);
-int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
void netlbl_skbuff_err(struct sk_buff *skb, int error);
#else
-static inline int netlbl_socket_setattr(const struct socket *sock,
+static inline int netlbl_sock_setattr(struct sock *sk,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
@@ -354,12 +352,6 @@ static inline int netlbl_sock_getattr(struct sock *sk,
return -ENOSYS;
}
-static inline int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- return -ENOSYS;
-}
-
static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0bf325c29af..7b510a9edb9 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -222,10 +222,10 @@ extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
gfp_t flags);
extern int nla_validate(struct nlattr *head, int len, int maxtype,
- struct nla_policy *policy);
+ const struct nla_policy *policy);
extern int nla_parse(struct nlattr *tb[], int maxtype,
struct nlattr *head, int len,
- struct nla_policy *policy);
+ const struct nla_policy *policy);
extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype);
extern size_t nla_strlcpy(char *dst, const struct nlattr *nla,
size_t dstsize);
@@ -360,7 +360,7 @@ static inline struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
*/
static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen,
struct nlattr *tb[], int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL;
@@ -392,7 +392,7 @@ static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh,
* @policy: validation policy
*/
static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL;
@@ -729,7 +729,7 @@ static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype)
*/
static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
struct nlattr *nla,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
}
@@ -990,7 +990,7 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
* Returns 0 on success or a negative error code.
*/
static inline int nla_validate_nested(struct nlattr *start, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
}
diff --git a/include/net/udp.h b/include/net/udp.h
index 496f89d45c8..98755ebaf16 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,16 +119,9 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
}
-struct udp_get_port_ops {
- int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
- int (*saddr_any)(const struct sock *sk);
- unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
- const struct sock *sk);
-};
-
/* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops);
+ int (*saddr_cmp)(const struct sock *, const struct sock *));
extern void udp_err(struct sk_buff *, u32);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 50b4b424d1c..635b0eafca9 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
extern void udplite4_register(void);
extern int udplite_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops);
+ int (*scmp)(const struct sock *, const struct sock *));
#endif /* _UDPLITE_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 90185e8b335..311f25af5e1 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -964,7 +964,7 @@ struct xfrmk_spdinfo {
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
+extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
@@ -1020,13 +1020,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+extern int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
struct flowi *fl, int family, int strict);
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b888c24e43..5c8ecbaa19a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -892,13 +892,29 @@ fastcall NORET_TYPE void do_exit(long code)
if (unlikely(tsk->flags & PF_EXITING)) {
printk(KERN_ALERT
"Fixing recursive fault but reboot is needed!\n");
+ /*
+ * We can do this unlocked here. The futex code uses
+ * this flag just to verify whether the pi state
+ * cleanup has been done or not. In the worst case it
+ * loops once more. We pretend that the cleanup was
+ * done as there is no way to return. Either the
+ * OWNER_DIED bit is set by now or we push the blocked
+ * task into the wait for ever nirwana as well.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
}
+ /*
+ * tsk->flags are checked in the futex code to protect against
+ * an exiting task cleaning up the robust pi futexes.
+ */
+ spin_lock_irq(&tsk->pi_lock);
tsk->flags |= PF_EXITING;
+ spin_unlock_irq(&tsk->pi_lock);
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
@@ -912,7 +928,7 @@ fastcall NORET_TYPE void do_exit(long code)
}
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
- hrtimer_cancel(&tsk->signal->real_timer);
+ hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
@@ -965,6 +981,12 @@ fastcall NORET_TYPE void do_exit(long code)
* Make sure we are holding no locks:
*/
debug_check_no_locks_held(tsk);
+ /*
+ * We can do this unlocked here. The futex code uses this flag
+ * just to verify whether the pi state cleanup has been done
+ * or not. In the worst case it loops once more.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
diff --git a/kernel/futex.c b/kernel/futex.c
index b7ce15c67e3..3b7f7713d9a 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -430,10 +430,6 @@ static struct task_struct * futex_find_get_task(pid_t pid)
p = NULL;
goto out_unlock;
}
- if (p->exit_state != 0) {
- p = NULL;
- goto out_unlock;
- }
get_task_struct(p);
out_unlock:
rcu_read_unlock();
@@ -502,7 +498,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
struct futex_q *this, *next;
struct plist_head *head;
struct task_struct *p;
- pid_t pid;
+ pid_t pid = uval & FUTEX_TID_MASK;
head = &hb->chain;
@@ -520,6 +516,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
return -EINVAL;
WARN_ON(!atomic_read(&pi_state->refcount));
+ WARN_ON(pid && pi_state->owner &&
+ pi_state->owner->pid != pid);
atomic_inc(&pi_state->refcount);
*ps = pi_state;
@@ -530,15 +528,33 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
/*
* We are the first waiter - try to look up the real owner and attach
- * the new pi_state to it, but bail out when the owner died bit is set
- * and TID = 0:
+ * the new pi_state to it, but bail out when TID = 0
*/
- pid = uval & FUTEX_TID_MASK;
- if (!pid && (uval & FUTEX_OWNER_DIED))
+ if (!pid)
return -ESRCH;
p = futex_find_get_task(pid);
- if (!p)
- return -ESRCH;
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ /*
+ * We need to look at the task state flags to figure out,
+ * whether the task is exiting. To protect against the do_exit
+ * change of the task flags, we do this protected by
+ * p->pi_lock:
+ */
+ spin_lock_irq(&p->pi_lock);
+ if (unlikely(p->flags & PF_EXITING)) {
+ /*
+ * The task is on the way out. When PF_EXITPIDONE is
+ * set, we know that the task has finished the
+ * cleanup:
+ */
+ int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN;
+
+ spin_unlock_irq(&p->pi_lock);
+ put_task_struct(p);
+ return ret;
+ }
pi_state = alloc_pi_state();
@@ -551,7 +567,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
/* Store the key for possible exit cleanups: */
pi_state->key = *key;
- spin_lock_irq(&p->pi_lock);
WARN_ON(!list_empty(&pi_state->list));
list_add(&pi_state->list, &p->pi_state_list);
pi_state->owner = p;
@@ -618,6 +633,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
* preserve the owner died bit.)
*/
if (!(uval & FUTEX_OWNER_DIED)) {
+ int ret = 0;
+
newval = FUTEX_WAITERS | new_owner->pid;
/* Keep the FUTEX_WAITER_REQUEUED flag if it was set */
newval |= (uval & FUTEX_WAITER_REQUEUED);
@@ -625,10 +642,15 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
pagefault_enable();
+
if (curval == -EFAULT)
- return -EFAULT;
+ ret = -EFAULT;
if (curval != uval)
- return -EINVAL;
+ ret = -EINVAL;
+ if (ret) {
+ spin_unlock(&pi_state->pi_mutex.wait_lock);
+ return ret;
+ }
}
spin_lock_irq(&pi_state->owner->pi_lock);
@@ -1174,7 +1196,7 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
#ifdef CONFIG_DEBUG_PI_LIST
this->list.plist.lock = &hb2->lock;
#endif
- }
+ }
this->key = key2;
get_futex_key_refs(&key2);
drop_count++;
@@ -1326,12 +1348,10 @@ static void unqueue_me_pi(struct futex_q *q)
/*
* Fixup the pi_state owner with current.
*
- * The cur->mm semaphore must be held, it is released at return of this
- * function.
+ * Must be called with hash bucket lock held and mm->sem held for non
+ * private futexes.
*/
-static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
- struct futex_q *q,
- struct futex_hash_bucket *hb,
+static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
struct task_struct *curr)
{
u32 newtid = curr->pid | FUTEX_WAITERS;
@@ -1355,23 +1375,24 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
list_add(&pi_state->list, &curr->pi_state_list);
spin_unlock_irq(&curr->pi_lock);
- /* Unqueue and drop the lock */
- unqueue_me_pi(q);
- if (fshared)
- up_read(fshared);
/*
* We own it, so we have to replace the pending owner
* TID. This must be atomic as we have preserve the
* owner died bit here.
*/
- ret = get_user(uval, uaddr);
+ ret = get_futex_value_locked(&uval, uaddr);
+
while (!ret) {
newval = (uval & FUTEX_OWNER_DIED) | newtid;
newval |= (uval & FUTEX_WAITER_REQUEUED);
+
+ pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr,
uval, newval);
+ pagefault_enable();
+
if (curval == -EFAULT)
- ret = -EFAULT;
+ ret = -EFAULT;
if (curval == uval)
break;
uval = curval;
@@ -1553,10 +1574,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
*/
uaddr = q.pi_state->key.uaddr;
- /* mmap_sem and hash_bucket lock are unlocked at
- return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared,
- &q, hb, curr);
+ ret = fixup_pi_state_owner(uaddr, &q, curr);
} else {
/*
* Catch the rare case, where the lock was released
@@ -1567,12 +1585,13 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
if (rt_mutex_trylock(&q.pi_state->pi_mutex))
ret = 0;
}
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
}
+ /* Unqueue and drop the lock */
+ unqueue_me_pi(&q);
+ if (fshared)
+ up_read(fshared);
+
debug_rt_mutex_free_waiter(&q.waiter);
return ret;
@@ -1688,7 +1707,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
struct futex_hash_bucket *hb;
u32 uval, newval, curval;
struct futex_q q;
- int ret, lock_held, attempt = 0;
+ int ret, lock_taken, ownerdied = 0, attempt = 0;
if (refill_pi_state_cache())
return -ENOMEM;
@@ -1709,10 +1728,11 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(ret != 0))
goto out_release_sem;
+ retry_unlocked:
hb = queue_lock(&q, -1, NULL);
retry_locked:
- lock_held = 0;
+ ret = lock_taken = 0;
/*
* To avoid races, we attempt to take the lock here again
@@ -1728,43 +1748,44 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(curval == -EFAULT))
goto uaddr_faulted;
- /* We own the lock already */
+ /*
+ * Detect deadlocks. In case of REQUEUE_PI this is a valid
+ * situation and we return success to user space.
+ */
if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
- if (!detect && 0)
- force_sig(SIGKILL, current);
- /*
- * Normally, this check is done in user space.
- * In case of requeue, the owner may attempt to lock this futex,
- * even if the ownership has already been given by the previous
- * waker.
- * In the usual case, this is a case of deadlock, but not in case
- * of REQUEUE_PI.
- */
if (!(curval & FUTEX_WAITER_REQUEUED))
ret = -EDEADLK;
goto out_unlock_release_sem;
}
/*
- * Surprise - we got the lock. Just return
- * to userspace:
+ * Surprise - we got the lock. Just return to userspace:
*/
if (unlikely(!curval))
goto out_unlock_release_sem;
uval = curval;
+
/*
- * In case of a requeue, check if there already is an owner
- * If not, just take the futex.
+ * Set the WAITERS flag, so the owner will know it has someone
+ * to wake at next unlock
*/
- if ((curval & FUTEX_WAITER_REQUEUED) && !(curval & FUTEX_TID_MASK)) {
- /* set current as futex owner */
- newval = curval | current->pid;
- lock_held = 1;
- } else
- /* Set the WAITERS flag, so the owner will know it has someone
- to wake at next unlock */
- newval = curval | FUTEX_WAITERS;
+ newval = curval | FUTEX_WAITERS;
+
+ /*
+ * There are two cases, where a futex might have no owner (the
+ * owner TID is 0): OWNER_DIED or REQUEUE. We take over the
+ * futex in this case. We also do an unconditional take over,
+ * when the owner of the futex died.
+ *
+ * This is safe as we are protected by the hash bucket lock !
+ */
+ if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
+ /* Keep the OWNER_DIED and REQUEUE bits */
+ newval = (curval & ~FUTEX_TID_MASK) | current->pid;
+ ownerdied = 0;
+ lock_taken = 1;
+ }
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
@@ -1775,8 +1796,13 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(curval != uval))
goto retry_locked;
- if (lock_held) {
- set_pi_futex_owner(hb, &q.key, curr);
+ /*
+ * We took the lock due to requeue or owner died take over.
+ */
+ if (unlikely(lock_taken)) {
+ /* For requeue we need to fixup the pi_futex */
+ if (curval & FUTEX_WAITER_REQUEUED)
+ set_pi_futex_owner(hb, &q.key, curr);
goto out_unlock_release_sem;
}
@@ -1787,34 +1813,40 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
if (unlikely(ret)) {
- /*
- * There were no waiters and the owner task lookup
- * failed. When the OWNER_DIED bit is set, then we
- * know that this is a robust futex and we actually
- * take the lock. This is safe as we are protected by
- * the hash bucket lock. We also set the waiters bit
- * unconditionally here, to simplify glibc handling of
- * multiple tasks racing to acquire the lock and
- * cleanup the problems which were left by the dead
- * owner.
- */
- if (curval & FUTEX_OWNER_DIED) {
- uval = newval;
- newval = current->pid |
- FUTEX_OWNER_DIED | FUTEX_WAITERS;
+ switch (ret) {
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr,
- uval, newval);
- pagefault_enable();
+ case -EAGAIN:
+ /*
+ * Task is exiting and we just wait for the
+ * exit to complete.
+ */
+ queue_unlock(&q, hb);
+ if (fshared)
+ up_read(fshared);
+ cond_resched();
+ goto retry;
- if (unlikely(curval == -EFAULT))
+ case -ESRCH:
+ /*
+ * No owner found for this futex. Check if the
+ * OWNER_DIED bit is set to figure out whether
+ * this is a robust futex or not.
+ */
+ if (get_futex_value_locked(&curval, uaddr))
goto uaddr_faulted;
- if (unlikely(curval != uval))
+
+ /*
+ * We simply start over in case of a robust
+ * futex. The code above will take the futex
+ * and return happy.
+ */
+ if (curval & FUTEX_OWNER_DIED) {
+ ownerdied = 1;
goto retry_locked;
- ret = 0;
+ }
+ default:
+ goto out_unlock_release_sem;
}
- goto out_unlock_release_sem;
}
/*
@@ -1845,31 +1877,42 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
down_read(fshared);
spin_lock(q.lock_ptr);
- /*
- * Got the lock. We might not be the anticipated owner if we
- * did a lock-steal - fix up the PI-state in that case.
- */
- if (!ret && q.pi_state->owner != curr)
- /* mmap_sem is unlocked at return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared, &q, hb, curr);
- else {
+ if (!ret) {
+ /*
+ * Got the lock. We might not be the anticipated owner
+ * if we did a lock-steal - fix up the PI-state in
+ * that case:
+ */
+ if (q.pi_state->owner != curr)
+ ret = fixup_pi_state_owner(uaddr, &q, curr);
+ } else {
/*
* Catch the rare case, where the lock was released
- * when we were on the way back before we locked
- * the hash bucket.
+ * when we were on the way back before we locked the
+ * hash bucket.
*/
- if (ret && q.pi_state->owner == curr) {
- if (rt_mutex_trylock(&q.pi_state->pi_mutex))
- ret = 0;
+ if (q.pi_state->owner == curr &&
+ rt_mutex_trylock(&q.pi_state->pi_mutex)) {
+ ret = 0;
+ } else {
+ /*
+ * Paranoia check. If we did not take the lock
+ * in the trylock above, then we should not be
+ * the owner of the rtmutex, neither the real
+ * nor the pending one:
+ */
+ if (rt_mutex_owner(&q.pi_state->pi_mutex) == curr)
+ printk(KERN_ERR "futex_lock_pi: ret = %d "
+ "pi-mutex: %p pi-state %p\n", ret,
+ q.pi_state->pi_mutex.owner,
+ q.pi_state->owner);
}
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
}
- if (!detect && ret == -EDEADLK && 0)
- force_sig(SIGKILL, current);
+ /* Unqueue and drop the lock */
+ unqueue_me_pi(&q);
+ if (fshared)
+ up_read(fshared);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
@@ -1887,16 +1930,19 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. :-) --ANK
*/
+ queue_unlock(&q, hb);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock_release_sem;
- goto retry_locked;
+ goto out_release_sem;
+ goto retry_unlocked;
}
- queue_unlock(&q, hb);
if (fshared)
up_read(fshared);
@@ -1940,9 +1986,9 @@ retry:
goto out;
hb = hash_futex(&key);
+retry_unlocked:
spin_lock(&hb->lock);
-retry_locked:
/*
* To avoid races, try to do the TID -> 0 atomic transition
* again. If it succeeds then we can return without waking
@@ -2005,16 +2051,19 @@ pi_faulted:
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. --ANK
*/
+ spin_unlock(&hb->lock);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock;
- goto retry_locked;
+ goto out;
+ goto retry_unlocked;
}
- spin_unlock(&hb->lock);
if (fshared)
up_read(fshared);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 12879f6c1ec..a6fbb413052 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -189,6 +189,19 @@ int rt_mutex_adjust_prio_chain(struct task_struct *task,
if (!waiter || !waiter->task)
goto out_unlock_pi;
+ /*
+ * Check the orig_waiter state. After we dropped the locks,
+ * the previous owner of the lock might have released the lock
+ * and made us the pending owner:
+ */
+ if (orig_waiter && !orig_waiter->task)
+ goto out_unlock_pi;
+
+ /*
+ * Drop out, when the task has no waiters. Note,
+ * top_waiter can be NULL, when we are in the deboosting
+ * mode!
+ */
if (top_waiter && (!task_has_pi_waiters(task) ||
top_waiter != task_top_pi_waiter(task)))
goto out_unlock_pi;
@@ -636,9 +649,16 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
* all over without going into schedule to try
* to get the lock now:
*/
- if (unlikely(!waiter.task))
+ if (unlikely(!waiter.task)) {
+ /*
+ * Reset the return value. We might
+ * have returned with -EDEADLK and the
+ * owner released the lock while we
+ * were walking the pi chain.
+ */
+ ret = 0;
continue;
-
+ }
if (unlikely(ret))
break;
}
diff --git a/lib/hexdump.c b/lib/hexdump.c
index e6da5b7fc29..473f5aed6ca 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -16,42 +16,98 @@
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 bytes of input data converted to hex + ASCII output.
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
*
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
* to a hex + ASCII dump at the supplied memory location.
* The converted output is always NUL-terminated.
*
* E.g.:
- * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ * linebuf, sizeof(linebuf), 1);
*
* example output buffer:
- * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
*/
-void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen)
+void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+ int groupsize, char *linebuf, size_t linebuflen,
+ bool ascii)
{
const u8 *ptr = buf;
u8 ch;
int j, lx = 0;
+ int ascii_column;
- for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
- if (j && !(j % 4))
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ if (!len)
+ goto nil;
+ if (len > rowsize) /* limit to one line at a time */
+ len = rowsize;
+ if ((len % groupsize) != 0) /* no mixed size output */
+ groupsize = 1;
+
+ switch (groupsize) {
+ case 8: {
+ const u64 *ptr8 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%16.16llx ", (unsigned long long)*(ptr8 + j));
+ ascii_column = 17 * ngroups + 2;
+ break;
+ }
+
+ case 4: {
+ const u32 *ptr4 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%8.8x ", *(ptr4 + j));
+ ascii_column = 9 * ngroups + 2;
+ break;
+ }
+
+ case 2: {
+ const u16 *ptr2 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%4.4x ", *(ptr2 + j));
+ ascii_column = 5 * ngroups + 2;
+ break;
+ }
+
+ default:
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
+ j++) {
+ ch = ptr[j];
+ linebuf[lx++] = hex_asc(ch >> 4);
+ linebuf[lx++] = hex_asc(ch & 0x0f);
linebuf[lx++] = ' ';
- ch = ptr[j];
- linebuf[lx++] = hex_asc(ch >> 4);
- linebuf[lx++] = hex_asc(ch & 0x0f);
+ }
+ ascii_column = 3 * rowsize + 2;
+ break;
}
- if ((lx + 2) < linebuflen) {
- linebuf[lx++] = ' ';
+ if (!ascii)
+ goto nil;
+
+ while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
linebuf[lx++] = ' ';
- }
- for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+nil:
linebuf[lx++] = '\0';
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -59,46 +115,83 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
/**
* print_hex_dump - print a text hex dump to syslog for a binary blob of data
* @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
*
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
* to the kernel log at the specified kernel log level, with an optional
* leading prefix.
*
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
* E.g.:
- * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ * 16, 1, frame->data, frame->len, 1);
*
- * Example output using %DUMP_PREFIX_OFFSET:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS:
- * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~.
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
*/
-void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii)
{
u8 *ptr = buf;
int i, linelen, remaining = len;
- unsigned char linebuf[100];
+ unsigned char linebuf[200];
- for (i = 0; i < len; i += 16) {
- linelen = min(remaining, 16);
- remaining -= 16;
- hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ for (i = 0; i < len; i += rowsize) {
+ linelen = min(remaining, rowsize);
+ remaining -= rowsize;
+ hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+ linebuf, sizeof(linebuf), ascii);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
- printk("%s%*p: %s\n", level,
+ printk("%s%s%*p: %s\n", level, prefix_str,
(int)(2 * sizeof(void *)), ptr + i, linebuf);
break;
case DUMP_PREFIX_OFFSET:
- printk("%s%.8x: %s\n", level, i, linebuf);
+ printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
break;
default:
- printk("%s%s\n", level, linebuf);
+ printk("%s%s%s\n", level, prefix_str, linebuf);
break;
}
}
}
EXPORT_SYMBOL(print_hex_dump);
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len)
+{
+ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+ buf, len, 1);
+}
+EXPORT_SYMBOL(print_hex_dump_bytes);
diff --git a/lib/kobject.c b/lib/kobject.c
index fc5f3f6e732..ac1520651b9 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -202,14 +202,14 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
/* be noisy on error issues */
if (error == -EEXIST)
- printk("kobject_add failed for %s with -EEXIST, "
- "don't try to register things with the "
- "same name in the same directory.\n",
+ printk(KERN_ERR "kobject_add failed for %s with "
+ "-EEXIST, don't try to register things with "
+ "the same name in the same directory.\n",
kobject_name(kobj));
else
- printk("kobject_add failed for %s (%d)\n",
+ printk(KERN_ERR "kobject_add failed for %s (%d)\n",
kobject_name(kobj), error);
- dump_stack();
+ dump_stack();
}
return error;
diff --git a/mm/shmem.c b/mm/shmem.c
index e537317bec4..b6aae2b3339 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -967,6 +967,8 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_
*nodelist++ = '\0';
if (nodelist_parse(nodelist, *policy_nodes))
goto out;
+ if (!nodes_subset(*policy_nodes, node_online_map))
+ goto out;
}
if (!strcmp(value, "default")) {
*policy = MPOL_DEFAULT;
diff --git a/mm/slab.c b/mm/slab.c
index 2e71a328aa0..6d65cf4e4b2 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3539,7 +3539,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
check_irq_off();
objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
- if (use_alien_caches && cache_free_alien(cachep, objp))
+ if (cache_free_alien(cachep, objp))
return;
if (likely(ac->avail < ac->limit)) {
diff --git a/mm/slub.c b/mm/slub.c
index 51663a3c3c2..c9ab68881b4 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2241,7 +2241,7 @@ void *__kmalloc(size_t size, gfp_t flags)
if (s)
return slab_alloc(s, flags, -1, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc);
@@ -2252,16 +2252,20 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
if (s)
return slab_alloc(s, flags, node, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc_node);
#endif
size_t ksize(const void *object)
{
- struct page *page = get_object_page(object);
+ struct page *page;
struct kmem_cache *s;
+ if (object == ZERO_SIZE_PTR)
+ return 0;
+
+ page = get_object_page(object);
BUG_ON(!page);
s = page->slab;
BUG_ON(!s);
@@ -2293,7 +2297,13 @@ void kfree(const void *x)
struct kmem_cache *s;
struct page *page;
- if (!x)
+ /*
+ * This has to be an unsigned comparison. According to Linus
+ * some gcc version treat a pointer as a signed entity. Then
+ * this comparison would be true for all "negative" pointers
+ * (which would cover the whole upper half of the address space).
+ */
+ if ((unsigned long)x <= (unsigned long)ZERO_SIZE_PTR)
return;
page = virt_to_head_page(x);
@@ -2398,12 +2408,12 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
void *ret;
size_t ks;
- if (unlikely(!p))
+ if (unlikely(!p || p == ZERO_SIZE_PTR))
return kmalloc(new_size, flags);
if (unlikely(!new_size)) {
kfree(p);
- return NULL;
+ return ZERO_SIZE_PTR;
}
ks = ksize(p);
@@ -2652,7 +2662,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, -1, caller);
}
@@ -2663,7 +2673,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, node, caller);
}
diff --git a/mm/sparse.c b/mm/sparse.c
index 545e4d3afcd..e03b39f3540 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -240,6 +240,27 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
return NULL;
}
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void __init sparse_init(void)
+{
+ unsigned long pnum;
+ struct page *map;
+
+ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+ if (!valid_section_nr(pnum))
+ continue;
+
+ map = sparse_early_mem_map_alloc(pnum);
+ if (!map)
+ continue;
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map);
+ }
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
{
struct page *page, *ret;
@@ -280,27 +301,6 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
}
/*
- * Allocate the accumulated non-linear sections, allocate a mem_map
- * for each and record the physical to section mapping.
- */
-void __init sparse_init(void)
-{
- unsigned long pnum;
- struct page *map;
-
- for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
- if (!valid_section_nr(pnum))
- continue;
-
- map = sparse_early_mem_map_alloc(pnum);
- if (!map)
- continue;
- sparse_init_one_section(__nr_to_section(pnum), pnum, map);
- }
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-/*
* returns the number of sections whose mem_maps were properly
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
diff --git a/net/core/dev.c b/net/core/dev.c
index 5a7f20f7857..26090621ea6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2577,7 +2577,7 @@ unsigned dev_get_flags(const struct net_device *dev)
int dev_change_flags(struct net_device *dev, unsigned flags)
{
- int ret;
+ int ret, changes;
int old_flags = dev->flags;
/*
@@ -2632,8 +2632,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
dev_set_allmulti(dev, inc);
}
- if (old_flags ^ dev->flags)
- rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags ^ dev->flags);
+ /* Exclude state transition flags, already notified */
+ changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING);
+ if (changes)
+ rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
return ret;
}
diff --git a/net/core/dst.c b/net/core/dst.c
index 764bccb3d99..c6a05879d58 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -111,13 +111,7 @@ out:
spin_unlock(&dst_lock);
}
-static int dst_discard_in(struct sk_buff *skb)
-{
- kfree_skb(skb);
- return 0;
-}
-
-static int dst_discard_out(struct sk_buff *skb)
+static int dst_discard(struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
@@ -138,8 +132,7 @@ void * dst_alloc(struct dst_ops * ops)
dst->ops = ops;
dst->lastuse = jiffies;
dst->path = dst;
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
#if RT_CACHE_DEBUG >= 2
atomic_inc(&dst_total);
#endif
@@ -153,8 +146,7 @@ static void ___dst_free(struct dst_entry * dst)
protocol module is unloaded.
*/
if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
}
dst->obsolete = 2;
}
@@ -242,8 +234,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
return;
if (!unregister) {
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
} else {
dst->dev = &loopback_dev;
dev_hold(&loopback_dev);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6f3bb73053c..9df26a07f06 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1761,7 +1761,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
return NULL;
}
-static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
[NDTA_NAME] = { .type = NLA_STRING },
[NDTA_THRESH1] = { .type = NLA_U32 },
[NDTA_THRESH2] = { .type = NLA_U32 },
@@ -1770,7 +1770,7 @@ static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
[NDTA_PARMS] = { .type = NLA_NESTED },
};
-static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
[NDTPA_IFINDEX] = { .type = NLA_U32 },
[NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
[NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 27da9cdec6a..02e8bf08427 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -551,7 +551,7 @@ cont:
return skb->len;
}
-static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
+static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
[IFLA_MTU] = { .type = NLA_U32 },
@@ -580,7 +580,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = -EINVAL;
ifm = nlmsg_data(nlh);
- if (ifm->ifi_index >= 0)
+ if (ifm->ifi_index > 0)
dev = dev_get_by_index(ifm->ifi_index);
else if (tb[IFLA_IFNAME])
dev = dev_get_by_name(ifname);
@@ -672,7 +672,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
* name provided implies that a name change has been
* requested.
*/
- if (ifm->ifi_index >= 0 && ifname[0]) {
+ if (ifm->ifi_index > 0 && ifname[0]) {
err = dev_change_name(dev, ifname);
if (err < 0)
goto errout_dev;
@@ -740,7 +740,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
return err;
ifm = nlmsg_data(nlh);
- if (ifm->ifi_index >= 0) {
+ if (ifm->ifi_index > 0) {
dev = dev_get_by_index(ifm->ifi_index);
if (dev == NULL)
return -ENODEV;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 764a56a13e3..ab41c1879fd 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -638,7 +638,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
return dn_dev;
}
-static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .type = NLA_U16 },
[IFA_LOCAL] = { .type = NLA_U16 },
[IFA_LABEL] = { .type = NLA_STRING,
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 17a1932216d..84ff3dd3707 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -108,7 +108,7 @@ errout:
return err;
}
-static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
};
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7110779a024..e00767e8ebd 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -877,7 +877,7 @@ static int arp_process(struct sk_buff *skb)
n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
- if (ipv4_devconf.arp_accept) {
+ if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
/* Unsolicited ARP is not accepted by default.
It is possible, that this option should be enabled for some
devices (strip is candidate)
@@ -987,11 +987,11 @@ static int arp_req_set(struct arpreq *r, struct net_device * dev)
return 0;
}
if (dev == NULL) {
- ipv4_devconf.proxy_arp = 1;
+ IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
return 0;
}
if (__in_dev_get_rtnl(dev)) {
- __in_dev_get_rtnl(dev)->cnf.proxy_arp = 1;
+ IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1);
return 0;
}
return -ENXIO;
@@ -1093,11 +1093,12 @@ static int arp_req_delete(struct arpreq *r, struct net_device * dev)
return pneigh_delete(&arp_tbl, &ip, dev);
if (mask == 0) {
if (dev == NULL) {
- ipv4_devconf.proxy_arp = 0;
+ IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
return 0;
}
if (__in_dev_get_rtnl(dev)) {
- __in_dev_get_rtnl(dev)->cnf.proxy_arp = 0;
+ IN_DEV_CONF_SET(__in_dev_get_rtnl(dev),
+ PROXY_ARP, 0);
return 0;
}
return -ENXIO;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 86a2b52aad3..ab56a052ce3 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -45,6 +45,7 @@
#include <net/cipso_ipv4.h>
#include <asm/atomic.h>
#include <asm/bug.h>
+#include <asm/unaligned.h>
struct cipso_v4_domhsh_entry {
char *domain;
@@ -1000,7 +1001,7 @@ static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
return -EFAULT;
for (iter = 0; iter < enumcat_len; iter += 2) {
- cat = ntohs(*((__be16 *)&enumcat[iter]));
+ cat = ntohs(get_unaligned((__be16 *)&enumcat[iter]));
if (cat <= cat_prev)
return -EFAULT;
cat_prev = cat;
@@ -1068,8 +1069,8 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
for (iter = 0; iter < net_cat_len; iter += 2) {
ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
- ntohs(*((__be16 *)&net_cat[iter])),
- GFP_ATOMIC);
+ ntohs(get_unaligned((__be16 *)&net_cat[iter])),
+ GFP_ATOMIC);
if (ret_val != 0)
return ret_val;
}
@@ -1102,9 +1103,10 @@ static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
return -EFAULT;
for (iter = 0; iter < rngcat_len; iter += 4) {
- cat_high = ntohs(*((__be16 *)&rngcat[iter]));
+ cat_high = ntohs(get_unaligned((__be16 *)&rngcat[iter]));
if ((iter + 4) <= rngcat_len)
- cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
+ cat_low = ntohs(
+ get_unaligned((__be16 *)&rngcat[iter + 2]));
else
cat_low = 0;
@@ -1201,9 +1203,10 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
u16 cat_high;
for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
- cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
+ cat_high = ntohs(get_unaligned((__be16 *)&net_cat[net_iter]));
if ((net_iter + 4) <= net_cat_len)
- cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
+ cat_low = ntohs(
+ get_unaligned((__be16 *)&net_cat[net_iter + 2]));
else
cat_low = 0;
@@ -1565,7 +1568,7 @@ int cipso_v4_validate(unsigned char **option)
}
rcu_read_lock();
- doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
+ doi_def = cipso_v4_doi_search(ntohl(get_unaligned((__be32 *)&opt[2])));
if (doi_def == NULL) {
err_offset = 2;
goto validate_return_locked;
@@ -1709,22 +1712,22 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
}
/**
- * cipso_v4_socket_setattr - Add a CIPSO option to a socket
- * @sock: the socket
+ * cipso_v4_sock_setattr - Add a CIPSO option to a socket
+ * @sk: the socket
* @doi_def: the CIPSO DOI to use
* @secattr: the specific security attributes of the socket
*
* Description:
* Set the CIPSO option on the given socket using the DOI definition and
* security attributes passed to the function. This function requires
- * exclusive access to @sock->sk, which means it either needs to be in the
- * process of being created or locked via lock_sock(sock->sk). Returns zero on
- * success and negative values on failure.
+ * exclusive access to @sk, which means it either needs to be in the
+ * process of being created or locked. Returns zero on success and negative
+ * values on failure.
*
*/
-int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr)
+int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -EPERM;
u32 iter;
@@ -1732,7 +1735,6 @@ int cipso_v4_socket_setattr(const struct socket *sock,
u32 buf_len = 0;
u32 opt_len;
struct ip_options *opt = NULL;
- struct sock *sk;
struct inet_sock *sk_inet;
struct inet_connection_sock *sk_conn;
@@ -1740,7 +1742,6 @@ int cipso_v4_socket_setattr(const struct socket *sock,
* defined yet but it is not a problem as the only users of these
* "lite" PF_INET sockets are functions which do an accept() call
* afterwards so we will label the socket as part of the accept(). */
- sk = sock->sk;
if (sk == NULL)
return 0;
@@ -1858,7 +1859,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
if (ret_val == 0)
return ret_val;
- doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+ doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
rcu_read_lock();
doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL) {
@@ -1892,29 +1893,6 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
}
/**
- * cipso_v4_socket_getattr - Get the security attributes from a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Query @sock to see if there is a CIPSO option attached to the socket and if
- * there is return the CIPSO security attributes in @secattr. Returns zero on
- * success and negative values on failure.
- *
- */
-int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- int ret_val;
-
- lock_sock(sock->sk);
- ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
- release_sock(sock->sk);
-
- return ret_val;
-}
-
-/**
* cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
* @skb: the packet
* @secattr: the security attributes
@@ -1936,7 +1914,7 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
return 0;
- doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+ doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
rcu_read_lock();
doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7f95e6e9bee..abf6352f990 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -64,21 +64,27 @@
#include <net/rtnetlink.h>
struct ipv4_devconf ipv4_devconf = {
- .accept_redirects = 1,
- .send_redirects = 1,
- .secure_redirects = 1,
- .shared_media = 1,
+ .data = {
+ [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+ },
};
static struct ipv4_devconf ipv4_devconf_dflt = {
- .accept_redirects = 1,
- .send_redirects = 1,
- .secure_redirects = 1,
- .shared_media = 1,
- .accept_source_route = 1,
+ .data = {
+ [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+ [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
+ },
};
-static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = {
+#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
+
+static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
[IFA_LOCAL] = { .type = NLA_U32 },
[IFA_ADDRESS] = { .type = NLA_U32 },
[IFA_BROADCAST] = { .type = NLA_U32 },
@@ -141,7 +147,7 @@ void in_dev_finish_destroy(struct in_device *idev)
}
}
-struct in_device *inetdev_init(struct net_device *dev)
+static struct in_device *inetdev_init(struct net_device *dev)
{
struct in_device *in_dev;
@@ -321,12 +327,8 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
}
}
- if (destroy) {
+ if (destroy)
inet_free_ifa(ifa1);
-
- if (!in_dev->ifa_list)
- inetdev_destroy(in_dev);
- }
}
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
@@ -399,12 +401,10 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
ASSERT_RTNL();
if (!in_dev) {
- in_dev = inetdev_init(dev);
- if (!in_dev) {
- inet_free_ifa(ifa);
- return -ENOBUFS;
- }
+ inet_free_ifa(ifa);
+ return -ENOBUFS;
}
+ ipv4_devconf_setall(in_dev);
if (ifa->ifa_dev != in_dev) {
BUG_TRAP(!ifa->ifa_dev);
in_dev_hold(in_dev);
@@ -514,13 +514,12 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
in_dev = __in_dev_get_rtnl(dev);
if (in_dev == NULL) {
- in_dev = inetdev_init(dev);
- if (in_dev == NULL) {
- err = -ENOBUFS;
- goto errout;
- }
+ err = -ENOBUFS;
+ goto errout;
}
+ ipv4_devconf_setall(in_dev);
+
ifa = inet_alloc_ifa();
if (ifa == NULL) {
/*
@@ -1057,11 +1056,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
if (!in_dev) {
if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev);
- if (!in_dev)
- panic("devinet: Failed to create loopback\n");
if (dev == &loopback_dev) {
- in_dev->cnf.no_xfrm = 1;
- in_dev->cnf.no_policy = 1;
+ if (!in_dev)
+ panic("devinet: "
+ "Failed to create loopback\n");
+ IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
+ IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
}
}
goto out;
@@ -1237,13 +1237,98 @@ errout:
#ifdef CONFIG_SYSCTL
+static void devinet_copy_dflt_conf(int i)
+{
+ struct net_device *dev;
+
+ read_lock(&dev_base_lock);
+ for_each_netdev(dev) {
+ struct in_device *in_dev;
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+ if (in_dev && !test_bit(i, in_dev->cnf.state))
+ in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
+ rcu_read_unlock();
+ }
+ read_unlock(&dev_base_lock);
+}
+
+static int devinet_conf_proc(ctl_table *ctl, int write,
+ struct file* filp, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+ if (write) {
+ struct ipv4_devconf *cnf = ctl->extra1;
+ int i = (int *)ctl->data - cnf->data;
+
+ set_bit(i, cnf->state);
+
+ if (cnf == &ipv4_devconf_dflt)
+ devinet_copy_dflt_conf(i);
+ }
+
+ return ret;
+}
+
+static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ struct ipv4_devconf *cnf;
+ int *valp = table->data;
+ int new;
+ int i;
+
+ if (!newval || !newlen)
+ return 0;
+
+ if (newlen != sizeof(int))
+ return -EINVAL;
+
+ if (get_user(new, (int __user *)newval))
+ return -EFAULT;
+
+ if (new == *valp)
+ return 0;
+
+ if (oldval && oldlenp) {
+ size_t len;
+
+ if (get_user(len, oldlenp))
+ return -EFAULT;
+
+ if (len) {
+ if (len > table->maxlen)
+ len = table->maxlen;
+ if (copy_to_user(oldval, valp, len))
+ return -EFAULT;
+ if (put_user(len, oldlenp))
+ return -EFAULT;
+ }
+ }
+
+ *valp = new;
+
+ cnf = table->extra1;
+ i = (int *)table->data - cnf->data;
+
+ set_bit(i, cnf->state);
+
+ if (cnf == &ipv4_devconf_dflt)
+ devinet_copy_dflt_conf(i);
+
+ return 1;
+}
+
void inet_forward_change(void)
{
struct net_device *dev;
- int on = ipv4_devconf.forwarding;
+ int on = IPV4_DEVCONF_ALL(FORWARDING);
- ipv4_devconf.accept_redirects = !on;
- ipv4_devconf_dflt.forwarding = on;
+ IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
+ IPV4_DEVCONF_DFLT(FORWARDING) = on;
read_lock(&dev_base_lock);
for_each_netdev(dev) {
@@ -1251,7 +1336,7 @@ void inet_forward_change(void)
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev)
- in_dev->cnf.forwarding = on;
+ IN_DEV_CONF_SET(in_dev, FORWARDING, on);
rcu_read_unlock();
}
read_unlock(&dev_base_lock);
@@ -1268,9 +1353,9 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val) {
- if (valp == &ipv4_devconf.forwarding)
+ if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
inet_forward_change();
- else if (valp != &ipv4_devconf_dflt.forwarding)
+ else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
rt_cache_flush(0);
}
@@ -1295,42 +1380,43 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
- int *valp = table->data;
- int new;
+ int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
+ newval, newlen);
- if (!newval || !newlen)
- return 0;
+ if (ret == 1)
+ rt_cache_flush(0);
- if (newlen != sizeof(int))
- return -EINVAL;
+ return ret;
+}
- if (get_user(new, (int __user *)newval))
- return -EFAULT;
- if (new == *valp)
- return 0;
+#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
+ { \
+ .ctl_name = NET_IPV4_CONF_ ## attr, \
+ .procname = name, \
+ .data = ipv4_devconf.data + \
+ NET_IPV4_CONF_ ## attr - 1, \
+ .maxlen = sizeof(int), \
+ .mode = mval, \
+ .proc_handler = proc, \
+ .strategy = sysctl, \
+ .extra1 = &ipv4_devconf, \
+ }
- if (oldval && oldlenp) {
- size_t len;
+#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
+ devinet_conf_sysctl)
- if (get_user(len, oldlenp))
- return -EFAULT;
+#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
+ devinet_conf_sysctl)
- if (len) {
- if (len > table->maxlen)
- len = table->maxlen;
- if (copy_to_user(oldval, valp, len))
- return -EFAULT;
- if (put_user(len, oldlenp))
- return -EFAULT;
- }
- }
-
- *valp = new;
- rt_cache_flush(0);
- return 1;
-}
+#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
+#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
+ DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \
+ ipv4_doint_and_flush_strategy)
static struct devinet_sysctl_table {
struct ctl_table_header *sysctl_header;
@@ -1341,178 +1427,34 @@ static struct devinet_sysctl_table {
ctl_table devinet_root_dir[2];
} devinet_sysctl = {
.devinet_vars = {
- {
- .ctl_name = NET_IPV4_CONF_FORWARDING,
- .procname = "forwarding",
- .data = &ipv4_devconf.forwarding,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &devinet_sysctl_forward,
- },
- {
- .ctl_name = NET_IPV4_CONF_MC_FORWARDING,
- .procname = "mc_forwarding",
- .data = &ipv4_devconf.mc_forwarding,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ACCEPT_REDIRECTS,
- .procname = "accept_redirects",
- .data = &ipv4_devconf.accept_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SECURE_REDIRECTS,
- .procname = "secure_redirects",
- .data = &ipv4_devconf.secure_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SHARED_MEDIA,
- .procname = "shared_media",
- .data = &ipv4_devconf.shared_media,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_RP_FILTER,
- .procname = "rp_filter",
- .data = &ipv4_devconf.rp_filter,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SEND_REDIRECTS,
- .procname = "send_redirects",
- .data = &ipv4_devconf.send_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
- .procname = "accept_source_route",
- .data = &ipv4_devconf.accept_source_route,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_PROXY_ARP,
- .procname = "proxy_arp",
- .data = &ipv4_devconf.proxy_arp,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_MEDIUM_ID,
- .procname = "medium_id",
- .data = &ipv4_devconf.medium_id,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_BOOTP_RELAY,
- .procname = "bootp_relay",
- .data = &ipv4_devconf.bootp_relay,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_LOG_MARTIANS,
- .procname = "log_martians",
- .data = &ipv4_devconf.log_martians,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_TAG,
- .procname = "tag",
- .data = &ipv4_devconf.tag,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARPFILTER,
- .procname = "arp_filter",
- .data = &ipv4_devconf.arp_filter,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_ANNOUNCE,
- .procname = "arp_announce",
- .data = &ipv4_devconf.arp_announce,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_IGNORE,
- .procname = "arp_ignore",
- .data = &ipv4_devconf.arp_ignore,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_ACCEPT,
- .procname = "arp_accept",
- .data = &ipv4_devconf.arp_accept,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_NOXFRM,
- .procname = "disable_xfrm",
- .data = &ipv4_devconf.no_xfrm,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_NOPOLICY,
- .procname = "disable_policy",
- .data = &ipv4_devconf.no_policy,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION,
- .procname = "force_igmp_version",
- .data = &ipv4_devconf.force_igmp_version,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
- .procname = "promote_secondaries",
- .data = &ipv4_devconf.promote_secondaries,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
+ DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
+ devinet_sysctl_forward,
+ devinet_conf_sysctl),
+ DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
+
+ DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
+ DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
+ DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
+ "accept_source_route"),
+ DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
+ DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
+ DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
+ DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
+ DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
+ DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
+
+ DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
+ "force_igmp_version"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
+ "promote_secondaries"),
},
.devinet_dev = {
{
@@ -1561,6 +1503,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
return;
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
+ t->devinet_vars[i].extra1 = p;
}
if (dev) {
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 9ad1f6252a9..311d633f7f3 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -441,7 +441,7 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg)
return -EINVAL;
}
-struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
+const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
[RTA_DST] = { .type = NLA_U32 },
[RTA_SRC] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 33083ad52e9..2a947840210 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -169,7 +169,7 @@ static struct fib_table *fib_empty_table(void)
return NULL;
}
-static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
[FRA_FLOW] = { .type = NLA_U32 },
};
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index f4dd4745310..a646409c2d0 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -128,14 +128,16 @@
* contradict to specs provided this delay is small enough.
*/
-#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \
- (in_dev)->cnf.force_igmp_version == 1 || \
- ((in_dev)->mr_v1_seen && \
- time_before(jiffies, (in_dev)->mr_v1_seen)))
-#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \
- (in_dev)->cnf.force_igmp_version == 2 || \
- ((in_dev)->mr_v2_seen && \
- time_before(jiffies, (in_dev)->mr_v2_seen)))
+#define IGMP_V1_SEEN(in_dev) \
+ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+ ((in_dev)->mr_v1_seen && \
+ time_before(jiffies, (in_dev)->mr_v1_seen)))
+#define IGMP_V2_SEEN(in_dev) \
+ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+ ((in_dev)->mr_v2_seen && \
+ time_before(jiffies, (in_dev)->mr_v2_seen)))
static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index d6427d91851..34ea4547ebb 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1352,7 +1352,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
}
{
- struct flowi fl = { .nl_u = { .ip4_u =
+ struct flowi fl = { .oif = arg->bound_dev_if,
+ .nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = rt->rt_spec_dst,
.tos = RT_TOS(ip_hdr(skb)->tos) } },
@@ -1376,6 +1377,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
inet->tos = ip_hdr(skb)->tos;
sk->sk_priority = skb->priority;
sk->sk_protocol = ip_hdr(skb)->protocol;
+ sk->sk_bound_dev_if = arg->bound_dev_if;
ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
&ipc, rt, MSG_DONTWAIT);
if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 0ebae413ae8..d96582acdf6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -152,9 +152,11 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
dev->flags |= IFF_MULTICAST;
in_dev = __in_dev_get_rtnl(dev);
- if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL)
+ if (in_dev == NULL)
goto failure;
- in_dev->cnf.rp_filter = 0;
+
+ ipv4_devconf_setall(in_dev);
+ IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
if (dev_open(dev))
goto failure;
@@ -218,10 +220,15 @@ static struct net_device *ipmr_reg_vif(void)
}
dev->iflink = 0;
- if ((in_dev = inetdev_init(dev)) == NULL)
+ rcu_read_lock();
+ if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
+ rcu_read_unlock();
goto failure;
+ }
- in_dev->cnf.rp_filter = 0;
+ ipv4_devconf_setall(in_dev);
+ IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
+ rcu_read_unlock();
if (dev_open(dev))
goto failure;
@@ -281,7 +288,7 @@ static int vif_delete(int vifi)
dev_set_allmulti(dev, -1);
if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
- in_dev->cnf.mc_forwarding--;
+ IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
ip_rt_multicast_event(in_dev);
}
@@ -426,7 +433,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
return -EADDRNOTAVAIL;
- in_dev->cnf.mc_forwarding++;
+ IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
dev_set_allmulti(dev, +1);
ip_rt_multicast_event(in_dev);
@@ -841,7 +848,7 @@ static void mrtsock_destruct(struct sock *sk)
{
rtnl_lock();
if (sk == mroute_socket) {
- ipv4_devconf.mc_forwarding--;
+ IPV4_DEVCONF_ALL(MC_FORWARDING)--;
write_lock_bh(&mrt_lock);
mroute_socket=NULL;
@@ -890,7 +897,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt
mroute_socket=sk;
write_unlock_bh(&mrt_lock);
- ipv4_devconf.mc_forwarding++;
+ IPV4_DEVCONF_ALL(MC_FORWARDING)++;
}
rtnl_unlock();
return ret;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e3f83bf160d..9bacf1a0363 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -499,7 +499,8 @@ check_entry(struct ipt_entry *e, const char *name)
}
static inline int check_match(struct ipt_entry_match *m, const char *name,
- const struct ipt_ip *ip, unsigned int hookmask)
+ const struct ipt_ip *ip, unsigned int hookmask,
+ unsigned int *i)
{
struct xt_match *match;
int ret;
@@ -515,6 +516,8 @@ static inline int check_match(struct ipt_entry_match *m, const char *name,
m->u.kernel.match->name);
ret = -EINVAL;
}
+ if (!ret)
+ (*i)++;
return ret;
}
@@ -537,11 +540,10 @@ find_check_match(struct ipt_entry_match *m,
}
m->u.kernel.match = match;
- ret = check_match(m, name, ip, hookmask);
+ ret = check_match(m, name, ip, hookmask, i);
if (ret)
goto err;
- (*i)++;
return 0;
err:
module_put(m->u.kernel.match->me);
@@ -1425,7 +1427,7 @@ out:
}
static inline int
-compat_check_calc_match(struct ipt_entry_match *m,
+compat_find_calc_match(struct ipt_entry_match *m,
const char *name,
const struct ipt_ip *ip,
unsigned int hookmask,
@@ -1449,6 +1451,31 @@ compat_check_calc_match(struct ipt_entry_match *m,
}
static inline int
+compat_release_match(struct ipt_entry_match *m, unsigned int *i)
+{
+ if (i && (*i)-- == 0)
+ return 1;
+
+ module_put(m->u.kernel.match->me);
+ return 0;
+}
+
+static inline int
+compat_release_entry(struct ipt_entry *e, unsigned int *i)
+{
+ struct ipt_entry_target *t;
+
+ if (i && (*i)-- == 0)
+ return 1;
+
+ /* Cleanup all matches */
+ IPT_MATCH_ITERATE(e, compat_release_match, NULL);
+ t = ipt_get_target(e);
+ module_put(t->u.kernel.target->me);
+ return 0;
+}
+
+static inline int
check_compat_entry_size_and_hooks(struct ipt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
@@ -1485,10 +1512,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
off = 0;
entry_offset = (void *)e - (void *)base;
j = 0;
- ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+ ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip,
e->comefrom, &off, &j);
if (ret != 0)
- goto cleanup_matches;
+ goto release_matches;
t = ipt_get_target(e);
target = try_then_request_module(xt_find_target(AF_INET,
@@ -1499,7 +1526,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
- goto cleanup_matches;
+ goto release_matches;
}
t->u.kernel.target = target;
@@ -1526,8 +1553,8 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
out:
module_put(t->u.kernel.target->me);
-cleanup_matches:
- IPT_MATCH_ITERATE(e, cleanup_match, &j);
+release_matches:
+ IPT_MATCH_ITERATE(e, compat_release_match, &j);
return ret;
}
@@ -1574,15 +1601,26 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
return ret;
}
-static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+static inline int compat_check_entry(struct ipt_entry *e, const char *name,
+ unsigned int *i)
{
- int ret;
+ int j, ret;
- ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
+ j = 0;
+ ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
if (ret)
- return ret;
+ goto cleanup_matches;
+
+ ret = check_target(e, name);
+ if (ret)
+ goto cleanup_matches;
- return check_target(e, name);
+ (*i)++;
+ return 0;
+
+ cleanup_matches:
+ IPT_MATCH_ITERATE(e, cleanup_match, &j);
+ return ret;
}
static int
@@ -1673,10 +1711,17 @@ translate_compat_table(const char *name,
if (!mark_source_chains(newinfo, valid_hooks, entry1))
goto free_newinfo;
+ i = 0;
ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
- name);
- if (ret)
- goto free_newinfo;
+ name, &i);
+ if (ret) {
+ j -= i;
+ IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i,
+ compat_release_entry, &j);
+ IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
+ xt_free_table_info(newinfo);
+ return ret;
+ }
/* And one copy for every other CPU */
for_each_possible_cpu(i)
@@ -1691,7 +1736,7 @@ translate_compat_table(const char *name,
free_newinfo:
xt_free_table_info(newinfo);
out:
- IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
+ IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
return ret;
out_unlock:
compat_flush_offsets();
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index fd62a41d69c..6dc72a815f7 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -133,6 +133,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper;
/* This is where we call the helper: as the packet goes out. */
ct = nf_ct_get(*pskb, &ctinfo);
@@ -140,12 +141,14 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
return NF_ACCEPT;
help = nfct_help(ct);
- if (!help || !help->helper)
+ if (!help)
return NF_ACCEPT;
-
- return help->helper->help(pskb,
- skb_network_offset(*pskb) + ip_hdrlen(*pskb),
- ct, ctinfo);
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(help->helper);
+ if (!helper)
+ return NF_ACCEPT;
+ return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
+ ct, ctinfo);
}
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cdbc6c13584..3b690cf2a4e 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -260,7 +260,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
seq_printf(seq, "\nIp: %d %d",
- ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+ IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8603cfb271f..29ca63e81ce 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1636,7 +1636,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -1778,9 +1778,9 @@ static inline int __mkroute_input(struct sk_buff *skb,
if (res->fi->fib_nhs > 1)
rth->u.dst.flags |= DST_BALANCED;
#endif
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
- if (out_dev->cnf.no_xfrm)
+ if (IN_DEV_CONF_GET(out_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -2021,7 +2021,7 @@ local_input:
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -2218,9 +2218,9 @@ static inline int __mkroute_output(struct rtable **result,
rth->u.dst.flags |= DST_BALANCED;
}
#endif
- if (in_dev->cnf.no_xfrm)
+ if (IN_DEV_CONF_GET(in_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = oldflp->fl4_dst;
@@ -2759,7 +2759,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
__be32 dst = rt->rt_dst;
if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
- ipv4_devconf.mc_forwarding) {
+ IPV4_DEVCONF_ALL(MC_FORWARDING)) {
int err = ipmr_get_route(skb, r, nowait);
if (err <= 0) {
if (!nowait) {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6817d6485df..53ef0f4bbda 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -37,12 +37,12 @@ static
int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int val = ipv4_devconf.forwarding;
+ int val = IPV4_DEVCONF_ALL(FORWARDING);
int ret;
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
- if (write && ipv4_devconf.forwarding != val)
+ if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
inet_forward_change();
return ret;
@@ -222,7 +222,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_FORWARD,
.procname = "ip_forward",
- .data = &ipv4_devconf.forwarding,
+ .data = &IPV4_DEVCONF_ALL(FORWARDING),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_sysctl_forward,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 47c61055eb6..97e294e8267 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -705,6 +705,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
ip_hdr(skb)->saddr, /* XXX */
arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+ if (twsk)
+ arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 760165a0800..d9323dfff82 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -63,6 +63,9 @@ struct {
* FIXME: causes an extra copy
*/
static void printl(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static void printl(const char *fmt, ...)
{
va_list args;
int len;
@@ -80,8 +83,7 @@ static void printl(const char *fmt, ...)
kfifo_put(tcpw.fifo, tbuf, len);
wake_up(&tcpw.wait);
-} __attribute__ ((format (printf, 1, 2)));
-
+}
/*
* Hook inserted to be called before each receive packet.
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index e61340150ba..e9b151b3a59 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -292,9 +292,9 @@ static void tcp_retransmit_timer(struct sock *sk)
* we cannot allow such beasts to hang infinitely.
*/
#ifdef TCP_DEBUG
- if (net_ratelimit()) {
+ if (1) {
struct inet_sock *inet = inet_sk(sk);
- printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
+ LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
NIPQUAD(inet->daddr), ntohs(inet->dport),
inet->num, tp->snd_una, tp->snd_nxt);
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5da703e699d..facb7e29304 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -114,36 +114,14 @@ DEFINE_RWLOCK(udp_hash_lock);
static int udp_port_rover;
-/*
- * Note about this hash function :
- * Typical use is probably daddr = 0, only dport is going to vary hash
- */
-static inline unsigned int udp_hash_port(__u16 port)
-{
- return port;
-}
-
-static inline int __udp_lib_port_inuse(unsigned int hash, int port,
- const struct sock *this_sk,
- struct hlist_head udptable[],
- const struct udp_get_port_ops *ops)
+static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
{
struct sock *sk;
struct hlist_node *node;
- struct inet_sock *inet;
- sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
- if (sk->sk_hash != hash)
- continue;
- inet = inet_sk(sk);
- if (inet->num != port)
- continue;
- if (this_sk) {
- if (ops->saddr_cmp(sk, this_sk))
- return 1;
- } else if (ops->saddr_any(sk))
+ sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+ if (sk->sk_hash == num)
return 1;
- }
return 0;
}
@@ -154,16 +132,16 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
* @snum: port number to look up
* @udptable: hash list table, must be of UDP_HTABLE_SIZE
* @port_rover: pointer to record of last unallocated port
- * @ops: AF-dependent address operations
+ * @saddr_comp: AF-dependent comparison of bound local IP addresses
*/
int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- const struct udp_get_port_ops *ops)
+ int (*saddr_comp)(const struct sock *sk1,
+ const struct sock *sk2 ) )
{
struct hlist_node *node;
struct hlist_head *head;
struct sock *sk2;
- unsigned int hash;
int error = 1;
write_lock_bh(&udp_hash_lock);
@@ -178,8 +156,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size;
- hash = ops->hash_port_and_rcv_saddr(result, sk);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1])
result = sysctl_local_port_range[0] +
@@ -204,16 +181,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1));
- hash = udp_hash_port(result);
- if (__udp_lib_port_inuse(hash, result,
- NULL, udptable, ops))
- continue;
- if (ops->saddr_any(sk))
- break;
-
- hash = ops->hash_port_and_rcv_saddr(result, sk);
- if (! __udp_lib_port_inuse(hash, result,
- sk, udptable, ops))
+ if (! __udp_lib_lport_inuse(result, udptable))
break;
}
if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,40 +189,21 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
gotit:
*port_rover = snum = result;
} else {
- hash = udp_hash_port(snum);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
- if (sk2->sk_hash == hash &&
- sk2 != sk &&
- inet_sk(sk2)->num == snum &&
- (!sk2->sk_reuse || !sk->sk_reuse) &&
- (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
- sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
- ops->saddr_cmp(sk, sk2))
+ if (sk2->sk_hash == snum &&
+ sk2 != sk &&
+ (!sk2->sk_reuse || !sk->sk_reuse) &&
+ (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+ || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+ (*saddr_comp)(sk, sk2) )
goto fail;
-
- if (!ops->saddr_any(sk)) {
- hash = ops->hash_port_and_rcv_saddr(snum, sk);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
-
- sk_for_each(sk2, node, head)
- if (sk2->sk_hash == hash &&
- sk2 != sk &&
- inet_sk(sk2)->num == snum &&
- (!sk2->sk_reuse || !sk->sk_reuse) &&
- (!sk2->sk_bound_dev_if ||
- !sk->sk_bound_dev_if ||
- sk2->sk_bound_dev_if ==
- sk->sk_bound_dev_if) &&
- ops->saddr_cmp(sk, sk2))
- goto fail;
- }
}
inet_sk(sk)->num = snum;
- sk->sk_hash = hash;
+ sk->sk_hash = snum;
if (sk_unhashed(sk)) {
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_add_node(sk, head);
sock_prot_inc_use(sk->sk_prot);
}
@@ -265,12 +214,12 @@ fail:
}
int udp_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops)
+ int (*scmp)(const struct sock *, const struct sock *))
{
- return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
+ return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
}
-static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
@@ -279,33 +228,9 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
inet1->rcv_saddr == inet2->rcv_saddr ));
}
-static int ipv4_rcv_saddr_any(const struct sock *sk)
-{
- return !inet_sk(sk)->rcv_saddr;
-}
-
-static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
-{
- addr ^= addr >> 16;
- addr ^= addr >> 8;
- return port ^ addr;
-}
-
-static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
- const struct sock *sk)
-{
- return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
-}
-
-const struct udp_get_port_ops udp_ipv4_ops = {
- .saddr_cmp = ipv4_rcv_saddr_equal,
- .saddr_any = ipv4_rcv_saddr_any,
- .hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
-};
-
static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, &udp_ipv4_ops);
+ return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
}
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -317,77 +242,63 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
{
struct sock *sk, *result = NULL;
struct hlist_node *node;
- unsigned int hash, hashwild;
- int score, best = -1, hport = ntohs(dport);
-
- hash = ipv4_hash_port_and_addr(hport, daddr);
- hashwild = udp_hash_port(hport);
+ unsigned short hnum = ntohs(dport);
+ int badness = -1;
read_lock(&udp_hash_lock);
-
-lookup:
-
- sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
struct inet_sock *inet = inet_sk(sk);
- if (sk->sk_hash != hash || ipv6_only_sock(sk) ||
- inet->num != hport)
- continue;
-
- score = (sk->sk_family == PF_INET ? 1 : 0);
- if (inet->rcv_saddr) {
- if (inet->rcv_saddr != daddr)
- continue;
- score+=2;
- }
- if (inet->daddr) {
- if (inet->daddr != saddr)
- continue;
- score+=2;
- }
- if (inet->dport) {
- if (inet->dport != sport)
- continue;
- score+=2;
- }
- if (sk->sk_bound_dev_if) {
- if (sk->sk_bound_dev_if != dif)
- continue;
- score+=2;
- }
- if (score == 9) {
- result = sk;
- goto found;
- } else if (score > best) {
- result = sk;
- best = score;
+ if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
+ int score = (sk->sk_family == PF_INET ? 1 : 0);
+ if (inet->rcv_saddr) {
+ if (inet->rcv_saddr != daddr)
+ continue;
+ score+=2;
+ }
+ if (inet->daddr) {
+ if (inet->daddr != saddr)
+ continue;
+ score+=2;
+ }
+ if (inet->dport) {
+ if (inet->dport != sport)
+ continue;
+ score+=2;
+ }
+ if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if != dif)
+ continue;
+ score+=2;
+ }
+ if (score == 9) {
+ result = sk;
+ break;
+ } else if (score > badness) {
+ result = sk;
+ badness = score;
+ }
}
}
-
- if (hash != hashwild) {
- hash = hashwild;
- goto lookup;
- }
-found:
if (result)
sock_hold(result);
read_unlock(&udp_hash_lock);
return result;
}
-static inline struct sock *udp_v4_mcast_next(struct sock *sk, unsigned int hnum,
- int hport, __be32 loc_addr,
+static inline struct sock *udp_v4_mcast_next(struct sock *sk,
+ __be16 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr,
int dif)
{
struct hlist_node *node;
struct sock *s = sk;
+ unsigned short hnum = ntohs(loc_port);
sk_for_each_from(s, node) {
struct inet_sock *inet = inet_sk(s);
if (s->sk_hash != hnum ||
- inet->num != hport ||
(inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) ||
(inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
@@ -1221,45 +1132,29 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
__be32 saddr, __be32 daddr,
struct hlist_head udptable[])
{
- struct sock *sk, *skw, *sknext;
+ struct sock *sk;
int dif;
- int hport = ntohs(uh->dest);
- unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
- unsigned int hashwild = udp_hash_port(hport);
-
- dif = skb->dev->ifindex;
read_lock(&udp_hash_lock);
-
- sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]);
- skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]);
-
- sk = udp_v4_mcast_next(sk, hash, hport, daddr, uh->source, saddr, dif);
- if (!sk) {
- hash = hashwild;
- sk = udp_v4_mcast_next(skw, hash, hport, daddr, uh->source,
- saddr, dif);
- }
+ sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+ dif = skb->dev->ifindex;
+ sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
if (sk) {
+ struct sock *sknext = NULL;
+
do {
struct sk_buff *skb1 = skb;
- sknext = udp_v4_mcast_next(sk_next(sk), hash, hport,
- daddr, uh->source, saddr, dif);
- if (!sknext && hash != hashwild) {
- hash = hashwild;
- sknext = udp_v4_mcast_next(skw, hash, hport,
- daddr, uh->source, saddr, dif);
- }
+
+ sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,
+ uh->source, saddr, dif);
if (sknext)
skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1) {
int ret = udp_queue_rcv_skb(sk, skb1);
if (ret > 0)
- /*
- * we should probably re-process
- * instead of dropping packets here.
- */
+ /* we should probably re-process instead
+ * of dropping packets here. */
kfree_skb(skb1);
}
sk = sknext;
@@ -1346,7 +1241,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
- skb->dev->ifindex, udptable);
+ skb->dev->ifindex, udptable );
if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb);
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 06d94195e64..820a477cfaa 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
#include <net/protocol.h>
#include <net/inet_common.h>
-extern const struct udp_get_port_ops udp_ipv4_ops;
-
extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- const struct udp_get_port_ops *ops);
+ int (*)(const struct sock*,const struct sock*));
+extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+
extern int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index 3653b32dce2..f34fd686a8f 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,15 +19,14 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
static int udplite_port_rover;
int udplite_get_port(struct sock *sk, unsigned short p,
- const struct udp_get_port_ops *ops)
+ int (*c)(const struct sock *, const struct sock *))
{
- return __udp_lib_get_port(sk, p, udplite_hash,
- &udplite_port_rover, ops);
+ return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
}
static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, &udp_ipv4_ops);
+ return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
}
static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 329de679ac3..5a5f8bd4597 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2990,7 +2990,7 @@ static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
return pfx;
}
-static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
[IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
[IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index fc3882c9060..53b3998a486 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -157,7 +157,7 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
return 1;
}
-static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
};
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index dc442fb791b..1b1797f1f33 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -160,6 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
{
struct nf_conn *ct;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo;
unsigned int ret, protoff;
unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
@@ -172,7 +173,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
goto out;
help = nfct_help(ct);
- if (!help || !help->helper)
+ if (!help)
+ goto out;
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(help->helper);
+ if (!helper)
goto out;
protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
@@ -182,7 +187,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
return NF_ACCEPT;
}
- ret = help->helper->help(pskb, protoff, ct, ctinfo);
+ ret = helper->help(pskb, protoff, ct, ctinfo);
if (ret != NF_ACCEPT)
return ret;
out:
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1324b06796c..fe8d9837f9f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1999,7 +1999,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
fib6_clean_all(rt6_mtu_change_route, 0, &arg);
}
-static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
+static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
[RTA_OIF] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d1fbddd172e..4210951edb6 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,28 +52,9 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
-static int ipv6_rcv_saddr_any(const struct sock *sk)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- return ipv6_addr_any(&np->rcv_saddr);
-}
-
-static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
- const struct sock *sk)
-{
- return port;
-}
-
-const struct udp_get_port_ops udp_ipv6_ops = {
- .saddr_cmp = ipv6_rcv_saddr_equal,
- .saddr_any = ipv6_rcv_saddr_any,
- .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
-};
-
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, &udp_ipv6_ops);
+ return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 36b0c11a28a..6e252f318f7 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,8 +6,6 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
-extern const struct udp_get_port_ops udp_ipv6_ops;
-
extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index c40a51362f8..f54016a5500 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, &udp_ipv6_ops);
+ return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
struct proto udplitev6_prot = {
diff --git a/net/key/af_key.c b/net/key/af_key.c
index d302ddae580..0f8304b0246 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1682,6 +1682,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
unsigned proto;
struct km_event c;
struct xfrm_audit audit_info;
+ int err;
proto = pfkey_satype2proto(hdr->sadb_msg_satype);
if (proto == 0)
@@ -1689,7 +1690,9 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0;
- xfrm_state_flush(proto, &audit_info);
+ err = xfrm_state_flush(proto, &audit_info);
+ if (err)
+ return err;
c.data.proto = proto;
c.seq = hdr->sadb_msg_seq;
c.pid = hdr->sadb_msg_pid;
@@ -2683,10 +2686,13 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
{
struct km_event c;
struct xfrm_audit audit_info;
+ int err;
audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0;
- xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ if (err)
+ return err;
c.data.type = XFRM_POLICY_TYPE_MAIN;
c.event = XFRM_MSG_FLUSHPOLICY;
c.pid = hdr->sadb_msg_pid;
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index b8869eab765..0568f2e86b5 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -208,13 +208,14 @@ static int __init nf_conntrack_amanda_init(void)
{
int ret, i;
- ret = -ENOMEM;
for (i = 0; i < ARRAY_SIZE(search); i++) {
search[i].ts = textsearch_prepare(ts_algo, search[i].string,
search[i].len,
GFP_KERNEL, TS_AUTOLOAD);
- if (search[i].ts == NULL)
+ if (IS_ERR(search[i].ts)) {
+ ret = PTR_ERR(search[i].ts);
goto err1;
+ }
}
ret = nf_conntrack_helper_register(&amanda_helper[0]);
if (ret < 0)
@@ -227,10 +228,9 @@ static int __init nf_conntrack_amanda_init(void)
err2:
nf_conntrack_helper_unregister(&amanda_helper[0]);
err1:
- for (; i >= 0; i--) {
- if (search[i].ts)
- textsearch_destroy(search[i].ts);
- }
+ while (--i >= 0)
+ textsearch_destroy(search[i].ts);
+
return ret;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 483e927a9ca..7a15e30356f 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -350,9 +350,15 @@ static void death_by_timeout(unsigned long ul_conntrack)
{
struct nf_conn *ct = (void *)ul_conntrack;
struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_helper *helper;
- if (help && help->helper && help->helper->destroy)
- help->helper->destroy(ct);
+ if (help) {
+ rcu_read_lock();
+ helper = rcu_dereference(help->helper);
+ if (helper && helper->destroy)
+ helper->destroy(ct);
+ rcu_read_unlock();
+ }
write_lock_bh(&nf_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path.
@@ -661,6 +667,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
unsigned int dataoff)
{
struct nf_conn *conntrack;
+ struct nf_conn_help *help;
struct nf_conntrack_tuple repl_tuple;
struct nf_conntrack_expect *exp;
u_int32_t features = 0;
@@ -691,6 +698,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
write_lock_bh(&nf_conntrack_lock);
exp = find_expectation(tuple);
+ help = nfct_help(conntrack);
if (exp) {
DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
conntrack, exp);
@@ -698,7 +706,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = exp->master;
if (exp->helper)
- nfct_help(conntrack)->helper = exp->helper;
+ rcu_assign_pointer(help->helper, exp->helper);
#ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark;
#endif
@@ -708,10 +716,11 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
} else {
- struct nf_conn_help *help = nfct_help(conntrack);
-
- if (help)
- help->helper = __nf_ct_helper_find(&repl_tuple);
+ if (help) {
+ /* not in hash table yet, so not strictly necessary */
+ rcu_assign_pointer(help->helper,
+ __nf_ct_helper_find(&repl_tuple));
+ }
NF_CT_STAT_INC(new);
}
@@ -893,7 +902,8 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
helper = __nf_ct_helper_find(newreply);
if (helper)
memset(&help->help, 0, sizeof(help->help));
- help->helper = helper;
+ /* not in hash table yet, so not strictly necessary */
+ rcu_assign_pointer(help->helper, helper);
}
write_unlock_bh(&nf_conntrack_lock);
}
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 117cbfdb910..504fb6c083f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -337,6 +337,10 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
NF_CT_ASSERT(master_help);
write_lock_bh(&nf_conntrack_lock);
+ if (!master_help->helper) {
+ ret = -ESHUTDOWN;
+ goto out;
+ }
list_for_each_entry(i, &nf_conntrack_expect_list, list) {
if (expect_matches(i, expect)) {
/* Refresh timer: if it's dying, ignore.. */
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 0743be4434b..f868b7fbd9b 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -93,7 +93,7 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
if (help && help->helper == me) {
nf_conntrack_event(IPCT_HELPER, ct);
- help->helper = NULL;
+ rcu_assign_pointer(help->helper, NULL);
}
return 0;
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d6d39e24132..3f73327794a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -171,21 +171,29 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
struct nfattr *nest_helper;
const struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_helper *helper;
- if (!help || !help->helper)
+ if (!help)
return 0;
+ rcu_read_lock();
+ helper = rcu_dereference(help->helper);
+ if (!helper)
+ goto out;
+
nest_helper = NFA_NEST(skb, CTA_HELP);
- NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
+ NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
- if (help->helper->to_nfattr)
- help->helper->to_nfattr(skb, ct);
+ if (helper->to_nfattr)
+ helper->to_nfattr(skb, ct);
NFA_NEST_END(skb, nest_helper);
-
+out:
+ rcu_read_unlock();
return 0;
nfattr_failure:
+ rcu_read_unlock();
return -1;
}
@@ -842,7 +850,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
if (help && help->helper) {
/* we had a helper before ... */
nf_ct_remove_expectations(ct);
- help->helper = NULL;
+ rcu_assign_pointer(help->helper, NULL);
}
return 0;
@@ -866,7 +874,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
/* need to zero data of old helper */
memset(&help->help, 0, sizeof(help->help));
- help->helper = helper;
+ rcu_assign_pointer(help->helper, helper);
return 0;
}
@@ -950,6 +958,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
struct nf_conn *ct;
int err = -EINVAL;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper = NULL;
ct = nf_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct))
@@ -980,14 +989,17 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
#endif
help = nfct_help(ct);
- if (help)
- help->helper = nf_ct_helper_find_get(rtuple);
+ if (help) {
+ helper = nf_ct_helper_find_get(rtuple);
+ /* not in hash table yet so not strictly necessary */
+ rcu_assign_pointer(help->helper, helper);
+ }
add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct);
- if (help && help->helper)
- nf_ct_helper_put(help->helper);
+ if (helper)
+ nf_ct_helper_put(helper);
return 0;
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 5434472420f..339c397d1b5 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -100,7 +100,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conn_help *help = nfct_help(ct);
struct nf_ct_gre_keymap **kmp, *km;
- BUG_ON(strcmp(help->helper->name, "pptp"));
kmp = &help->help.ct_pptp_info.keymap[dir];
if (*kmp) {
/* check whether it's a retransmission */
@@ -137,7 +136,6 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
enum ip_conntrack_dir dir;
DEBUGP("entering for ct %p\n", ct);
- BUG_ON(strcmp(help->helper->name, "pptp"));
write_lock_bh(&nf_ct_gre_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 07e47dbcb0a..24b660f16ce 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -59,7 +59,7 @@ static struct genl_family netlbl_cipsov4_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
+static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
[NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index f2535e7f286..b165712aaa7 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -246,19 +246,18 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
/**
* netlbl_socket_setattr - Label a socket using the correct protocol
- * @sock: the socket to label
+ * @sk: the socket to label
* @secattr: the security attributes
*
* Description:
* Attach the correct label to the given socket using the security attributes
- * specified in @secattr. This function requires exclusive access to
- * @sock->sk, which means it either needs to be in the process of being
- * created or locked via lock_sock(sock->sk). Returns zero on success,
- * negative values on failure.
+ * specified in @secattr. This function requires exclusive access to @sk,
+ * which means it either needs to be in the process of being created or locked.
+ * Returns zero on success, negative values on failure.
*
*/
-int netlbl_socket_setattr(const struct socket *sock,
- const struct netlbl_lsm_secattr *secattr)
+int netlbl_sock_setattr(struct sock *sk,
+ const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -ENOENT;
struct netlbl_dom_map *dom_entry;
@@ -269,9 +268,9 @@ int netlbl_socket_setattr(const struct socket *sock,
goto socket_setattr_return;
switch (dom_entry->type) {
case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_socket_setattr(sock,
- dom_entry->type_def.cipsov4,
- secattr);
+ ret_val = cipso_v4_sock_setattr(sk,
+ dom_entry->type_def.cipsov4,
+ secattr);
break;
case NETLBL_NLTYPE_UNLABELED:
ret_val = 0;
@@ -309,30 +308,6 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
}
/**
- * netlbl_socket_getattr - Determine the security attributes of a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Examines the given socket to see any NetLabel style labeling has been
- * applied to the socket, if so it parses the socket label and returns the
- * security attributes in @secattr. Returns zero on success, negative values
- * on failure.
- *
- */
-int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- int ret_val;
-
- ret_val = cipso_v4_socket_getattr(sock, secattr);
- if (ret_val == 0)
- return 0;
-
- return netlbl_unlabel_getattr(secattr);
-}
-
-/**
* netlbl_skbuff_getattr - Determine the security attributes of a packet
* @skb: the packet
* @secattr: the security attributes
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index e8c80f33f3d..e00fc219c72 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -59,7 +59,7 @@ static struct genl_family netlbl_mgmt_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
+static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index b931edee4b8..5c303c68af1 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -61,7 +61,7 @@ static struct genl_family netlbl_unlabel_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
+static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
};
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index df5f820a4c3..c591212793e 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -24,9 +24,9 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
};
static int validate_nla(struct nlattr *nla, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
- struct nla_policy *pt;
+ const struct nla_policy *pt;
int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype)
@@ -99,7 +99,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
* Returns 0 on success or a negative error code.
*/
int nla_validate(struct nlattr *head, int len, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
@@ -130,7 +130,7 @@ errout:
* Returns 0 on success or a negative error code.
*/
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 6e31234a419..b9ab62f938d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -472,7 +472,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
return skb;
}
-static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = {
+static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
.len = GENL_NAMSIZ - 1 },
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index be7d299acd7..d1c383fca82 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -599,6 +599,7 @@ static void atm_tc_destroy(struct Qdisc *sch)
/* races ? */
while ((flow = p->flows)) {
tcf_destroy_chain(flow->filter_list);
+ flow->filter_list = NULL;
if (flow->ref > 1)
printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow,
flow->ref);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index a294542cb8e..ee2d5967d10 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1748,10 +1748,12 @@ cbq_destroy(struct Qdisc* sch)
* classes from root to leafs which means that filters can still
* be bound to classes which have been destroyed already. --TGR '04
*/
- for (h = 0; h < 16; h++)
- for (cl = q->classes[h]; cl; cl = cl->next)
+ for (h = 0; h < 16; h++) {
+ for (cl = q->classes[h]; cl; cl = cl->next) {
tcf_destroy_chain(cl->filter_list);
-
+ cl->filter_list = NULL;
+ }
+ }
for (h = 0; h < 16; h++) {
struct cbq_class *next;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 87c794d8fa2..d70fa30d429 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1744,20 +1744,23 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
int chunk;
struct sk_buff *skb;
+ unix_state_lock(sk);
skb = skb_dequeue(&sk->sk_receive_queue);
if (skb==NULL)
{
if (copied >= target)
- break;
+ goto unlock;
/*
* POSIX 1003.1g mandates this order.
*/
if ((err = sock_error(sk)) != 0)
- break;
+ goto unlock;
if (sk->sk_shutdown & RCV_SHUTDOWN)
- break;
+ goto unlock;
+
+ unix_state_unlock(sk);
err = -EAGAIN;
if (!timeo)
break;
@@ -1771,7 +1774,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
}
mutex_lock(&u->readlock);
continue;
+ unlock:
+ unix_state_unlock(sk);
+ break;
}
+ unix_state_unlock(sk);
if (check_creds) {
/* Never glue messages from different writers */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 64a375178c5..157bfbd250b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -834,11 +834,67 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
}
EXPORT_SYMBOL(xfrm_policy_byid);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
{
- int dir;
+ int dir, err = 0;
+
+ for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+ struct xfrm_policy *pol;
+ struct hlist_node *entry;
+ int i;
+
+ hlist_for_each_entry(pol, entry,
+ &xfrm_policy_inexact[dir], bydst) {
+ if (pol->type != type)
+ continue;
+ err = security_xfrm_policy_delete(pol);
+ if (err) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSPD, 0,
+ pol, NULL);
+ return err;
+ }
+ }
+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+ hlist_for_each_entry(pol, entry,
+ xfrm_policy_bydst[dir].table + i,
+ bydst) {
+ if (pol->type != type)
+ continue;
+ err = security_xfrm_policy_delete(pol);
+ if (err) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSPD,
+ 0, pol, NULL);
+ return err;
+ }
+ }
+ }
+ }
+ return err;
+}
+#else
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+{
+ return 0;
+}
+#endif
+
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+{
+ int dir, err = 0;
write_lock_bh(&xfrm_policy_lock);
+
+ err = xfrm_policy_flush_secctx_check(type, audit_info);
+ if (err)
+ goto out;
+
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy *pol;
struct hlist_node *entry;
@@ -891,7 +947,9 @@ void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
xfrm_policy_count[dir] -= killed;
}
atomic_inc(&flow_cache_genid);
+out:
write_unlock_bh(&xfrm_policy_lock);
+ return err;
}
EXPORT_SYMBOL(xfrm_policy_flush);
@@ -2583,4 +2641,3 @@ restore_state:
}
EXPORT_SYMBOL(xfrm_migrate);
#endif
-
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 372f06eb8bb..85f3f43a6cc 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -391,12 +391,48 @@ int xfrm_state_delete(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_delete);
-void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
{
- int i;
- int err = 0;
+ int i, err = 0;
+
+ for (i = 0; i <= xfrm_state_hmask; i++) {
+ struct hlist_node *entry;
+ struct xfrm_state *x;
+
+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+ if (xfrm_id_proto_match(x->id.proto, proto) &&
+ (err = security_xfrm_state_delete(x)) != 0) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSA,
+ 0, NULL, x);
+
+ return err;
+ }
+ }
+ }
+
+ return err;
+}
+#else
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+{
+ return 0;
+}
+#endif
+
+int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+{
+ int i, err = 0;
spin_lock_bh(&xfrm_state_lock);
+ err = xfrm_state_flush_secctx_check(proto, audit_info);
+ if (err)
+ goto out;
+
for (i = 0; i <= xfrm_state_hmask; i++) {
struct hlist_node *entry;
struct xfrm_state *x;
@@ -419,8 +455,12 @@ restart:
}
}
}
+ err = 0;
+
+out:
spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq);
+ return err;
}
EXPORT_SYMBOL(xfrm_state_flush);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b14c7e590c3..c06883bf620 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1418,10 +1418,13 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct km_event c;
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
struct xfrm_audit audit_info;
+ int err;
audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid;
- xfrm_state_flush(p->proto, &audit_info);
+ err = xfrm_state_flush(p->proto, &audit_info);
+ if (err)
+ return err;
c.data.proto = p->proto;
c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
@@ -1582,7 +1585,9 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid;
- xfrm_policy_flush(type, &audit_info);
+ err = xfrm_policy_flush(type, &audit_info);
+ if (err)
+ return err;
c.data.type = type;
c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index e216d49624b..aea90d30d22 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1,14 +1,15 @@
#!/usr/bin/perl -w
# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
-# (c) 2005, Joel Scohpp <jschopp@austin.ibm.com> (the ugly bit)
+# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
# Licensed under the terms of the GNU GPL License version 2
use strict;
my $P = $0;
+$P =~ s@.*/@@g;
-my $V = '0.01';
+my $V = '0.04';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -26,7 +27,7 @@ GetOptions(
my $exit = 0;
if ($#ARGV < 0) {
- print "usage: patchstylecheckemail.pl [options] patchfile\n";
+ print "usage: $P [options] patchfile\n";
print "version: $V\n";
print "options: -q => quiet\n";
print " --no-tree => run without a kernel tree\n";
@@ -38,7 +39,8 @@ if ($tree && !top_of_kernel_tree()) {
exit(2);
}
-my @deprecated = ();
+my @dep_includes = ();
+my @dep_functions = ();
my $removal = 'Documentation/feature-removal-schedule.txt';
if ($tree && -f $removal) {
open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
@@ -46,22 +48,27 @@ if ($tree && -f $removal) {
if (/^Files:\s+(.*\S)/) {
for my $file (split(/[, ]+/, $1)) {
if ($file =~ m@include/(.*)@) {
- push(@deprecated, $1);
+ push(@dep_includes, $1);
}
}
+
+ } elsif (/^Funcs:\s+(.*\S)/) {
+ for my $func (split(/[, ]+/, $1)) {
+ push(@dep_functions, $func);
+ }
}
}
}
-my @lines = ();
+my @rawlines = ();
while (<>) {
chomp;
- push(@lines, $_);
+ push(@rawlines, $_);
if (eof(ARGV)) {
- if (!process($ARGV, @lines)) {
+ if (!process($ARGV, @rawlines)) {
$exit = 1;
}
- @lines = ();
+ @rawlines = ();
}
}
@@ -99,6 +106,130 @@ sub expand_tabs {
return $res;
}
+sub line_stats {
+ my ($line) = @_;
+
+ # Drop the diff line leader and expand tabs
+ $line =~ s/^.//;
+ $line = expand_tabs($line);
+
+ # Pick the indent from the front of the line.
+ my ($white) = ($line =~ /^(\s*)/);
+
+ return (length($line), length($white));
+}
+
+sub sanitise_line {
+ my ($line) = @_;
+
+ my $res = '';
+ my $l = '';
+
+ my $quote = '';
+
+ foreach my $c (split(//, $line)) {
+ if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
+ if ($quote eq '') {
+ $quote = $c;
+ $res .= $c;
+ $l = $c;
+ next;
+ } elsif ($quote eq $c) {
+ $quote = '';
+ }
+ }
+ if ($quote && $c ne "\t") {
+ $res .= "X";
+ } else {
+ $res .= $c;
+ }
+
+ $l = $c;
+ }
+
+ return $res;
+}
+
+sub ctx_block_get {
+ my ($linenr, $remain, $outer) = @_;
+ my $line;
+ my $start = $linenr - 1;
+ my $blk = '';
+ my @o;
+ my @c;
+ my @res = ();
+
+ for ($line = $start; $remain > 0; $line++) {
+ next if ($rawlines[$line] =~ /^-/);
+ $remain--;
+
+ $blk .= $rawlines[$line];
+
+ @o = ($blk =~ /\{/g);
+ @c = ($blk =~ /\}/g);
+
+ if (!$outer || (scalar(@o) - scalar(@c)) == 1) {
+ push(@res, $rawlines[$line]);
+ }
+
+ last if (scalar(@o) == scalar(@c));
+ }
+
+ return @res;
+}
+sub ctx_block_outer {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 1);
+}
+sub ctx_block {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 0);
+}
+
+sub ctx_locate_comment {
+ my ($first_line, $end_line) = @_;
+
+ # Catch a comment on the end of the line itself.
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+ return $current_comment if (defined $current_comment);
+
+ # Look through the context and try and figure out if there is a
+ # comment.
+ my $in_comment = 0;
+ $current_comment = '';
+ for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
+ my $line = $rawlines[$linenr - 1];
+ #warn " $line\n";
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@/\*@) {
+ $in_comment = 1;
+ }
+ if (!$in_comment && $current_comment ne '') {
+ $current_comment = '';
+ }
+ $current_comment .= $line . "\n" if ($in_comment);
+ if ($line =~ m@\*/@) {
+ $in_comment = 0;
+ }
+ }
+
+ chomp($current_comment);
+ return($current_comment);
+}
+sub ctx_has_comment {
+ my ($first_line, $end_line) = @_;
+ my $cmt = ctx_locate_comment($first_line, $end_line);
+
+ ##print "LINE: $rawlines[$end_line - 1 ]\n";
+ ##print "CMMT: $cmt\n";
+
+ return ($cmt ne '');
+}
+
sub cat_vet {
my ($vet) = @_;
@@ -116,7 +247,7 @@ sub process {
my $prevline="";
my $stashline="";
- my $lineforcounting='';
+ my $length;
my $indent;
my $previndent=0;
my $stashindent=0;
@@ -139,13 +270,14 @@ sub process {
#extract the filename as it passes
if ($line=~/^\+\+\+\s+(\S+)/) {
$realfile=$1;
+ $realfile =~ s@^[^/]*/@@;
$in_comment = 0;
next;
}
#extract the line range in the file after the patch is applied
if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
$is_patch = 1;
- $first_line = 1;
+ $first_line = $linenr + 1;
$in_comment = 0;
$realline=$1-1;
if (defined $2) {
@@ -156,10 +288,11 @@ sub process {
next;
}
-#track the line number as we move through the hunk
- if ($line=~/^[ \+]/) {
+# track the line number as we move through the hunk, note that
+# new versions of GNU diff omit the leading space on completely
+# blank context lines so we need to count that too.
+ if ($line =~ /^( |\+|$)/) {
$realline++;
- $realcnt-- if ($realcnt != 0);
# track any sort of multi-line comment. Obviously if
# the added text or context do not include the whole
@@ -168,7 +301,7 @@ sub process {
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
- if ($first_line and $line =~ m@^.\s*\*@) {
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
$in_comment = 1;
}
if ($line =~ m@/\*@) {
@@ -178,23 +311,20 @@ sub process {
$in_comment = 0;
}
- $lineforcounting = $line;
- $lineforcounting =~ s/^\+//;
- $lineforcounting = expand_tabs($lineforcounting);
-
- my ($white) = ($lineforcounting =~ /^(\s*)/);
- $indent = length($white);
+ # Measure the line length and indent.
+ ($length, $indent) = line_stats($line);
# Track the previous line.
($prevline, $stashline) = ($stashline, $line);
($previndent, $stashindent) = ($stashindent, $indent);
- $first_line = 0;
}
+ $realcnt-- if ($realcnt != 0);
#make up the handle for any error we report on this line
- $here = "PATCH: $ARGV:$linenr:";
- $here .= "\nFILE: $realfile:$realline:" if ($realcnt != 0);
+ $here = "#$linenr: ";
+ $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+ my $hereline = "$here\n$line\n";
my $herecurr = "$here\n$line\n\n";
my $hereprev = "$here\n$prevline\n$line\n\n";
@@ -203,6 +333,8 @@ sub process {
$signoff++;
} elsif ($line =~ /^\s*signed-off-by:/i) {
+ # This is a signoff, if ugly, so do not double report.
+ $signoff++;
if (!($line =~ /^\s*Signed-off-by:/)) {
print "use Signed-off-by:\n";
print "$herecurr";
@@ -215,21 +347,28 @@ sub process {
}
}
-#ignore lines not being added
- if ($line=~/^[^\+]/) {next;}
+# Check for wrappage within a valid hunk of the file
+ if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
+ print "patch seems to be corrupt (line wrapped?) [$realcnt]\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+#ignore lines being removed
+ if ($line=~/^-/) {next;}
-# check we are in a valid source file *.[hcsS] if not then ignore this hunk
- next if ($realfile !~ /\.[hcsS]$/);
+# check we are in a valid source file if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
#trailing whitespace
- if ($line=~/\S\s+$/) {
+ if ($line=~/\+.*\S\s+$/) {
my $herevet = "$here\n" . cat_vet($line) . "\n\n";
print "trailing whitespace\n";
print "$herevet";
$clean = 0;
}
#80 column limit
- if (!($prevline=~/\/\*\*/) && length($lineforcounting) > 80) {
+ if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
print "line over 80 characters\n";
print "$herecurr";
$clean = 0;
@@ -253,19 +392,59 @@ sub process {
#
next if ($in_comment);
+ # Remove comments from the line before processing.
+ $line =~ s@/\*.*\*/@@g;
+ $line =~ s@/\*.*@@;
+ $line =~ s@.*\*/@@;
+
+ #
+ # Checks which may be anchored in the context.
+ #
+
+ # Check for switch () and associated case and default
+ # statements should be at the same indent.
+ if ($line=~/\bswitch\s*\(.*\)/) {
+ my $err = '';
+ my $sep = '';
+ my @ctx = ctx_block_outer($linenr, $realcnt);
+ shift(@ctx);
+ for my $ctx (@ctx) {
+ my ($clen, $cindent) = line_stats($ctx);
+ if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
+ $indent != $cindent) {
+ $err .= "$sep$ctx\n";
+ $sep = '';
+ } else {
+ $sep = "[...]\n";
+ }
+ }
+ if ($err ne '') {
+ print "switch and case should be at the same indent\n";
+ print "$here\n$line\n$err\n";
+ $clean = 0;
+ }
+ }
+
+#ignore lines not being added
+ if ($line=~/^[^\+]/) {next;}
+
+ #
+ # Checks which are anchored on the added line.
+ #
+
# no C99 // comments
- if ($line =~ m@//@ and !($line =~ m@\".*//.*\"@)) {
+ if ($line =~ m{//}) {
print "do not use C99 // comments\n";
print "$herecurr";
$clean = 0;
}
-
- # Remove comments from the line before processing.
- $line =~ s@/\*.*\*/@@g;
- $line =~ s@/\*.*@@;
- $line =~ s@.*\*/@@;
+ # Remove C99 comments.
$line =~ s@//.*@@;
+ # Standardise the strings and chars within the input
+ # to simplify matching.
+ $line = sanitise_line($line);
+
#EXPORT_SYMBOL should immediately follow its function closing }.
if (($line =~ /EXPORT_SYMBOL.*\(.*\)/) ||
($line =~ /EXPORT_UNUSED_SYMBOL.*\(.*\)/)) {
@@ -293,8 +472,28 @@ sub process {
}
# * goes on variable not on type
- if ($line=~/[A-Za-z\d_]+\* [A-Za-z\d_]+/) {
- print "\"foo* bar\" should be \"foo *bar\"\n";
+ my $type = '(?:char|short|int|long|unsigned|float|double|' .
+ 'struct\s+[A-Za-z\d_]+|' .
+ 'union\s+[A-Za-z\d_]+)';
+
+ if ($line =~ m{[A-Za-z\d_]+(\*+) [A-Za-z\d_]+}) {
+ print "\"foo$1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{$type (\*) [A-Za-z\d_]+} ||
+ $line =~ m{[A-Za-z\d_]+ (\*\*+) [A-Za-z\d_]+}) {
+ print "\"foo $1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{\([A-Za-z\d_\s]+[A-Za-z\d_](\*+)\)}) {
+ print "\"(foo$1)\" should be \"(foo $1)\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{\([A-Za-z\d_\s]+[A-Za-z\d_]\s+(\*+)\s+\)}) {
+ print "\"(foo $1 )\" should be \"(foo $1)\"\n";
print "$herecurr";
$clean = 0;
}
@@ -306,11 +505,29 @@ sub process {
# $clean = 0;
# }
-# printk should use KERN_* levels
+# printk should use KERN_* levels. Note that follow on printk's on the
+# same line do not need a level, so we use the current block context
+# to try and find and validate the current printk. In summary the current
+# printk includes all preceeding printk's which have no newline on the end.
+# we assume the first bad printk is the one to report.
if ($line =~ /\bprintk\((?!KERN_)/) {
- print "printk() should include KERN_ facility level\n";
- print "$herecurr";
- $clean = 0;
+ my $ok = 0;
+ for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
+ #print "CHECK<$lines[$ln - 1]\n";
+ # we have a preceeding printk if it ends
+ # with "\n" ignore it, else it is to blame
+ if ($lines[$ln - 1] =~ m{\bprintk\(}) {
+ if ($rawlines[$ln - 1] !~ m{\\n"}) {
+ $ok = 1;
+ }
+ last;
+ }
+ }
+ if ($ok == 0) {
+ print "printk() should include KERN_ facility level\n";
+ print "$herecurr";
+ $clean = 0;
+ }
}
#function brace can't be on same line, except for #defines of do while, or if closed on same line
@@ -320,86 +537,91 @@ sub process {
print "$herecurr";
$clean = 0;
}
+ # Note we expand the line with the leading + as the real
+ # line will be displayed with the leading + and the tabs
+ # will therefore also expand that way.
my $opline = $line;
- $opline =~ s/^.//;
+ $opline = expand_tabs($opline);
+ $opline =~ s/^./ /;
if (!($line=~/\#\s*include/)) {
# Check operator spacing.
my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
+ my $off = 0;
for (my $n = 0; $n < $#elements; $n += 2) {
- # $wN says we have white-space before or after
- # $sN says we have a separator before or after
- # $oN says we have another operator before or after
- my $w1 = $elements[$n] =~ /\s$/;
- my $s1 = $elements[$n] =~ /(\[|\(|\s)$/;
- my $o1 = $elements[$n] eq '';
+ $off += length($elements[$n]);
+
+ my $a = '';
+ $a = 'V' if ($elements[$n] ne '');
+ $a = 'W' if ($elements[$n] =~ /\s$/);
+ $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+ $a = 'O' if ($elements[$n] eq '');
+ $a = 'E' if ($elements[$n] eq '' && $n == 0);
+
my $op = $elements[$n + 1];
- my $w2 = 1;
- my $s2 = 1;
- my $o2 = 0;
- # If we have something after the operator handle it.
+
+ my $c = '';
if (defined $elements[$n + 2]) {
- $w2 = $elements[$n + 2] =~ /^\s/;
- $s2 = $elements[$n + 2] =~ /^(\s|\)|\]|;)/;
- $o2 = $elements[$n + 2] eq '';
+ $c = 'V' if ($elements[$n + 2] ne '');
+ $c = 'W' if ($elements[$n + 2] =~ /^\s/);
+ $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
+ $c = 'O' if ($elements[$n + 2] eq '');
+ } else {
+ $c = 'E';
}
- # Generate the context.
- my $at = "here: ";
- for (my $m = $n; $m >= 0; $m--) {
- if ($elements[$m] ne '') {
- $at .= $elements[$m];
- last;
- }
- }
- $at .= $op;
- for (my $m = $n + 2; defined $elements[$m]; $m++) {
- if ($elements[$m] ne '') {
- $at .= $elements[$m];
- last;
- }
+ # Pick up the preceeding and succeeding characters.
+ my $ca = substr($opline, $off - 1, 1);
+ my $cc = '';
+ if (length($opline) > ($off + length($elements[$n]))) {
+ $cc = substr($opline, $off + 1 + length($elements[$n]), 1);
}
+ my $ctx = "${a}x${c}";
+
+ my $at = "(ctx:$ctx)";
+
+ my $ptr = (" " x $off) . "^";
+ my $hereptr = "$hereline$ptr\n\n";
+
##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
- # Skip things apparently in quotes.
- next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
# We need ; as an operator. // is a comment.
if ($op eq ';' or $op eq '//') {
# -> should have no spaces
} elsif ($op eq '->') {
- if ($s1 or $s2) {
+ if ($ctx =~ /Wx.|.xW/) {
print "no spaces around that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# , must have a space on the right.
} elsif ($op eq ',') {
- if (!$s2) {
+ if ($ctx !~ /.xW|.xE/) {
print "need space after that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# unary ! and unary ~ are allowed no space on the right
} elsif ($op eq '!' or $op eq '~') {
- if (!$s1 && !$o1) {
+ if ($ctx !~ /[WOEB]x./) {
print "need space before that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
- if ($s2) {
+ if ($ctx =~ /.xW/) {
print "no space after that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq '++' or $op eq '--') {
- if (($s1 && $s2) || ((!$s1 && !$o1) && (!$s2 && !$o2))) {
+ if ($ctx !~ /[WOB]x[^W]|[^W]x[WOB]/) {
print "need space one side of that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
@@ -415,15 +637,28 @@ sub process {
#
# - is the same
#
- # * is the same only adding:
+ } elsif ($op eq '&' or $op eq '-') {
+ if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
+ print "need space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # * is the same as & only adding:
# type:
# (foo *)
# (foo **)
#
- } elsif ($op eq '&' or $op eq '-' or $op eq '*') {
- if ($w2 and !$w1) {
+ } elsif ($op eq '*') {
+ if ($ca eq '*') {
+ if ($cc =~ /\s/) {
+ print "no space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ } elsif ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB/) {
print "need space before that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
@@ -431,18 +666,19 @@ sub process {
} elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
$op eq '^' or $op eq '|')
{
- if ($s1 != $s2) {
+ if ($ctx !~ /VxV|WxW|VxE|WxE/) {
print "need consistent spacing around '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# All the others need spaces both sides.
- } elsif (!$s1 or !$s2) {
+ } elsif ($ctx !~ /[EW]x[WE]/) {
print "need spaces around that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
+ $off += length($elements[$n + 1]);
}
}
@@ -454,7 +690,7 @@ sub process {
}
#goto labels aren't indented, allow a single space however
- if ($line=~/^.\s+[A-Za-z\d_]+:/ and
+ if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
print "labels should not be indented\n";
print "$herecurr";
@@ -462,15 +698,16 @@ sub process {
}
# Need a space before open parenthesis after if, while etc
- if ($line=~/(if|while|for|switch)\(/) {
+ if ($line=~/\b(if|while|for|switch)\(/) {
print "need a space before the open parenthesis\n";
print "$herecurr";
$clean = 0;
}
# Check for illegal assignment in if conditional.
- if ($line=~/(if|while)\s*\(.*[^<>!=]=[^=].*\)/) {
- print "do not use assignment in if condition\n";
+ if ($line=~/\b(if|while)\s*\(.*[^<>!=]=[^=].*\)/) {
+ #next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
+ print "do not use assignment in condition\n";
print "$herecurr";
$clean = 0;
}
@@ -484,17 +721,6 @@ sub process {
$clean = 0;
}
- # Check for switch () {<nl>case, these must be at the
- # same indent. We will only catch the first one, as our
- # context is very small but people tend to be consistent
- # so we will catch them out more often than not.
- if ($prevline=~/\s*switch\s*\(.*\)/ and $line=~/\s*case\s+/
- and $previndent != $indent) {
- print "switch and case should be at the same indent\n";
- print "$hereprev";
- $clean = 0;
- }
-
#studly caps, commented out until figure out how to distinguish between use of existing and adding new
# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
# print "No studly caps, use _\n";
@@ -520,11 +746,11 @@ sub process {
}
#if/while/etc brace do not go on next line, unless #defining a do while loop, or if that brace on the next line is for something else
- if ($prevline=~/(if|while|for|switch)\s*\(/) {
+ if ($prevline=~/\b(if|while|for|switch)\s*\(/) {
my @opened = $prevline=~/\(/g;
my @closed = $prevline=~/\)/g;
my $nr_line = $linenr;
- my $remaining = $realcnt;
+ my $remaining = $realcnt - 1;
my $next_line = $line;
my $extra_lines = 0;
my $display_segment = $prevline;
@@ -540,10 +766,10 @@ sub process {
@closed = $prevline=~/\)/g;
}
- if (($prevline=~/(if|while|for|switch)\s*\(.*\)\s*$/) and ($next_line=~/{/) and
- !($next_line=~/(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) {
+ if (($prevline=~/\b(if|while|for|switch)\s*\(.*\)\s*$/) and ($next_line=~/{/) and
+ !($next_line=~/\b(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) {
print "That { should be on the previous line\n";
- print "$display_segment\n$next_line\n\n";
+ print "$here\n$display_segment\n$next_line\n\n";
$clean = 0;
}
}
@@ -558,7 +784,7 @@ sub process {
}
# don't include deprecated include files
- for my $inc (@deprecated) {
+ for my $inc (@dep_includes) {
if ($line =~ m@\#\s*include\s*\<$inc>@) {
print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
print "$herecurr";
@@ -566,9 +792,56 @@ sub process {
}
}
-# don't use kernel_thread()
- if ($line =~ /\bkernel_thread\b/) {
- print "Don't use kernel_thread(), use kthread(): see Documentation/feature-removal-schedule.txt\n";
+# don't use deprecated functions
+ for my $func (@dep_functions) {
+ if ($line =~ /\b$func\b/) {
+ print "Don't use $func(): see Documentation/feature-removal-schedule.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# no volatiles please
+ if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
+ print "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #if 0
+ if ($line =~ /^.#\s*if\s+0\b/) {
+ print "#if 0 -- if this code redundant remove it\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #ifdefs in C files
+# if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+# print "#ifdef in C files should be avoided\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+# check for spinlock_t definitions without a comment.
+ if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
+ my $which = $1;
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "$1 definition without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check for memory barriers without a comment.
+ if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "memory barrier without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check of hardware specific defines
+ if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
+ print "architecture specific defines should be avoided\n";
print "$herecurr";
$clean = 0;
}
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index bf8750791dd..e64eca246f1 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -36,8 +36,8 @@
#include "security.h"
/**
- * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
- * @sock: the socket to label
+ * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
+ * @sk: the socket t