]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'libertas' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorJeff Garzik <jeff@garzik.org>
Wed, 13 Jun 2007 02:27:30 +0000 (22:27 -0400)
committerJeff Garzik <jeff@garzik.org>
Wed, 13 Jun 2007 02:27:30 +0000 (22:27 -0400)
243 files changed:
Documentation/SubmittingPatches
Documentation/atomic_ops.txt
Documentation/driver-model/platform.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/tmpfs.txt
Documentation/firmware_class/README
Documentation/firmware_class/firmware_sample_driver.c
Documentation/firmware_class/firmware_sample_firmware_class.c
Documentation/networking/00-INDEX
Documentation/networking/cxacru.txt [new file with mode: 0644]
Documentation/powerpc/booting-without-of.txt
MAINTAINERS
arch/arm/boot/compressed/head.S
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/pm.c
arch/arm/oprofile/op_model_mpcore.c
arch/i386/math-emu/fpu_entry.c
arch/i386/mm/fault.c
arch/m68knommu/platform/5307/timers.c
arch/mips/Kconfig
arch/mips/emma2rh/markeins/setup.c
arch/mips/kernel/linux32.c
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/traps.c
arch/mips/mips-boards/atlas/atlas_setup.c
arch/mips/mips-boards/generic/display.c
arch/mips/mips-boards/generic/time.c
arch/mips/mips-boards/malta/malta_setup.c
arch/mips/mips-boards/sead/sead_setup.c
arch/mips/mm/dma-default.c
arch/mips/qemu/q-irq.c
arch/mips/sni/pcimt.c
arch/mips/sni/setup.c
arch/powerpc/boot/crt0.S
arch/powerpc/kernel/of_platform.c
arch/powerpc/platforms/cell/cbe_cpufreq.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/celleb/Makefile
arch/powerpc/platforms/pasemi/iommu.c
arch/ppc/syslib/qspan_pci.c
arch/sh/boards/se/73180/setup.c
arch/sh/boards/superh/microdev/irq.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/mm/ioremap.c
arch/sh64/kernel/pci_sh5.c
arch/sparc64/Kconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/mdesc.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/sysfs.c [new file with mode: 0644]
arch/um/Kconfig
arch/um/drivers/line.c
arch/um/drivers/stderr_console.c
arch/um/drivers/ubd_kern.c
arch/um/kernel/exitcode.c
arch/x86_64/kernel/traps.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/xtensa/kernel/asm-offsets.c
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/head.S
arch/xtensa/kernel/pci.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/lib/strncpy_user.S
arch/xtensa/lib/strnlen_user.S
arch/xtensa/mm/init.c
arch/xtensa/platform-iss/network.c
drivers/ata/Kconfig
drivers/ata/sata_promise.c
drivers/base/class.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/block/loop.c
drivers/cdrom/mcdx.c
drivers/char/stallion.c
drivers/infiniband/hw/amso1100/c2.c
drivers/input/keyboard/pxa27x_keyboard.c
drivers/isdn/hardware/eicon/divasfunc.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/e100.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/ibmveth.c
drivers/net/myri10ge/myri10ge.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_isr.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_niu.c
drivers/net/phy/marvell.c
drivers/net/usb/Kconfig
drivers/net/via-velocity.c
drivers/serial/amba-pl010.c
drivers/tc/zs.c
drivers/usb/atm/cxacru.c
drivers/usb/class/usblp.c
drivers/usb/core/Kconfig
drivers/usb/core/config.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/host/ohci-hub.c
drivers/usb/storage/unusual_devs.h
drivers/video/console/Makefile
drivers/video/ffb.c
drivers/video/sunxvr2500.c
drivers/video/sunxvr500.c
fs/binfmt_flat.c
fs/ocfs2/aops.c
fs/ocfs2/cluster/masklog.c
fs/ramfs/file-nommu.c
include/asm-arm/arch-at91/at91_shdwc.h
include/asm-arm/arch-at91/at91_wdt.h
include/asm-arm/arch-pxa/gpio.h
include/asm-frv/system.h
include/asm-mips/asmmacro.h
include/asm-mips/mips-boards/prom.h
include/asm-mips/unistd.h
include/asm-sh/se73180.h
include/asm-sparc64/cpudata.h
include/asm-sparc64/dma-mapping.h
include/asm-sparc64/hypervisor.h
include/asm-sparc64/smp.h
include/asm-sparc64/topology.h
include/asm-xtensa/bitops.h
include/asm-xtensa/byteorder.h
include/asm-xtensa/coprocessor.h
include/asm-xtensa/div64.h
include/asm-xtensa/elf.h
include/asm-xtensa/fcntl.h
include/asm-xtensa/mmu_context.h
include/asm-xtensa/page.h
include/asm-xtensa/param.h
include/asm-xtensa/ptrace.h
include/asm-xtensa/shmparam.h
include/asm-xtensa/sigcontext.h
include/asm-xtensa/thread_info.h
include/asm-xtensa/unistd.h
include/linux/console_struct.h
include/linux/inetdevice.h
include/linux/kernel.h
include/linux/netfilter_ipv4/ip_tables.h
include/linux/rfkill.h
include/linux/sched.h
include/linux/slub_def.h
include/net/cipso_ipv4.h
include/net/fib_rules.h
include/net/genetlink.h
include/net/ip.h
include/net/ip_fib.h
include/net/netlabel.h
include/net/netlink.h
include/net/udp.h
include/net/udplite.h
include/net/xfrm.h
kernel/exit.c
kernel/futex.c
kernel/rtmutex.c
kernel/signal.c
lib/hexdump.c
lib/kobject.c
mm/shmem.c
mm/slab.c
mm/slub.c
mm/sparse.c
net/core/dev.c
net/core/dst.c
net/core/neighbour.c
net/core/rtnetlink.c
net/decnet/dn_dev.c
net/decnet/dn_rules.c
net/ipv4/arp.c
net/ipv4/cipso_ipv4.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_rules.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/proc.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_probe.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv4/udplite.c
net/ipv6/addrconf.c
net/ipv6/fib6_rules.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/route.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c
net/key/af_key.c
net/netfilter/nf_conntrack_amanda.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_gre.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_unlabeled.c
net/netlink/attr.c
net/netlink/genetlink.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/unix/af_unix.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/checkpatch.pl [changed mode: 0644->0755]
security/selinux/netlabel.c

index d91125ab6f49253fece7bc6e056cd248ec7812ec..0958e97d4bf4326ad0f6bc6418263f403d168eda 100644 (file)
@@ -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:
 
index 2a63d5662a93a1fd2e0889bc6aab93c1ae987102..05851e9982edfefbab5ead5b774ab976926a12e4 100644 (file)
@@ -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:
 
index 19c4a6e136760750365483d49751edb4853daad6..2a97320ee17f1d1b1c5a9b1efc138bbea4631f0e 100644 (file)
@@ -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.
index 49ae1ea9e868d9d0803e8d2711748be45cc1a546..7d3f205b0ba50fddc8da631ba9fad29063239256 100644 (file)
@@ -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
index 6dd050878a2087269b9891f704177dc7f1dc1462..145e44086358653e4b8b6b17302f3b7652246194 100644 (file)
@@ -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
index e9cc8bb26f7d0952b0226c66e6a43abe8e00a211..c3480aa66ba8048bf46483544ed6fb3ebb7151eb 100644 (file)
@@ -1,7 +1,7 @@
 
  request_firmware() hotplug interface:
  ------------------------------------
-       Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
+       Copyright (C) 2003 Manuel Estrada Sainz
 
  Why:
  ---
index 87feccdb5c9f8f67b2739358edca07c76a9a24a1..6865cbe075ec3549cf033fa3c11c07bb0ee4eef6 100644 (file)
@@ -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.
  *
index 9e1b0e4051cd0546985b9985fd308d301d537c41..4994f1f28f8ce23bf56ec61976cbefe19c008d41 100644 (file)
@@ -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");
 
index e06b6e3c1db577d5fe513cc2ea045e3d57507564..153d84d281e6aa6fa8c1bb6e001d39f8660c0444 100644 (file)
@@ -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 (file)
index 0000000..b074681
--- /dev/null
@@ -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)
index b49ce169a63aa27d75271a45948b0c1ed8d15ecd..d42d98107d494d906ded560a3e61bfad829e8911 100644 (file)
@@ -1,7 +1,6 @@
            Booting the Linux/ppc kernel without Open Firmware
            --------------------------------------------------
 
-
 (c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
     IBM Corp.
 (c) 2005 Becky Bruce <becky.bruce at freescale.com>,
@@ -9,6 +8,62 @@
 (c) 2006 MontaVista Software, Inc.
     Flash chip node definition
 
+Table of Contents
+=================
+
+  I - Introduction
+    1) Entry point for arch/powerpc
+    2) Board support
+
+  II - The DT block format
+    1) Header
+    2) Device tree generalities
+    3) Device tree "structure" block
+    4) Device tree "strings" block
+
+  III - Required content of the device tree
+    1) Note about cells and address representation
+    2) Note about "compatible" properties
+    3) Note about "name" properties
+    4) Note about node and property names and character set
+    5) Required nodes and properties
+      a) The root node
+      b) The /cpus node
+      c) The /cpus/* nodes
+      d) the /memory node(s)
+      e) The /chosen node
+      f) the /soc<SOCname> node
+
+  IV - "dtc", the device tree compiler
+
+  V - Recommendations for a bootloader
+
+  VI - System-on-a-chip devices and nodes
+    1) Defining child nodes of an SOC
+    2) Representing devices without a current OF specification
+      a) MDIO IO device
+      c) PHY nodes
+      b) Gianfar-compatible ethernet nodes
+      d) Interrupt controllers
+      e) I2C
+      f) Freescale SOC USB controllers
+      g) Freescale SOC SEC Security Engines
+      h) Board Control and Status (BCSR)
+      i) Freescale QUICC Engine module (QE)
+      g) Flash chip nodes
+
+  VII - Specifying interrupt information for devices
+    1) interrupts property
+    2) interrupt-parent property
+    3) OpenPIC Interrupt Controllers
+    4) ISA Interrupt Controllers
+
+  Appendix A - Sample SOC node for MPC8540
+
+
+Revision Information
+====================
+
    May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
 
    May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
@@ -1687,7 +1742,7 @@ platforms are moved over to use the flattened-device-tree model.
                };
        };
 
-    g) Flash chip nodes
+    j) Flash chip nodes
 
     Flash chips (Memory Technology Devices) are often used for solid state
     file systems on embedded devices.
index f3b5a391e074822b9303d8bd06e5743efbddacaa..4c715a7e059a70f914ad49f9d6b747964e129c5f 100644 (file)
@@ -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
index 2568d311be215a7301bc752f4813a9e64e866999..23348e9561b92070406f4d40a7a5060190561e6e 100644 (file)
@@ -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
index 06c9a0507d0d8316137507979a62d631f2861769..848efb2a4ebfbc14cc7bf9426dadc04ca5c194e1 100644 (file)
@@ -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");
index ff8db29e989e2f39c420a9de219f63b435ace081..47ff676aca5f07e8155a4380a5f9da99f05546a5 100644 (file)
@@ -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
index 7791da791f5f936cb54c7d1f7cf38832652007e5..75bae067922d1c55fdef728f67e8f952062009be 100644 (file)
@@ -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;
 }
index ddf8fa3bbd01d7c15ef03abf6c7c55c5356ebd57..1853524c8b576f5420de5cbd746aecb30f594d50 100644 (file)
@@ -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;
index 29d7d61543a1dec88f2e2a1c348e5a696c1e70d2..1ecb3e43b523387388a99e2ed7cccdf0a7cdd131 100644 (file)
@@ -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.
index 92e58070b01664f31d10625b02822ddc2ede3bff..fb66eadd589633cf02ecc9e9f89dffe395a808ef 100644 (file)
@@ -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))
index 0f09412e1b7f249629166b5dce4d4f95cc59fd76..9528ee90640acc9ac99923f454e9db262405fc27 100644 (file)
@@ -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
index b29a447392306056bdbe2ca877d171c39e876f94..2f060e1ed36c674c0e9da4e0d11f281edc8d07a0 100644 (file)
@@ -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)
index 37849edd0645df1d611613a0838c351f3f98f552..06e04da211d57ec9f36a07dae2a34f2d56289d9c 100644 (file)
@@ -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)
index cc566cf122464f8672685766dd595bc8cc50cceb..06729596812f744581cce609938fee82d36d25cc 100644 (file)
@@ -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
index 6eac28337423536c3f1bf19988b0606611706f39..1631035ffc243aa5fdf730828127d87dcf0d3685 100644 (file)
@@ -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
index 7e74b412a782b8133b1557a6d69c58a710872a14..2aa99426ac1c11332e4e430a4131b6b8817ff01e 100644 (file)
@@ -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
index 200de027f354ec8e0bb0919ab707f0ff4e640af1..3f58b6ac135815fe5944d3f98ec943f1529ce41d 100644 (file)
@@ -927,12 +927,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 +1122,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;
index 0c6b0ce15028827c6e1e069bcf2ee497d23dfc3b..1cc6ebbedfdd8cc89d611f71522478dd90f96adf 100644 (file)
@@ -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();
index 548dbe5ce7c8c889447ee24df97e2987ceca5d28..5d600054090a5c258a448a77340de12d205fd906 100644 (file)
  */
 
 #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);
+}
index df2a2bd3aa5d198188e0fc3f8e1eadb167ee5dfd..37735bfc3afda540f7bb56adae0cfc0dcd7d075e 100644 (file)
 
 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);
@@ -143,7 +117,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
                if (cpu_data[cpu].vpe_id == 0) {
                                timer_interrupt(irq, NULL);
                                smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-                               scroll_display_message();
                } else {
                        write_c0_compare(read_c0_count() +
                                         (mips_hpt_frequency/HZ));
@@ -167,8 +140,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 +233,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)
index 7873932532a10b9fc2c8186bf6bfdca2d6ef3923..c14b7bf89950cb131445c509ef0dbec189645417 100644 (file)
@@ -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)
 {
index a189dec7c7bc8603ebecce5eab41570144ca236e..811aba100605aa53711930e400f21f82b17cac15 100644 (file)
@@ -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;
index f0eb29917d9aa3443a44c404f7ca3b5762eb0a99..76903c7276475145fa1661ae8d08df5bde458747 100644 (file)
@@ -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;
index f5ea2fe10f141d598b70a85f3d6514b73c54331c..89891e984b3bc3c67f0c66ee81a65bb691311941 100644 (file)
@@ -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();
index 9ee208daa8b12f238adb47a4d796f4706b5fff2a..97b234361b4d0afa8d5c0b64434c2bf07a253292 100644 (file)
@@ -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;
index 68d7cf609b4fcabd36396ec85c4838b203ff1f89..4fedfbda0c791b71a8ccfa94080fa80c6a0eee27 100644 (file)
@@ -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
index 5a4215c4b0146aa063fe87c5bb503a398232f6d3..f1c4dfc635be20380d6a718d420cb83b6e4a6068 100644 (file)
@@ -13,6 +13,7 @@
 
        .text
        /* a procedure descriptor used when booting this as a COFF file */
+       .globl  _zimage_start_opd
 _zimage_start_opd:
        .long   _zimage_start, 0, 0, 0
 
index d501c23e5159559ca493caf512e888ca6671e73a..d454f61c9c7c7b5a84c00ef3f66b730e436171ee 100644 (file)
@@ -433,7 +433,7 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
         * Note also that we don't do ISA, this will also be fixed with a
         * more massive rework.
         */
-       pci_setup_phb_io(phb, 0);
+       pci_setup_phb_io(phb, pci_io_base == 0);
 
        /* Init pci_dn data structures */
        pci_devs_phb_init_dynamic(phb);
index f9ac3fe3be9767fbf04a73296dfc365d3efbbec7..ac445998d8313d087964e0e6133f272a6b080ab8 100644 (file)
@@ -67,6 +67,7 @@ static u64 MIC_Slow_Next_Timer_table[] = {
        0x00003FC000000000ull,
 };
 
+static unsigned int pmi_frequency_limit = 0;
 /*
  * hardware specific functions
  */
@@ -164,7 +165,6 @@ static int set_pmode(int cpu, unsigned int slow_mode) {
 
 static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
 {
-       struct cpufreq_policy policy;
        u8 cpu;
        u8 cbe_pmode_new;
 
@@ -173,15 +173,27 @@ static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
        cpu = cbe_node_to_cpu(pmi_msg.data1);
        cbe_pmode_new = pmi_msg.data2;
 
-       cpufreq_get_policy(&policy, cpu);
+       pmi_frequency_limit = cbe_freqs[cbe_pmode_new].frequency;
 
-       policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency);
-       policy.min = min(policy.min, policy.max);
+       pr_debug("cbe_handle_pmi: max freq=%d\n", pmi_frequency_limit);
+}
+
+static int pmi_notifier(struct notifier_block *nb,
+                                      unsigned long event, void *data)
+{
+       struct cpufreq_policy *policy = data;
 
-       pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max);
-       cpufreq_set_policy(&policy);
+       if (event != CPUFREQ_INCOMPATIBLE)
+               return 0;
+
+       cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
+       return 0;
 }
 
+static struct notifier_block pmi_notifier_block = {
+       .notifier_call = pmi_notifier,
+};
+
 static struct pmi_handler cbe_pmi_handler = {
        .type                   = PMI_TYPE_FREQ_CHANGE,
        .handle_pmi_message     = cbe_cpufreq_handle_pmi,
@@ -238,12 +250,21 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
+       if (pmi_dev) {
+               /* frequency might get limited later, initialize limit with max_freq */
+               pmi_frequency_limit = max_freq;
+               cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+       }
+
        /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
        return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
 }
 
 static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
+       if (pmi_dev)
+               cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+
        cpufreq_frequency_table_put_attr(policy->cpu);
        return 0;
 }
index 8654749e317bae0aa67795dda4ba2eebdae50c3f..7c51cb54bca1ca8ba78c5074631247465dc784e7 100644 (file)
@@ -39,7 +39,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        if (spu_init_csa(&ctx->csa))
                goto out_free;
        spin_lock_init(&ctx->mmio_lock);
-       spin_lock_init(&ctx->mapping_lock);
+       mutex_init(&ctx->mapping_lock);
        kref_init(&ctx->kref);
        mutex_init(&ctx->state_mutex);
        mutex_init(&ctx->run_mutex);
@@ -103,6 +103,7 @@ void spu_forget(struct spu_context *ctx)
 
 void spu_unmap_mappings(struct spu_context *ctx)
 {
+       mutex_lock(&ctx->mapping_lock);
        if (ctx->local_store)
                unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
        if (ctx->mfc)
@@ -117,6 +118,7 @@ void spu_unmap_mappings(struct spu_context *ctx)
                unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
        if (ctx->psmap)
                unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
+       mutex_unlock(&ctx->mapping_lock);
 }
 
 /**
index 45614c73c7841824d1a1f47834ebc2838bfbbe0a..b1e7e2f8a2e9256f4263a1ee72a589de6c592408 100644 (file)
@@ -45,11 +45,11 @@ spufs_mem_open(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = ctx;
        if (!i->i_openers++)
                ctx->local_store = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -59,10 +59,10 @@ spufs_mem_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->local_store = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -217,6 +217,7 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
 
 static const struct file_operations spufs_mem_fops = {
        .open                   = spufs_mem_open,
+       .release                = spufs_mem_release,
        .read                   = spufs_mem_read,
        .write                  = spufs_mem_write,
        .llseek                 = generic_file_llseek,
@@ -309,11 +310,11 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = ctx;
        if (!i->i_openers++)
                ctx->cntl = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return simple_attr_open(inode, file, spufs_cntl_get,
                                        spufs_cntl_set, "0x%08lx");
 }
@@ -326,10 +327,10 @@ spufs_cntl_release(struct inode *inode, struct file *file)
 
        simple_attr_close(inode, file);
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->cntl = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -812,11 +813,11 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = ctx;
        if (!i->i_openers++)
                ctx->signal1 = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return nonseekable_open(inode, file);
 }
 
@@ -826,10 +827,10 @@ spufs_signal1_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->signal1 = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -936,11 +937,11 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = ctx;
        if (!i->i_openers++)
                ctx->signal2 = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return nonseekable_open(inode, file);
 }
 
@@ -950,10 +951,10 @@ spufs_signal2_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->signal2 = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -1154,10 +1155,10 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
 
        file->private_data = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!i->i_openers++)
                ctx->mss = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return nonseekable_open(inode, file);
 }
 
@@ -1167,10 +1168,10 @@ spufs_mss_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->mss = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -1211,11 +1212,11 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = i->i_ctx;
        if (!i->i_openers++)
                ctx->psmap = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return nonseekable_open(inode, file);
 }
 
@@ -1225,10 +1226,10 @@ spufs_psmap_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->psmap = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
@@ -1281,11 +1282,11 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
        if (atomic_read(&inode->i_count) != 1)
                return -EBUSY;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        file->private_data = ctx;
        if (!i->i_openers++)
                ctx->mfc = inode->i_mapping;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return nonseekable_open(inode, file);
 }
 
@@ -1295,10 +1296,10 @@ spufs_mfc_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       spin_lock(&ctx->mapping_lock);
+       mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
                ctx->mfc = NULL;
-       spin_unlock(&ctx->mapping_lock);
+       mutex_unlock(&ctx->mapping_lock);
        return 0;
 }
 
index 7150730e2ff11b9896039bd46a05ef83c8d26931..9807206e02196d479b1ea171ecc754fae9c7a746 100644 (file)
@@ -177,7 +177,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
                          int mode, struct spu_context *ctx)
 {
-       struct dentry *dentry;
+       struct dentry *dentry, *tmp;
        int ret;
 
        while (files->name && files->name[0]) {
@@ -193,7 +193,20 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
        }
        return 0;
 out:
-       spufs_prune_dir(dir);
+       /*
+        * remove all children from dir. dir->inode is not set so don't
+        * just simply use spufs_prune_dir() and panic afterwards :)
+        * dput() looks like it will do the right thing:
+        * - dec parent's ref counter
+        * - remove child from parent's child list
+        * - free child's inode if possible
+        * - free child
+        */
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+               dput(dentry);
+       }
+
+       shrink_dcache_parent(dir);
        return ret;
 }
 
@@ -274,6 +287,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
        goto out;
 
 out_free_ctx:
+       spu_forget(ctx);
        put_spu_context(ctx);
 out_iput:
        iput(inode);
@@ -349,37 +363,6 @@ out:
        return ret;
 }
 
-static int spufs_rmgang(struct inode *root, struct dentry *dir)
-{
-       /* FIXME: this fails if the dir is not empty,
-                 which causes a leak of gangs. */
-       return simple_rmdir(root, dir);
-}
-
-static int spufs_gang_close(struct inode *inode, struct file *file)
-{
-       struct inode *parent;
-       struct dentry *dir;
-       int ret;
-
-       dir = file->f_path.dentry;
-       parent = dir->d_parent->d_inode;
-
-       ret = spufs_rmgang(parent, dir);
-       WARN_ON(ret);
-
-       return dcache_dir_close(inode, file);
-}
-
-const struct file_operations spufs_gang_fops = {
-       .open           = dcache_dir_open,
-       .release        = spufs_gang_close,
-       .llseek         = dcache_dir_lseek,
-       .read           = generic_read_dir,
-       .readdir        = dcache_readdir,
-       .fsync          = simple_sync_file,
-};
-
 static int
 spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
 {
@@ -407,7 +390,6 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
        inode->i_fop = &simple_dir_operations;
 
        d_instantiate(dentry, inode);
-       dget(dentry);
        dir->i_nlink++;
        dentry->d_inode->i_nlink++;
        return ret;
@@ -437,7 +419,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
                goto out;
        }
 
-       filp->f_op = &spufs_gang_fops;
+       filp->f_op = &simple_dir_operations;
        fd_install(ret, filp);
 out:
        return ret;
@@ -458,8 +440,10 @@ static int spufs_create_gang(struct inode *inode,
         * in error path of *_open().
         */
        ret = spufs_gang_open(dget(dentry), mntget(mnt));
-       if (ret < 0)
-               WARN_ON(spufs_rmgang(inode, dentry));
+       if (ret < 0) {
+               int err = simple_rmdir(inode, dentry);
+               WARN_ON(err);
+       }
 
 out:
        mutex_unlock(&inode->i_mutex);
@@ -600,6 +584,10 @@ spufs_create_root(struct super_block *sb, void *data)
        struct inode *inode;
        int ret;
 
+       ret = -ENODEV;
+       if (!spu_management_ops)
+               goto out;
+
        ret = -ENOMEM;
        inode = spufs_new_inode(sb, S_IFDIR | 0775);
        if (!inode)
index b6ecb30e7d58b71ef8530f13bd02ea4bfe21039e..3b831e07f1ed740eabf0cd95fcafb985f105a8f2 100644 (file)
@@ -93,43 +93,6 @@ void spu_stop_tick(struct spu_context *ctx)
        }
 }
 
-void spu_sched_tick(struct work_struct *work)
-{
-       struct spu_context *ctx =
-               container_of(work, struct spu_context, sched_work.work);
-       struct spu *spu;
-       int preempted = 0;
-
-       /*
-        * If this context is being stopped avoid rescheduling from the
-        * scheduler tick because we would block on the state_mutex.
-        * The caller will yield the spu later on anyway.
-        */
-       if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
-               return;
-
-       mutex_lock(&ctx->state_mutex);
-       spu = ctx->spu;
-       if (spu) {
-               int best = sched_find_first_bit(spu_prio->bitmap);
-               if (best <= ctx->prio) {
-                       spu_deactivate(ctx);
-                       preempted = 1;
-               }
-       }
-       mutex_unlock(&ctx->state_mutex);
-
-       if (preempted) {
-               /*
-                * We need to break out of the wait loop in spu_run manually
-                * to ensure this context gets put on the runqueue again
-                * ASAP.
-                */
-               wake_up(&ctx->stop_wq);
-       } else
-               spu_start_tick(ctx);
-}
-
 /**
  * spu_add_to_active_list - add spu to active list
  * @spu:       spu to add to the active list
@@ -273,34 +236,6 @@ static void spu_prio_wait(struct spu_context *ctx)
        remove_wait_queue(&ctx->stop_wq, &wait);
 }
 
-/**
- * spu_reschedule - try to find a runnable context for a spu
- * @spu:       spu available
- *
- * This function is called whenever a spu becomes idle.  It looks for the
- * most suitable runnable spu context and schedules it for execution.
- */
-static void spu_reschedule(struct spu *spu)
-{
-       int best;
-
-       spu_free(spu);
-
-       spin_lock(&spu_prio->runq_lock);
-       best = sched_find_first_bit(spu_prio->bitmap);
-       if (best < MAX_PRIO) {
-               struct list_head *rq = &spu_prio->runq[best];
-               struct spu_context *ctx;
-
-               BUG_ON(list_empty(rq));
-
-               ctx = list_entry(rq->next, struct spu_context, rq);
-               __spu_del_from_rq(ctx);
-               wake_up(&ctx->stop_wq);
-       }
-       spin_unlock(&spu_prio->runq_lock);
-}
-
 static struct spu *spu_get_idle(struct spu_context *ctx)
 {
        struct spu *spu = NULL;
@@ -428,6 +363,51 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
        return -ERESTARTSYS;
 }
 
+/**
+ * grab_runnable_context - try to find a runnable context
+ *
+ * Remove the highest priority context on the runqueue and return it
+ * to the caller.  Returns %NULL if no runnable context was found.
+ */
+static struct spu_context *grab_runnable_context(int prio)
+{
+       struct spu_context *ctx = NULL;
+       int best;
+
+       spin_lock(&spu_prio->runq_lock);
+       best = sched_find_first_bit(spu_prio->bitmap);
+       if (best < prio) {
+               struct list_head *rq = &spu_prio->runq[best];
+
+               BUG_ON(list_empty(rq));
+
+               ctx = list_entry(rq->next, struct spu_context, rq);
+               __spu_del_from_rq(ctx);
+       }
+       spin_unlock(&spu_prio->runq_lock);
+
+       return ctx;
+}
+
+static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
+{
+       struct spu *spu = ctx->spu;
+       struct spu_context *new = NULL;
+
+       if (spu) {
+               new = grab_runnable_context(max_prio);
+               if (new || force) {
+                       spu_unbind_context(spu, ctx);
+                       spu_free(spu);
+                       if (new)
+                               wake_up(&new->stop_wq);
+               }
+
+       }
+
+       return new != NULL;
+}
+
 /**
  * spu_deactivate - unbind a context from it's physical spu
  * @ctx:       spu context to unbind
@@ -437,12 +417,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
  */
 void spu_deactivate(struct spu_context *ctx)
 {
-       struct spu *spu = ctx->spu;
-
-       if (spu) {
-               spu_unbind_context(spu, ctx);
-               spu_reschedule(spu);
-       }
+       __spu_deactivate(ctx, 1, MAX_PRIO);
 }
 
 /**
@@ -455,21 +430,43 @@ void spu_deactivate(struct spu_context *ctx)
  */
 void spu_yield(struct spu_context *ctx)
 {
-       struct spu *spu;
-
-       if (mutex_trylock(&ctx->state_mutex)) {
-               if ((spu = ctx->spu) != NULL) {
-                       int best = sched_find_first_bit(spu_prio->bitmap);
-                       if (best < MAX_PRIO) {
-                               pr_debug("%s: yielding SPU %d NODE %d\n",
-                                        __FUNCTION__, spu->number, spu->node);
-                               spu_deactivate(ctx);
-                       }
-               }
+       if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
+               mutex_lock(&ctx->state_mutex);
+               __spu_deactivate(ctx, 0, MAX_PRIO);
                mutex_unlock(&ctx->state_mutex);
        }
 }
 
+void spu_sched_tick(struct work_struct *work)
+{
+       struct spu_context *ctx =
+               container_of(work, struct spu_context, sched_work.work);
+       int preempted;
+
+       /*
+        * If this context is being stopped avoid rescheduling from the
+        * scheduler tick because we would block on the state_mutex.
+        * The caller will yield the spu later on anyway.
+        */
+       if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+               return;
+
+       mutex_lock(&ctx->state_mutex);
+       preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
+       mutex_unlock(&ctx->state_mutex);
+
+       if (preempted) {
+               /*
+                * We need to break out of the wait loop in spu_run manually
+                * to ensure this context gets put on the runqueue again
+                * ASAP.
+                */
+               wake_up(&ctx->stop_wq);
+       } else {
+               spu_start_tick(ctx);
+       }
+}
+
 int __init spu_sched_init(void)
 {
        int i;
index 0a947fd7de57c3da11e2444b64d5d020637a9323..47617e8014a5acc402f1c0222dfb1d1c6c3bf972 100644 (file)
@@ -55,7 +55,7 @@ struct spu_context {
        struct address_space *signal2;     /* 'signal2' area mappings. */
        struct address_space *mss;         /* 'mss' area mappings. */
        struct address_space *psmap;       /* 'psmap' area mappings. */
-       spinlock_t mapping_lock;
+       struct mutex mapping_lock;
        u64 object_id;             /* user space pointer for oprofile */
 
        enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
index f4f82520dc4f59aa1d0f35d387f43637185251d8..5240046d86715275156d7adf6b41434f28b1155a 100644 (file)
@@ -4,5 +4,5 @@ obj-y                           += interrupt.o iommu.o setup.o \
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PPC_UDBG_BEAT)    += udbg_beat.o
-obj-$(CONFIG_HAS_TXX9_SERIAL)  += scc_sio.o
+obj-$(CONFIG_SERIAL_TXX9)      += scc_sio.o
 obj-$(CONFIG_SPU_BASE)         += spu_priv1.o
index 95fa6a7d15ee4d11aab9e8543d8ac59d11f4c1f7..f33b21b9f5d4338d9ad9c01ba610a90250b7e132 100644 (file)
@@ -31,8 +31,6 @@
 #define IOBMAP_PAGE_SIZE       (1 << IOBMAP_PAGE_SHIFT)
 #define IOBMAP_PAGE_MASK       (IOBMAP_PAGE_SIZE - 1)
 
-#define IOBMAP_PAGE_FACTOR     (PAGE_SHIFT - IOBMAP_PAGE_SHIFT)
-
 #define IOB_BASE               0xe0000000
 #define IOB_SIZE               0x3000
 /* Configuration registers */
@@ -97,9 +95,6 @@ static void iobmap_build(struct iommu_table *tbl, long index,
 
        bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
 
-       npages <<= IOBMAP_PAGE_FACTOR;
-       index <<= IOBMAP_PAGE_FACTOR;
-
        ip = ((u32 *)tbl->it_base) + index;
 
        while (npages--) {
@@ -125,9 +120,6 @@ static void iobmap_free(struct iommu_table *tbl, long index,
 
        bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
 
-       npages <<= IOBMAP_PAGE_FACTOR;
-       index <<= IOBMAP_PAGE_FACTOR;
-
        ip = ((u32 *)tbl->it_base) + index;
 
        while (npages--) {
index 85053b2816a9dd9a40a394ca5cc7299118f13953..7a97c7440b30267f84e45b2773e85bd8f545bdd0 100644 (file)
@@ -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);
 
index 911ce1cdbd7f86865bb903ac054b359f0f6be82b..e143017c8975a0662ca64c2116106e8f97389533 100644 (file)
@@ -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);
 
index cc1cb04fa61832975ebfde104dc24e1066b2b6ca..4d335077a3ffc8c590594f6065ece5573be91d31 100644 (file)
@@ -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>
index 70f12907647f13a32e73b3476c967dcb3cd0d237..d70e5c8461b56e4b60c72c43ae9204c4b0637a8e 100644 (file)
@@ -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;
index 659cc081e5e701f5d155bf72e9cd297f93a42524..b0b59d4a33ca8ada675d624481d76b1708c9a4fc 100644 (file)
@@ -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
index fcb2c41bc34e766c9a6650abdde04e6904846230..a33429463e96cd0c758b9f05f631a5d610025d6e 100644 (file)
@@ -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;
index be03d74e99cbc4412c713ba96141b66a0443a21d..0c7b7e33abdcfd6e2ddf242623683d3ee89d7b6c 100644 (file)
@@ -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
index fb51660847c8380e92b315099c659b432f86f191..3334f99b5835f0a113514fa3e25dcf886690dbd5 100644 (file)
@@ -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;
index bd00f89eed1ed3c4dcaa7a5cb39cd6ef1a132505..89a1b469b93df149b21c1c65c5d1723d36e97e09 100644 (file)
@@ -396,6 +396,15 @@ config SCHED_SMT
          when dealing with UltraSPARC cpus at a cost of slightly increased
          overhead in some places. If unsure say N here.
 
+config SCHED_MC
+       bool "Multi-core scheduler support"
+       depends on SMP
+       default y
+       help
+         Multi-core scheduler support improves the CPU scheduler's decision
+         making when dealing with multi-core CPU chips at a cost of slightly
+         increased overhead in some places. If unsure say N here.
+
 source "kernel/Kconfig.preempt"
 
 config CMDLINE_BOOL
index d8d19093d12fd0a650f1196f2d44f490895fccc3..f964bf28d21a2568fed3a436af906c3e78d238ea 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $
+#
 # Makefile for the linux kernel.
 #
 
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror
 extra-y                := head.o init_task.o vmlinux.lds
 
 obj-y          := process.o setup.o cpu.o idprom.o \
-                  traps.o auxio.o una_asm.o \
+                  traps.o auxio.o una_asm.o sysfs.o \
                   irq.o ptrace.o time.o sys_sparc.o signal.o \
                   unaligned.o central.o pci.o starfire.o semaphore.o \
                   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
index ed712e0b337238199b52aadc646b6123a585aef6..7d1a11822a1e2c5407300ac346792397af9d21cf 100644 (file)
@@ -2514,9 +2514,9 @@ sun4v_ncs_request:
         nop
        .size   sun4v_ncs_request, .-sun4v_ncs_request
 
-       .globl  sun4v_scv_send
-       .type   sun4v_scv_send,#function
-sun4v_scv_send:
+       .globl  sun4v_svc_send
+       .type   sun4v_svc_send,#function
+sun4v_svc_send:
        save    %sp, -192, %sp
        mov     %i0, %o0
        mov     %i1, %o1
@@ -2526,11 +2526,11 @@ sun4v_scv_send:
        stx     %o1, [%i3]
        ret
        restore
-       .size   sun4v_scv_send, .-sun4v_scv_send
+       .size   sun4v_svc_send, .-sun4v_svc_send
 
-       .globl  sun4v_scv_recv
-       .type   sun4v_scv_recv,#function
-sun4v_scv_recv:
+       .globl  sun4v_svc_recv
+       .type   sun4v_svc_recv,#function
+sun4v_svc_recv:
        save    %sp, -192, %sp
        mov     %i0, %o0
        mov     %i1, %o1
@@ -2540,33 +2540,55 @@ sun4v_scv_recv:
        stx     %o1, [%i3]
        ret
        restore
-       .size   sun4v_scv_recv, .-sun4v_scv_recv
+       .size   sun4v_svc_recv, .-sun4v_svc_recv
 
-       .globl  sun4v_scv_getstatus
-       .type   sun4v_scv_getstatus,#function
-sun4v_scv_getstatus:
+       .globl  sun4v_svc_getstatus
+       .type   sun4v_svc_getstatus,#function
+sun4v_svc_getstatus:
        mov     HV_FAST_SVC_GETSTATUS, %o5
        mov     %o1, %o4
        ta      HV_FAST_TRAP
        stx     %o1, [%o4]
        retl
         nop
-       .size   sun4v_scv_getstatus, .-sun4v_scv_getstatus
+       .size   sun4v_svc_getstatus, .-sun4v_svc_getstatus
 
-       .globl  sun4v_scv_setstatus
-       .type   sun4v_scv_setstatus,#function
-sun4v_scv_setstatus:
+       .globl  sun4v_svc_setstatus
+       .type   sun4v_svc_setstatus,#function
+sun4v_svc_setstatus:
        mov     HV_FAST_SVC_SETSTATUS, %o5
        ta      HV_FAST_TRAP
        retl
         nop
-       .size   sun4v_scv_setstatus, .-sun4v_scv_setstatus
+       .size   sun4v_svc_setstatus, .-sun4v_svc_setstatus
 
-       .globl  sun4v_scv_clrstatus
-       .type   sun4v_scv_clrstatus,#function
-sun4v_scv_clrstatus:
+       .globl  sun4v_svc_clrstatus
+       .type   sun4v_svc_clrstatus,#function
+sun4v_svc_clrstatus:
        mov     HV_FAST_SVC_CLRSTATUS, %o5
        ta      HV_FAST_TRAP
        retl
         nop
-       .size   sun4v_scv_clrstatus, .-sun4v_scv_clrstatus
+       .size   sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
+
+       .globl  sun4v_mmustat_conf
+       .type   sun4v_mmustat_conf,#function
+sun4v_mmustat_conf:
+       mov     %o1, %o4
+       mov     HV_FAST_MMUSTAT_CONF, %o5
+       ta      HV_FAST_TRAP
+       stx     %o1, [%o4]
+       retl
+        nop
+       .size   sun4v_mmustat_conf, .-sun4v_mmustat_conf
+
+       .globl  sun4v_mmustat_info
+       .type   sun4v_mmustat_info,#function
+sun4v_mmustat_info:
+       mov     %o0, %o4
+       mov     HV_FAST_MMUSTAT_INFO, %o5
+       ta      HV_FAST_TRAP
+       stx     %o1, [%o4]
+       retl
+        nop
+       .size   sun4v_mmustat_info, .-sun4v_mmustat_info
index 9246c2cf95747685fba8106d7cb83dcd99d6a60b..f0e16045fb1693f0f8ba9e8e507413833aa05b9f 100644 (file)
@@ -473,6 +473,53 @@ static void __init set_core_ids(void)
        }
 }
 
+static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id)
+{
+       int i;
+
+       for (i = 0; i < mp->num_arcs; i++) {
+               struct mdesc_node *t = mp->arcs[i].arc;
+               const u64 *id;
+
+               if (strcmp(mp->arcs[i].name, "back"))
+                       continue;
+
+               if (strcmp(t->name, "cpu"))
+                       continue;
+
+               id = md_get_property(t, "id", NULL);
+               if (*id < NR_CPUS)
+                       cpu_data(*id).proc_id = proc_id;
+       }
+}
+
+static void __init __set_proc_ids(const char *exec_unit_name)
+{
+       struct mdesc_node *mp;
+       int idx;
+
+       idx = 0;
+       md_for_each_node_by_name(mp, exec_unit_name) {
+               const char *type;
+               int len;
+
+               type = md_get_property(mp, "type", &len);
+               if (!find_in_proplist(type, "int", len) &&
+                   !find_in_proplist(type, "integer", len))
+                       continue;
+
+               mark_proc_ids(mp, idx);
+
+               idx++;
+       }
+}
+
+static void __init set_proc_ids(void)
+{
+       __set_proc_ids("exec_unit");
+       __set_proc_ids("exec-unit");
+}
+
 static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
 {
        u64 val;
@@ -574,9 +621,15 @@ static void __init mdesc_fill_in_cpu_data(void)
 #endif
 
                c->core_id = 0;
+               c->proc_id = -1;
        }
 
+#ifdef CONFIG_SMP
+       sparc64_multi_core = 1;
+#endif
+
        set_core_ids();
+       set_proc_ids();
 
        smp_fill_in_sib_core_maps();
 }
index 16cc46a718724cc5cd93a99beb3b5c43fb08fb23..6676b93219dcd51cee5454cb2577854074c4ec80 100644 (file)
@@ -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;
index 38a32bc95d22bb0423a6bd28b2ff75f18e69fef1..81f4a5ea05f7ab948e307daa1853f53d1b554fbd 100644 (file)
@@ -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)
index 323d6c278518fd36d87ac443b22be131c8047ab0..22e1be5c7489aaf1420da8fb1c4becf437c2eb49 100644 (file)
@@ -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);
 }
index dad4b3ba705f5aaab2e354692db7eb229a490a4c..61036b346664b994cf329e90eef89305f7a28be3 100644 (file)
@@ -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;
@@ -1781,6 +1781,10 @@ static void __init of_fill_in_cpu_data(void)
                        }
 
                        cpu_data(cpuid).core_id = portid + 1;
+                       cpu_data(cpuid).proc_id = portid;
+#ifdef CONFIG_SMP
+                       sparc64_multi_core = 1;
+#endif
                } else {
                        cpu_data(cpuid).dcache_size =
                                of_getintprop_default(dp, "dcache-size", 16 * 1024);
@@ -1799,6 +1803,7 @@ static void __init of_fill_in_cpu_data(void)
                                of_getintprop_default(dp, "ecache-line-size", 64);
 
                        cpu_data(cpuid).core_id = 0;
+                       cpu_data(cpuid).proc_id = -1;
                }
 
 #ifdef CONFIG_SMP
index 91f6e2a74ad5fdc263c94fec5dd41dfb06ea254c..a1fd9bcc0b872a5485bb6514b9a835cad583ee49 100644 (file)
@@ -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;
index de9b4c13f1c71deee9d62cd69f41eb04d5e76a65..7490cc670a530e495a81e1d5d7d762b8228f7f22 100644 (file)
@@ -513,22 +513,3 @@ void sun_do_break(void)
 
 int serial_console = -1;
 int stop_a_enabled = 1;
-
-static int __init topology_init(void)
-{
-       int i, err;
-
-       err = -ENOMEM;
-
-       for_each_possible_cpu(i) {
-               struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
-               if (p) {
-                       register_cpu(p, i);
-                       err = 0;
-               }
-       }
-
-       return err;
-}
-
-subsys_initcall(topology_init);
index c550bba3490a528fb240f3dc4f5b565a0f59fdc4..4dcd7d0b60f2d8abb8e8ad7630df207cfc39ad21 100644 (file)
@@ -44,6 +44,8 @@
 
 extern void calibrate_delay(void);
 
+int sparc64_multi_core __read_mostly;
+
 /* Please don't make this stuff initdata!!!  --DaveM */
 unsigned char boot_cpu_id;
 
@@ -51,6 +53,8 @@ cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
 cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
        { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
+       { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 static cpumask_t smp_commenced_mask;
 static cpumask_t cpu_callout_map;
 
@@ -1217,13 +1221,28 @@ void __devinit smp_fill_in_sib_core_maps(void)
                unsigned int j;
 
                if (cpu_data(i).core_id == 0) {
-                       cpu_set(i, cpu_sibling_map[i]);
+                       cpu_set(i, cpu_core_map[i]);
                        continue;
                }
 
                for_each_possible_cpu(j) {
                        if (cpu_data(i).core_id ==
                            cpu_data(j).core_id)
+                               cpu_set(j, cpu_core_map[i]);
+               }
+       }
+
+       for_each_possible_cpu(i) {
+               unsigned int j;
+
+               if (cpu_data(i).proc_id == -1) {
+                       cpu_set(i, cpu_sibling_map[i]);
+                       continue;
+               }
+
+               for_each_possible_cpu(j) {
+                       if (cpu_data(i).proc_id ==
+                           cpu_data(j).proc_id)
                                cpu_set(j, cpu_sibling_map[i]);
                }
        }
index d00f51a5683fd46234954ffa3648bb8a6822b851..6fa76161289910680c8bb3f350429f18248553a9 100644 (file)
@@ -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/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
new file mode 100644 (file)
index 0000000..cdb1477
--- /dev/null
@@ -0,0 +1,297 @@
+/* sysfs.c: Toplogy sysfs support code for sparc64.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/spitfire.h>
+
+static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
+
+#define SHOW_MMUSTAT_ULONG(NAME) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+       struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
+       return sprintf(buf, "%lu\n", p->NAME); \
+} \
+static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL)
+
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
+
+static struct attribute *mmu_stat_attrs[] = {
+       &attr_immu_tsb_hits_ctx0_8k_tte.attr,
+       &attr_immu_tsb_ticks_ctx0_8k_tte.attr,
+       &attr_immu_tsb_hits_ctx0_64k_tte.attr,
+       &attr_immu_tsb_ticks_ctx0_64k_tte.attr,
+       &attr_immu_tsb_hits_ctx0_4mb_tte.attr,
+       &attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
+       &attr_immu_tsb_hits_ctx0_256mb_tte.attr,
+       &attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
+       &attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
+       &attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
+       &attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
+       &attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
+       &attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
+       &attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
+       &attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
+       &attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
+       &attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
+       &attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
+       &attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
+       &attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
+       &attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
+       &attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
+       &attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
+       &attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
+       &attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
+       &attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
+       &attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
+       &attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
+       &attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
+       &attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
+       &attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
+       &attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
+       NULL,
+};
+
+static struct attribute_group mmu_stat_group = {
+       .attrs = mmu_stat_attrs,
+       .name = "mmu_stats",
+};
+
+/* XXX convert to rusty's on_one_cpu */
+static unsigned long run_on_cpu(unsigned long cpu,
+                               unsigned long (*func)(unsigned long),
+                               unsigned long arg)
+{
+       cpumask_t old_affinity = current->cpus_allowed;
+       unsigned long ret;
+
+       /* should return -EINVAL to userspace */
+       if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
+               return 0;
+
+       ret = func(arg);
+
+       set_cpus_allowed(current, old_affinity);
+
+       return ret;
+}
+
+static unsigned long read_mmustat_enable(unsigned long junk)
+{
+       unsigned long ra = 0;
+
+       sun4v_mmustat_info(&ra);
+
+       return ra != 0;
+}
+
+static unsigned long write_mmustat_enable(unsigned long val)
+{
+       unsigned long ra, orig_ra;
+
+       if (val)
+               ra = __pa(&per_cpu(mmu_stats, smp_processor_id()));
+       else
+               ra = 0UL;
+
+       return sun4v_mmustat_conf(ra, &orig_ra);
+}
+
+static ssize_t show_mmustat_enable(struct sys_device *s, char *buf)
+{
+       unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
+       return sprintf(buf, "%lx\n", val);
+}
+
+static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count)
+{
+       unsigned long val, err;
+       int ret = sscanf(buf, "%ld", &val);
+
+       if (ret != 1)
+               return -EINVAL;
+
+       err = run_on_cpu(s->id, write_mmustat_enable, val);
+       if (err)
+               return -EIO;
+
+       return count;
+}
+
+static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
+
+static int mmu_stats_supported;
+
+static int register_mmu_stats(struct sys_device *s)
+{
+       if (!mmu_stats_supported)
+               return 0;
+       sysdev_create_file(s, &attr_mmustat_enable);
+       return sysfs_create_group(&s->kobj, &mmu_stat_group);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_mmu_stats(struct sys_device *s)
+{
+       if (!mmu_stats_supported)
+               return;
+       sysfs_remove_group(&s->kobj, &mmu_stat_group);
+       sysdev_remove_file(s, &attr_mmustat_enable);
+}
+#endif
+
+#define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+       cpuinfo_sparc *c = &cpu_data(dev->id); \
+       return sprintf(buf, "%lu\n", c->MEMBER); \
+}
+
+#define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+       cpuinfo_sparc *c = &cpu_data(dev->id); \
+       return sprintf(buf, "%u\n", c->MEMBER); \
+}
+
+SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
+SHOW_CPUDATA_ULONG_NAME(udelay_val, udelay_val);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
+
+static struct sysdev_attribute cpu_core_attrs[] = {
+       _SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
+       _SYSDEV_ATTR(udelay_val,          0444, show_udelay_val, NULL),
+       _SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
+       _SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
+       _SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
+       _SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
+       _SYSDEV_ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
+       _SYSDEV_ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
+};
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static void register_cpu_online(unsigned int cpu)
+{
+       struct cpu *c = &per_cpu(cpu_devices, cpu);
+       struct sys_device *s = &c->sysdev;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+               sysdev_create_file(s, &cpu_core_attrs[i]);
+
+       register_mmu_stats(s);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_cpu_online(unsigned int cpu)
+{
+       struct cpu *c = &per_cpu(cpu_devices, cpu);
+       struct sys_device *s = &c->sysdev;
+       int i;
+
+       unregister_mmu_stats(s);
+       for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+               sysdev_remove_file(s, &cpu_core_attrs[i]);
+}
+#endif
+
+static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
+                                     unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned int)(long)hcpu;
+
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               register_cpu_online(cpu);
+               break;
+#ifdef CONFIG_HOTPLUG_CPU
+       case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
+               unregister_cpu_online(cpu);
+               break;
+#endif
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
+       .notifier_call  = sysfs_cpu_notify,
+};
+
+static void __init check_mmu_stats(void)
+{
+       unsigned long dummy1, err;
+
+       if (tlb_type != hypervisor)
+               return;
+
+       err = sun4v_mmustat_info(&dummy1);
+       if (!err)
+               mmu_stats_supported = 1;
+}
+
+static int __init topology_init(void)
+{
+       int cpu;
+
+       check_mmu_stats();
+
+       register_cpu_notifier(&sysfs_cpu_nb);
+
+       for_each_possible_cpu(cpu) {
+               struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+               register_cpu(c, cpu);
+               if (cpu_online(cpu))
+                       register_cpu_online(cpu);
+       }
+
+       return 0;
+}
+
+subsys_initcall(topology_init);
index c504312219b42b8f9797c50fe1569e5f05163a84..e6ff30266542a79b8909a5ef5f4e7991e58e16ca 100644 (file)
@@ -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
index ced99106f7982b84a13eed11a71890f04ba4ae2e..4bd40bb43ec27f3935306fb784e84bdf160172a4 100644 (file)
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/kernel.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
index 911539293871d271ed306c36fd1b113f6acc9203..4739dd527b43ab8ff5cf59ab007cfbbd033b90d8 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/console.h>
 
index 70509ddaac035cd60537e286883614323410be6d..2e09f162c42f01b6ac39f3689eae208f5d4b75b1 100644 (file)
@@ -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"
index 8b7f2cdedf945148ffd96306ac04024dc9a0a7ee..c716b5a6db13d9552a59e7f7ec5688229ca9bf0e 100644 (file)
@@ -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:
- */
index cb29fb96948dd2653886e2fe444fb35ea55dae48..aac1c0be54c6b8f99c032f61f6b29f904d91977d 100644 (file)
@@ -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 */;
index bfb62a13d7eee005f2b364b159b21096e811ae53..635e58d443d7c555f118cca839656bfad2adb15e 100644 (file)
@@ -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;
 
index 1ad5111aec381d7042648c0a871f2707181f3400..efb6e845114ec727430860981b03b22495f9d299 100644 (file)
@@ -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))
index 698079b3a3368f86735a584daa26384456d11dc1..d0323cd6a2ead094411a48109e2512d76c17e9e1 100644 (file)
@@ -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]));
index 9e271ba009bfd88645008e0adca5d7b3e87a4e0d..8dc7a2c26ff9f87f9854118d0c1006f544c8202f 100644 (file)
@@ -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
index ea89910efa44f523e928ffc6a1b33938e5e97d45..67e69139520bd91cb834dbfc68d591039712d3b7 100644 (file)
@@ -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
 
index 45571ccb72d63e16b169b3aa2301676d0917fc52..77deae5290f06e43f64c379ba1bc33646b325afb 100644 (file)
@@ -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) {
index 1ecf6716c3274a1ce2575236b036e864c57e6127..2e8d398cf19627aef6db11a8e6d723ae7b106fa7 100644 (file)
@@ -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};
index 58107672a619eeebf783b8249658bfc6396274ed..033aae0336d260d323f07c3abaad1ea521690d7c 100644 (file)
-// 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;
 }
+
index 4b7b4ff7997349abfb994becb0fade83492ad28b..b0582c3c5f8da9dad2f43eb5b9d81ca9a14cbfb0 100644 (file)
@@ -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) }
index cd7e6a0206024a835daf7aff2c545ef06f808be6..60dbdb43fb4c92d27e12f15cba95d8195601721f 100644 (file)
 /*
  * 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);
 
 /*
index a834057bda6b45040a6182705e9610fb1448377e..b2655d94558d8db837e248d09856c3246cfa78e5 100644 (file)
 /*
  * 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
index 5e9c1e709b2eaf33d32d883a4681453398027313..ad3f616322caaa31bd54c9a56f87b892d5e0726d 100644 (file)
 /*
  * 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
 
index e1ec2d1e8189e64c998ba8dba7d9b3a9d30d5cc1..8415c76f11c2a75ea69f080ec334a46a22ba715e 100644 (file)
@@ -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.
         */
index 4bfe333be22943558a8448679b71f4bcd2b273e8..f09962fa98c09a5594358d22c23b0b7d993209f0 100644 (file)
@@ -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)
index 7d893a60f99420ffc9d8fe7a2b6b999dc99889b2..b4a8d6030e480859b8c594ad68cd2e40686ae4c7 100644 (file)
@@ -8,7 +8,6 @@ menuconfig ATA
        depends on BLOCK
        depends on !(M32R || M68K) || BROKEN
        depends on !SUN4 || BROKEN
-       depends on !(SPARC64 && !PCI)
        select SCSI
        ---help---
          If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
index 2b924a69b365cfda37d7b6acd705c2b567672e84..6dc0b011a6b7c5a10febc2a0242c5dc431939a23 100644 (file)
@@ -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);
 }
 
index 20c4ea6eb50d0a8836e2f89af145fc88634c02ba..8c506dbe39138bc11b8901944a81461c5a424e79 100644 (file)
@@ -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];
index b78fc1e68264872a196c6a7b1e454b080a9831bd..dd40d78a023dd1f2fde9712ac7700d5ade4893cf 100644 (file)
@@ -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,
index 92428e55b0c210a8c00cf8e656a934fa9e21f2d3..b0088b0efecdd1e5395e4104d23d0fe34dbb9a0d 100644 (file)
@@ -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.
index 97ab5bd1c4d62ebb72ef9babc07f2c35571c484b..89a5f4a5491391e2270069090f43c6e82b6ef601 100644 (file)
@@ -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");
 
index 5526eadb65926d4318b790a0ede84d9f272a7059..0ed5470d25339674a5c449feab66f5505db5f3c2 100644 (file)
@@ -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");
 }
index f574962f4288d36233491eb0d98f8968e2d0da2b..4310cc84dfedb4c3b59dc20751e91ed076ace202 100644 (file)
@@ -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
index e45113a7a472f7f1035d3fd92b2909b237bd298b..45bf2a262a858c144c74388f271bfb13cb4e9b9a 100644 (file)
@@ -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);
index 58bc272bd407273d18416c00afb35a9e51c086d2..0aecea67f3e69cb6339dfe5d6f29679eb36285e7 100644 (file)
@@ -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;
index 06eaf766d9d2fc2ff9026598bb15ccbc847520b7..f9e82c9ca42191142dcab70ed8493072bc049d39 100644 (file)
@@ -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;
        }
 
index 46fc21a3f8ff232038298c3c8dc8e8720f954f3c..d36a4c09e25db2b5d8ee558ab2bf31664455e508 100644 (file)
@@ -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;
 
index da7c3b0c533c5c55d937ee9dc2878d6be434cec7..ce3ed67a878e39af77ab5a95453406091b7c6e15 100644 (file)
@@ -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;
 
index bd6288d6350f87d505df811c0a9ee7e372799cec..49a5de253b17ff1af7f18fcfc7c92cacc0e7a2cb 100644 (file)
@@ -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)
 
index 61696637a21edcc0b646e1c8894c3b89f632dadd..763810c7f33aa1e3bb682e1afdc780ac18ca8ce1 100644 (file)
@@ -285,6 +285,12 @@ enum scb_status {
        rus_mask         = 0x3C,
 };
 
+enum ru_state  {
+       RU_SUSPENDED = 0,
+       RU_RUNNING       = 1,
+       RU_UNINITIALIZED = -1,
+};
+
 enum scb_stat_ack {
        stat_ack_not_ours    = 0x00,
        stat_ack_sw_gen      = 0x04,
@@ -526,6 +532,7 @@ struct nic {
        struct rx *rx_to_use;
        struct rx *rx_to_clean;
        struct rfd blank_rfd;
+       enum ru_state ru_running;
 
        spinlock_t cb_lock                      ____cacheline_aligned;
        spinlock_t cmd_lock;
@@ -947,7 +954,7 @@ static void e100_get_defaults(struct nic *nic)
                ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
 
        /* Template for a freshly allocated RFD */
-       nic->blank_rfd.command = cpu_to_le16(cb_el & cb_s);
+       nic->blank_rfd.command = cpu_to_le16(cb_el);
        nic->blank_rfd.rbd = 0xFFFFFFFF;
        nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
 
@@ -1742,11 +1749,19 @@ static int e100_alloc_cbs(struct nic *nic)
        return 0;
 }
 
-static inline void e100_start_receiver(struct nic *nic)
+static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
 {
-       /* Start if RFA is non-NULL */
-       if(nic->rx_to_clean->skb)
-               e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
+       if(!nic->rxs) return;
+       if(RU_SUSPENDED != nic->ru_running) return;
+
+       /* handle init time starts */
+       if(!rx) rx = nic->rxs;
+
+       /* (Re)start RU if suspended or idle and RFA is non-NULL */
+       if(rx->skb) {
+               e100_exec_cmd(nic, ruc_start, rx->dma_addr);
+               nic->ru_running = RU_RUNNING;
+       }
 }
 
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
@@ -1775,7 +1790,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
                put_unaligned(cpu_to_le32(rx->dma_addr),
                        (u32 *)&prev_rfd->link);
                wmb();
-               prev_rfd->command &= ~cpu_to_le16(cb_el & cb_s);
+               prev_rfd->command &= ~cpu_to_le16(cb_el);
                pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
                        sizeof(struct rfd), PCI_DMA_TODEVICE);
        }
@@ -1813,6 +1828,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
        pci_unmap_single(nic->pdev, rx->dma_addr,
                RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
 
+       /* this allows for a fast restart without re-enabling interrupts */
+       if(le16_to_cpu(rfd->command) & cb_el)
+               nic->ru_running = RU_SUSPENDED;
+
        /* Pull off the RFD and put the actual data (minus eth hdr) */
        skb_reserve(skb, sizeof(struct rfd));
        skb_put(skb, actual_size);
@@ -1843,18 +1862,45 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
        unsigned int work_to_do)
 {
        struct rx *rx;
+       int restart_required = 0;
+       struct rx *rx_to_start = NULL;
+
+       /* are we already rnr? then pay attention!!! this ensures that
+        * the state machine progression never allows a start with a
+        * partially cleaned list, avoiding a race between hardware
+        * and rx_to_clean when in NAPI mode */
+       if(RU_SUSPENDED == nic->ru_running)
+               restart_required = 1;
 
        /* Indicate newly arrived packets */
        for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
-               if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+               int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
+               if(-EAGAIN == err) {
+                       /* hit quota so have more work to do, restart once
+                        * cleanup is complete */
+                       restart_required = 0;
+                       break;
+               } else if(-ENODATA == err)
                        break; /* No more to clean */
        }
 
+       /* save our starting point as the place we'll restart the receiver */
+       if(restart_required)
+               rx_to_start = nic->rx_to_clean;
+
        /* Alloc new skbs to refill list */
        for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
                if(unlikely(e100_rx_alloc_skb(nic, rx)))
                        break; /* Better luck next time (see watchdog) */
        }
+
+       if(restart_required) {
+               // ack the rnr?
+               writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+               e100_start_receiver(nic, rx_to_start);
+               if(work_done)
+                       (*work_done)++;
+       }
 }
 
 static void e100_rx_clean_list(struct nic *nic)
@@ -1862,6 +1908,8 @@ static void e100_rx_clean_list(struct nic *nic)
        struct rx *rx;
        unsigned int i, count = nic->params.rfds.count;
 
+       nic->ru_running = RU_UNINITIALIZED;
+
        if(nic->rxs) {
                for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
                        if(rx->skb) {
@@ -1883,6 +1931,7 @@ static int e100_rx_alloc_list(struct nic *nic)
        unsigned int i, count = nic->params.rfds.count;
 
        nic->rx_to_use = nic->rx_to_clean = NULL;
+       nic->ru_running = RU_UNINITIALIZED;
 
        if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
                return -ENOMEM;
@@ -1897,6 +1946,7 @@ static int e100_rx_alloc_list(struct nic *nic)
        }
 
        nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+       nic->ru_running = RU_SUSPENDED;
 
        return 0;
 }
@@ -1916,6 +1966,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
        /* Ack interrupt(s) */
        iowrite8(stat_ack, &nic->csr->scb.stat_ack);
 
+       /* We hit Receive No Resource (RNR); restart RU after cleaning */
+       if(stat_ack & stat_ack_rnr)
+               nic->ru_running = RU_SUSPENDED;
+
        if(likely(netif_rx_schedule_prep(netdev))) {
                e100_disable_irq(nic);
                __netif_rx_schedule(netdev);
@@ -2007,7 +2061,7 @@ static int e100_up(struct nic *nic)
        if((err = e100_hw_init(nic)))
                goto err_clean_cbs;
        e100_set_multicast_list(nic->netdev);
-       e100_start_receiver(nic);
+       e100_start_receiver(nic, NULL);
        mod_timer(&nic->watchdog, jiffies);
        if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
                nic->netdev->name, nic->netdev)))
@@ -2088,7 +2142,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
                mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
                        BMCR_LOOPBACK);
 
-       e100_start_receiver(nic);
+       e100_start_receiver(nic, NULL);
 
        if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
                err = -ENOMEM;
index e85a933a47625e68bee0704b17d2a5675ac7d492..c0f81b5a30fb4737b0b89839d9d3cb93ae62b591 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0061"
+#define DRV_VERSION    "EHEA_0064"
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
        | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
index 152bb2016a2c94998e68c0094ab64d9425582dc7..9e13433a268a7a40c360a17ed7904281a89e245b 100644 (file)
@@ -451,7 +451,8 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
                                processed_rq3++;
                        }
 
-                       if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+                       if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+                           && port->vgrp)
                                vlan_hwaccel_receive_skb(skb, port->vgrp,
                                                         cqe->vlan_tag);
                        else
@@ -1910,10 +1911,7 @@ static void ehea_vlan_rx_register(struct net_device *dev,
                goto out;
        }
 
-       if (grp)
-               memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
-       else
-               memset(cb1->vlan_filter, 0xFF, sizeof(cb1->vlan_filter));
+       memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
 
        hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
                                       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1947,7 +1945,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
        }
 
        index = (vid / 64);
-       cb1->vlan_filter[index] |= ((u64)(1 << (vid & 0x3F)));
+       cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
 
        hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
                                       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1982,7 +1980,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        }
 
        index = (vid / 64);
-       cb1->vlan_filter[index] &= ~((u64)(1 << (vid & 0x3F)));
+       cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
 
        hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
                                       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
index 3bec0f733f01e6a882bc60be9ee51cce807e965d..6ec3d500f3341ac491519c60d27d2f2c1b936c45 100644 (file)
@@ -915,17 +915,36 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct ibmveth_adapter *adapter = dev->priv;
        int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
-       int i;
+       int reinit = 0;
+       int i, rc;
 
        if (new_mtu < IBMVETH_MAX_MTU)
                return -EINVAL;
 
+       for (i = 0; i < IbmVethNumBufferPools; i++)
+               if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
+                       break;
+
+       if (i == IbmVethNumBufferPools)
+               return -EINVAL;
+
        /* Look for an active buffer pool that can hold the new MTU */
        for(i = 0; i<IbmVethNumBufferPools; i++) {
-               if (!adapter->rx_buff_pool[i].active)
-                       continue;
+               if (!adapter->rx_buff_pool[i].active) {
+                       adapter->rx_buff_pool[i].active = 1;
+                       reinit = 1;
+               }
+
                if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
-                       dev->mtu = new_mtu;
+                       if (reinit && netif_running(adapter->netdev)) {
+                               adapter->pool_config = 1;
+                               ibmveth_close(adapter->netdev);
+                               adapter->pool_config = 0;
+                               dev->mtu = new_mtu;
+                               if ((rc = ibmveth_open(adapter->netdev)))
+                                       return rc;
+                       } else
+                               dev->mtu = new_mtu;
                        return 0;
                }
        }
@@ -1243,16 +1262,19 @@ const char * buf, size_t count)
 
        if (attr == &veth_active_attr) {
                if (value && !pool->active) {
-                       if(ibmveth_alloc_buffer_pool(pool)) {
-                                ibmveth_error_printk("unable to alloc pool\n");
-                                return -ENOMEM;
-                        }
-                       pool->active = 1;
-                       adapter->pool_config = 1;
-                       ibmveth_close(netdev);
-                       adapter->pool_config = 0;
-                       if ((rc = ibmveth_open(netdev)))
-                               return rc;
+                       if (netif_running(netdev)) {
+                               if(ibmveth_alloc_buffer_pool(pool)) {
+                                       ibmveth_error_printk("unable to alloc pool\n");
+                                       return -ENOMEM;
+                               }
+                               pool->active = 1;
+                               adapter->pool_config = 1;
+                               ibmveth_close(netdev);
+                               adapter->pool_config = 0;
+                               if ((rc = ibmveth_open(netdev)))
+                                       return rc;
+                       } else
+                               pool->active = 1;
                } else if (!value && pool->active) {
                        int mtu = netdev->mtu + IBMVETH_BUFF_OH;
                        int i;
@@ -1281,23 +1303,29 @@ const char * buf, size_t count)
                if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
                        return -EINVAL;
                else {
-                       adapter->pool_config = 1;
-                       ibmveth_close(netdev);
-                       adapter->pool_config = 0;
-                       pool->size = value;
-                       if ((rc = ibmveth_open(netdev)))
-                               return rc;
+                       if (netif_running(netdev)) {
+                               adapter->pool_config = 1;
+                               ibmveth_close(netdev);
+                               adapter->pool_config = 0;
+                               pool->size = value;
+                               if ((rc = ibmveth_open(netdev)))
+                                       return rc;
+                       } else
+                               pool->size = value;
                }
        } else if (attr == &veth_size_attr) {
                if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
                        return -EINVAL;
                else {
-                       adapter->pool_config = 1;
-                       ibmveth_close(netdev);
-                       adapter->pool_config = 0;
-                       pool->buff_size = value;
-                       if ((rc = ibmveth_open(netdev)))
-                               return rc;
+                       if (netif_running(netdev)) {
+                               adapter->pool_config = 1;
+                               ibmveth_close(netdev);
+                               adapter->pool_config = 0;
+                               pool->buff_size = value;
+                               if ((rc = ibmveth_open(netdev)))
+                                       return rc;
+                       } else
+                               pool->buff_size = value;
                }
        }
 
index b53b7ad999bcb58290b5f790b3afcb15b7eddbb0..0f9904fe3a5a2b4273ffe5901846f627233fa818 100644 (file)
@@ -71,7 +71,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.3.0-1.233"
+#define MYRI10GE_VERSION_STR "1.3.1-1.248"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -279,6 +279,8 @@ static int myri10ge_fill_thresh = 256;
 module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
 
+static int myri10ge_reset_recover = 1;
+
 static int myri10ge_wcfifo = 0;
 module_param(myri10ge_wcfifo, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
@@ -1154,9 +1156,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
        struct mcp_irq_data *stats = mgp->fw_stats;
 
        if (unlikely(stats->stats_updated)) {
-               if (mgp->link_state != stats->link_up) {
-                       mgp->link_state = stats->link_up;
-                       if (mgp->link_state) {
+               unsigned link_up = ntohl(stats->link_up);
+               if (mgp->link_state != link_up) {
+                       mgp->link_state = link_up;
+
+                       if (mgp->link_state == MXGEFW_LINK_UP) {
                                if (netif_msg_link(mgp))
                                        printk(KERN_INFO
                                               "myri10ge: %s: link up\n",
@@ -1166,8 +1170,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
                        } else {
                                if (netif_msg_link(mgp))
                                        printk(KERN_INFO
-                                              "myri10ge: %s: link down\n",
-                                              mgp->dev->name);
+                                              "myri10ge: %s: link %s\n",
+                                              mgp->dev->name,
+                                              (link_up == MXGEFW_LINK_MYRINET ?
+                                               "mismatch (Myrinet detected)" :
+                                               "down"));
                                netif_carrier_off(mgp->dev);
                                mgp->link_changes++;
                        }
@@ -2730,8 +2737,14 @@ static void myri10ge_watchdog(struct work_struct *work)
                 * For now, just report it */
                reboot = myri10ge_read_reboot(mgp);
                printk(KERN_ERR
-                      "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
-                      mgp->dev->name, reboot);
+                      "myri10ge: %s: NIC rebooted (0x%x),%s resetting\n",
+                      mgp->dev->name, reboot,
+                      myri10ge_reset_recover ? " " : " not");
+               if (myri10ge_reset_recover == 0)
+                       return;
+
+               myri10ge_reset_recover--;
+
                /*
                 * A rebooted nic will come back with config space as
                 * it was after power was applied to PCIe bus.
index ad6688eab265f741c5e3b8b385b40c35fdc7fd17..91f25e0a638ea64c21fd42910e4c0a2880abf649 100644 (file)
 #define _NETXEN_NIC_LINUX_SUBVERSION 2
 #define NETXEN_NIC_LINUX_VERSIONID  "3.4.2"
 
-#define NUM_FLASH_SECTORS (64)
-#define FLASH_SECTOR_SIZE (64 * 1024)
-#define FLASH_TOTAL_SIZE  (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE)
+#define NETXEN_NUM_FLASH_SECTORS (64)
+#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
+#define NETXEN_FLASH_TOTAL_SIZE  (NETXEN_NUM_FLASH_SECTORS \
+                                       * NETXEN_FLASH_SECTOR_SIZE)
 
 #define PHAN_VENDOR_ID 0x4040
 
@@ -677,28 +678,28 @@ struct netxen_new_user_info {
 
 /* Flash memory map */
 typedef enum {
-       CRBINIT_START = 0,      /* Crbinit section */
-       BRDCFG_START = 0x4000,  /* board config */
-       INITCODE_START = 0x6000,        /* pegtune code */
-       BOOTLD_START = 0x10000, /* bootld */
-       IMAGE_START = 0x43000,  /* compressed image */
-       SECONDARY_START = 0x200000,     /* backup images */
-       PXE_START = 0x3E0000,   /* user defined region */
-       USER_START = 0x3E8000,  /* User defined region for new boards */
-       FIXED_START = 0x3F0000  /* backup of crbinit */
+       NETXEN_CRBINIT_START = 0,       /* Crbinit section */
+       NETXEN_BRDCFG_START = 0x4000,   /* board config */
+       NETXEN_INITCODE_START = 0x6000, /* pegtune code */
+       NETXEN_BOOTLD_START = 0x10000,  /* bootld */
+       NETXEN_IMAGE_START = 0x43000,   /* compressed image */
+       NETXEN_SECONDARY_START = 0x200000,      /* backup images */
+       NETXEN_PXE_START = 0x3E0000,    /* user defined region */
+       NETXEN_USER_START = 0x3E8000,   /* User defined region for new boards */
+       NETXEN_FIXED_START = 0x3F0000   /* backup of crbinit */
 } netxen_flash_map_t;
 
-#define USER_START_OLD PXE_START       /* for backward compatibility */
-
-#define FLASH_START            (CRBINIT_START)
-#define INIT_SECTOR            (0)
-#define PRIMARY_START          (BOOTLD_START)
-#define FLASH_CRBINIT_SIZE     (0x4000)
-#define FLASH_BRDCFG_SIZE      (sizeof(struct netxen_board_info))
-#define FLASH_USER_SIZE                (sizeof(struct netxen_user_info)/sizeof(u32))
-#define FLASH_SECONDARY_SIZE   (USER_START-SECONDARY_START)
-#define NUM_PRIMARY_SECTORS    (0x20)
-#define NUM_CONFIG_SECTORS     (1)
+#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
+
+#define NETXEN_FLASH_START             (NETXEN_CRBINIT_START)
+#define NETXEN_INIT_SECTOR             (0)
+#define NETXEN_PRIMARY_START           (NETXEN_BOOTLD_START)
+#define NETXEN_FLASH_CRBINIT_SIZE      (0x4000)
+#define NETXEN_FLASH_BRDCFG_SIZE       (sizeof(struct netxen_board_info))
+#define NETXEN_FLASH_USER_SIZE         (sizeof(struct netxen_user_info)/sizeof(u32))
+#define NETXEN_FLASH_SECONDARY_SIZE    (NETXEN_USER_START-NETXEN_SECONDARY_START)
+#define NETXEN_NUM_PRIMARY_SECTORS     (0x20)
+#define NETXEN_NUM_CONFIG_SECTORS      (1)
 #define PFX "NetXen: "
 extern char netxen_nic_driver_name[];
 
@@ -1048,6 +1049,7 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr);
 int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
 
 /* Functions from netxen_nic_isr.c */
+int netxen_nic_link_ok(struct netxen_adapter *adapter);
 void netxen_nic_isr_other(struct netxen_adapter *adapter);
 void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link);
 void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable);
index 16fabb377488977646ff83906424196c44003bd7..0175f6c353f625d732a1ac08e4e5392346578cfc 100644 (file)
@@ -94,7 +94,7 @@ static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 static int netxen_nic_get_eeprom_len(struct net_device *dev)
 {
-       return FLASH_TOTAL_SIZE;
+       return NETXEN_FLASH_TOTAL_SIZE;
 }
 
 static void
@@ -470,7 +470,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                return 0;
        }
 
-       if (offset == BOOTLD_START) {
+       if (offset == NETXEN_BOOTLD_START) {
                ret = netxen_flash_erase_primary(adapter);
                if (ret != FLASH_SUCCESS) {
                        printk(KERN_ERR "%s: Flash erase failed.\n", 
@@ -478,10 +478,10 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                        return ret;
                }
 
-               ret = netxen_rom_se(adapter, USER_START);
+               ret = netxen_rom_se(adapter, NETXEN_USER_START);
                if (ret != FLASH_SUCCESS)
                        return ret;
-               ret = netxen_rom_se(adapter, FIXED_START);
+               ret = netxen_rom_se(adapter, NETXEN_FIXED_START);
                if (ret != FLASH_SUCCESS)
                        return ret;
 
index baff17a24d633ba8a5eec76c9ad7dab9b8a73aaa..c012764d114578a2414132370a7752ae9d7e8656 100644 (file)
@@ -257,7 +257,7 @@ u64 ctx_addr_sig_regs[][3] = {
 #define ADDR_IN_RANGE(addr, low, high) \
        (((addr) <= (high)) && ((addr) >= (low)))
 
-#define NETXEN_FLASH_BASE      (BOOTLD_START)
+#define NETXEN_FLASH_BASE      (NETXEN_BOOTLD_START)
 #define NETXEN_PHANTOM_MEM_BASE        (NETXEN_FLASH_BASE)
 #define NETXEN_MAX_MTU         8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
 #define NETXEN_MIN_MTU         64
@@ -611,7 +611,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
        u32 *pmac = (u32 *) & mac[0];
 
        if (netxen_get_flash_block(adapter,
-                                  USER_START +
+                                  NETXEN_USER_START +
                                   offsetof(struct netxen_new_user_info,
                                            mac_addr),
                                   FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
@@ -619,7 +619,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
        }
        if (*mac == ~0ULL) {
                if (netxen_get_flash_block(adapter,
-                                          USER_START_OLD +
+                                          NETXEN_USER_START_OLD +
                                           offsetof(struct netxen_user_old_info,
                                                    mac_addr),
                                           FLASH_NUM_PORTS * sizeof(u64),
@@ -942,7 +942,7 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter,
 int
 netxen_nic_erase_pxe(struct netxen_adapter *adapter)
 {
-       if (netxen_rom_fast_write(adapter, PXE_START, 0) == -1) {
+       if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) {
                printk(KERN_ERR "%s: erase pxe failed\n", 
                        netxen_nic_driver_name);
                return -1;
@@ -953,7 +953,7 @@ netxen_nic_erase_pxe(struct netxen_adapter *adapter)
 int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 {
        int rv = 0;
-       int addr = BRDCFG_START;
+       int addr = NETXEN_BRDCFG_START;
        struct netxen_board_info *boardinfo;
        int index;
        u32 *ptr32;
@@ -1115,7 +1115,7 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
        u32 fw_build = 0;
        char brd_name[NETXEN_MAX_SHORT_NAME];
        struct netxen_new_user_info user_info;
-       int i, addr = USER_START;
+       int i, addr = NETXEN_USER_START;
        __le32 *ptr32;
 
        struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
index a36892457761321adaf634daa031d6d7dfd6afa5..bb23f4c360db39368db8681d8bb74289a5d760a7 100644 (file)
@@ -585,7 +585,7 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter)
 {
        int ret = FLASH_SUCCESS;
        int val;
-       char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL);
+       char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL);
 
        if (!buffer)
                return -ENOMEM; 
@@ -601,13 +601,13 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter)
                goto out_kfree;
 
        /* copy  sector 0 to sector 63 */
-       ret = netxen_rom_fast_read_words(adapter, CRBINIT_START, 
-                                               buffer, FLASH_SECTOR_SIZE);
+       ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START, 
+                                       buffer, NETXEN_FLASH_SECTOR_SIZE);
        if (ret != FLASH_SUCCESS)
                goto out_kfree;
 
-       ret = netxen_rom_fast_write_words(adapter, FIXED_START, 
-                                               buffer, FLASH_SECTOR_SIZE);
+       ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START, 
+                                       buffer, NETXEN_FLASH_SECTOR_SIZE);
        if (ret != FLASH_SUCCESS)
                goto out_kfree;
 
@@ -654,7 +654,8 @@ void check_erased_flash(struct netxen_adapter *adapter, int addr)
        int count = 0, erased_errors = 0;
        int range;
 
-       range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE;
+       range = (addr == NETXEN_USER_START) ? 
+               NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE;
        
        for (i = addr; i < range; i += 4) {
                netxen_rom_fast_read(adapter, i, &val);
@@ -689,7 +690,7 @@ netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end)
        int i;
 
        for (i = start; i < end; i++) {
-               ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE);
+               ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE);
                if (ret)
                        break;
                ret = netxen_rom_wip_poll(adapter);
@@ -706,8 +707,8 @@ netxen_flash_erase_secondary(struct netxen_adapter *adapter)
        int ret = FLASH_SUCCESS;
        int start, end;
 
-       start = SECONDARY_START / FLASH_SECTOR_SIZE;
-       end   = USER_START / FLASH_SECTOR_SIZE;
+       start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
+       end   = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE;
        ret = netxen_flash_erase_sections(adapter, start, end);
 
        return ret;
@@ -719,8 +720,8 @@ netxen_flash_erase_primary(struct netxen_adapter *adapter)
        int ret = FLASH_SUCCESS;
        int start, end;
 
-       start = PRIMARY_START / FLASH_SECTOR_SIZE;
-       end   = SECONDARY_START / FLASH_SECTOR_SIZE;
+       start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE;
+       end   = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
        ret = netxen_flash_erase_sections(adapter, start, end);
 
        return ret;
@@ -1036,18 +1037,23 @@ void netxen_watchdog_task(struct work_struct *work)
        if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
                return;
 
+       if (adapter->handle_phy_intr)
+               adapter->handle_phy_intr(adapter);
+
        netdev = adapter->netdev;
-       if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
-               printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
-                      netxen_nic_driver_name, adapter->portnum, netdev->name);
+       if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
+                       netxen_nic_link_ok(adapter) ) {
+               printk(KERN_INFO "%s %s (port %d), Link is up\n",
+                              netxen_nic_driver_name, netdev->name, adapter->portnum);
                netif_carrier_on(netdev);
-       }
-
-       if (netif_queue_stopped(netdev))
                netif_wake_queue(netdev);
+       } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
+               printk(KERN_ERR "%s %s Link is Down\n",
+                               netxen_nic_driver_name, netdev->name);
+               netif_carrier_off(netdev);
+               netif_stop_queue(netdev);
+       }
 
-       if (adapter->handle_phy_intr)
-               adapter->handle_phy_intr(adapter);
        mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
 
index b213b062eb567fe777651c1c196ff5d716712a38..b2de6b6c2a7f1f2dc32a0414b823a272c10a1473 100644 (file)
@@ -169,6 +169,24 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
        netxen_nic_isr_other(adapter);
 }
 
+int netxen_nic_link_ok(struct netxen_adapter *adapter)
+{
+       switch (adapter->ahw.board_type) {
+       case NETXEN_NIC_GBE:
+               return ((adapter->ahw.qg_linksup) & 1);
+
+       case NETXEN_NIC_XGBE:
+               return ((adapter->ahw.xg_linkup) & 1);
+
+       default:
+               printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
+                       netxen_nic_driver_name, __FUNCTION__);
+               break;
+       }
+
+       return 0;
+}
+
 void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -183,6 +201,10 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
                printk(KERN_INFO "%s: %s NIC Link is down\n",
                       netxen_nic_driver_name, netdev->name);
                adapter->ahw.xg_linkup = 0;
+               if (netif_running(netdev)) {
+                       netif_carrier_off(netdev);
+                       netif_stop_queue(netdev);
+               }
                /* read twice to clear sticky bits */
                /* WINDOW = 0 */
                netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
@@ -196,5 +218,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
                printk(KERN_INFO "%s: %s NIC Link is up\n",
                       netxen_nic_driver_name, netdev->name);
                adapter->ahw.xg_linkup = 1;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
        }
 }
index c61181f23bd58dce16d347240b39da5f04f3fb40..6167b58d2731fea3d5941a424108e2033f98b51c 100644 (file)
@@ -542,6 +542,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
                /* Handshake with the card before we register the devices. */
                netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+              /* leave the hw in the same state as reboot */
+              writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+              netxen_pinit_from_rom(adapter, 0);
+              udelay(500);
+              netxen_load_firmware(adapter);
+              netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
        }
 
        /*
index cef90a78351e91d51d5bb5f2c8c758cd979592bf..75102d30730f0cdecf3942485211cfbcfe5eb59f 100644 (file)
@@ -454,16 +454,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
-       u32 reg;
        u32 portnum = physical_port[adapter->portnum];
 
        netxen_crb_writelit_adapter(adapter,
-               NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
-       netxen_nic_hw_read_wx(adapter,
-               NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), &reg, 4);
-       reg = (reg & ~0x2000UL);
+               NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
        netxen_crb_writelit_adapter(adapter,
-               NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), reg);
+               NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
 
        return 0;
 }
index 22aec5cce68310ab6e4128b2ec30435fcff5c375..b87f8d2a888bb409af90e36a99662c2310ad54d3 100644 (file)
 #define MII_M1111_PHY_LED_CONTROL      0x18
 #define MII_M1111_PHY_LED_DIRECT       0x4100
 #define MII_M1111_PHY_LED_COMBINE      0x411c
+#define MII_M1111_PHY_EXT_CR           0x14
+#define MII_M1111_RX_DELAY             0x80
+#define MII_M1111_TX_DELAY             0x2
+#define MII_M1111_PHY_EXT_SR           0x1b
+#define MII_M1111_HWCFG_MODE_MASK      0xf
+#define MII_M1111_HWCFG_MODE_RGMII     0xb
 
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -131,6 +137,45 @@ static int marvell_config_aneg(struct phy_device *phydev)
        return err;
 }
 
+static int m88e1111_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) {
+               int temp;
+
+               if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+                       temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
+                       if (temp < 0)
+                               return temp;
+
+                       temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
+
+                       err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
+                       if (err < 0)
+                               return err;
+               }
+
+               temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+               if (temp < 0)
+                       return temp;
+
+               temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+               temp |= MII_M1111_HWCFG_MODE_RGMII;
+
+               err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+               if (err < 0)
+                       return err;
+       }
+
+       err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 static int m88e1145_config_init(struct phy_device *phydev)
 {
        int err;
@@ -152,7 +197,7 @@ static int m88e1145_config_init(struct phy_device *phydev)
        if (err < 0)
                return err;
 
-       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
                int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
                if (temp < 0)
                        return temp;
@@ -206,7 +251,7 @@ static struct phy_driver m88e1101_driver = {
        .driver = {.owner = THIS_MODULE,},
 };
 
-static struct phy_driver m88e1111s_driver = {
+static struct phy_driver m88e1111_driver = {
        .phy_id = 0x01410cc0,
        .phy_id_mask = 0xfffffff0,
        .name = "Marvell 88E1111",
@@ -216,6 +261,7 @@ static struct phy_driver m88e1111s_driver = {
        .read_status = &genphy_read_status,
        .ack_interrupt = &marvell_ack_interrupt,
        .config_intr = &marvell_config_intr,
+       .config_init = &m88e1111_config_init,
        .driver = {.owner = THIS_MODULE,},
 };
 
@@ -241,9 +287,9 @@ static int __init marvell_init(void)
        if (ret)
                return ret;
 
-       ret = phy_driver_register(&m88e1111s_driver);
+       ret = phy_driver_register(&m88e1111_driver);
        if (ret)
-               goto err1111s;
+               goto err1111;
 
        ret = phy_driver_register(&m88e1145_driver);
        if (ret)
@@ -251,9 +297,9 @@ static int __init marvell_init(void)
 
        return 0;
 
-      err1145:
-       phy_driver_unregister(&m88e1111s_driver);
-      err1111s:
+err1145:
+       phy_driver_unregister(&m88e1111_driver);
+err1111:
        phy_driver_unregister(&m88e1101_driver);
        return ret;
 }
@@ -261,7 +307,7 @@ static int __init marvell_init(void)
 static void __exit marvell_exit(void)
 {
        phy_driver_unregister(&m88e1101_driver);
-       phy_driver_unregister(&m88e1111s_driver);
+       phy_driver_unregister(&m88e1111_driver);
        phy_driver_unregister(&m88e1145_driver);
 }
 
index 3de564b2314799b98a805d017f19ca2542db53e6..8dc09a3790cb4fe8b15d6595ae8cf0877bf850d7 100644 (file)
@@ -313,8 +313,8 @@ config USB_KC2190
        boolean "KT Technology KC2190 based cables (InstaNet)"
        depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
        help
-        Â Choose this option if you're using a host-to-host cable
-        Â with one of these chips.
+         Choose this option if you're using a host-to-host cable
+         with one of these chips.
 
 config USB_NET_ZAURUS
        tristate "Sharp Zaurus (stock ROMs) and compatible"
index 25b75b615188ff521c238a0da54021cce20e9100..b670b97bcfde488a7de7a2e4bbe47985a0597a22 100644 (file)
@@ -1562,7 +1562,7 @@ static void velocity_print_link_status(struct velocity_info *vptr)
        if (vptr->mii_status & VELOCITY_LINK_FAIL) {
                VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
        } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
-               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name);
+               VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
 
                if (vptr->mii_status & VELOCITY_SPEED_1000)
                        VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
index 00d1255e4c12026cd3ff7104e3861e217a0649fe..e88da72f8304e9a6abc00daa73590e409e76e88b 100644 (file)
@@ -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)
index 3524e3fc08b91ed27316748dc5ea528e3f7d61a0..61de78a9f6ee76156523e7041b04fd8b3b8434dd 100644 (file)
@@ -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)
 {
index 30b7bfbc985a752065b62770c9e52aa0f5cde8f8..8bcf7fe1dd80c7b531c417f5c58e565b8fd8653f 100644 (file)
@@ -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,
index 7b1edfe46b28b54856a443ecdddeb697b00fe930..6778f9af794381ec0ae40df7253aa26f0bbddfbc 100644 (file)
@@ -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;
        }
index f493fb1eaa274fccef4266ae6784e91c165c3935..346fc030c929ae172b6658df8f1a2b54113e1ac3 100644 (file)
@@ -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)"
index 2d4fd530e5e448d42fa7f2b40641ccbe39bdd934..dd3482328ad2603e7726e10d07dd4f2dc09ffc58 100644 (file)
@@ -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;
index f28af06905a5caaee0245e5a85f78176ca015b0d..6042364402b8fb0b4fe1551fe8b5c57b8ae190c5 100644 (file)
@@ -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 */
index 188c74a95216860cb1740243211b94ef013cbddd..46d0e52527447aea5d9f63073d964317dd0bd0a9 100644 (file)
@@ -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;
index 52779c52b56d97231aecfc5703e062ff68c8c64e..d975ecf18e00537bb6a67895f04f4a5bd00b6ee5 100644 (file)
@@ -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);
index b394e63894d2e21c50ba15265fd7433838c1c91d..c4975a6cf7774cc32fcd0ff3500462694b2c0f7b 100644 (file)
@@ -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
index 6ec8cf1a3ccb1cd14d39667231da28b36abdecdf..708657c89132068f2bfdbb8cc7f3552cbc182cbe 100644 (file)
@@ -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;
index 216c9c9d4d6d58b07b0ed39d86ce77e080367740..bb9cc595219e84cb0582250dc857d9892a503c0a 100644 (file)
@@ -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)
index d230ee72f9cd7751343275b08b0faf2acb99a5a0..54979c239c6329d7382176e7996a5384c371b160 100644 (file)
@@ -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,
index 9b26dda18a38c1e13fde4b3b92610a36d840d7ef..ac46cc3f6a2a1286586d51cc3bec3dce23ff0d19 100644 (file)
@@ -47,7 +47,7 @@ targets := promcon_tbl.c
 quiet_cmd_conmakehash = CNMKHSH $@
       cmd_conmakehash = scripts/conmakehash $< | \
                sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
-               -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@
+               -e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@
 
 $(obj)/promcon_tbl.c: $(src)/prom.uni
        $(call cmd,conmakehash)
index 1d4e8354b56159b407783eb073a70a4c464fcbf2..3f6c98fad437fca8f542dbd11a29a19e55d52bce 100644 (file)
@@ -656,7 +656,7 @@ static int ffb_setcolreg(unsigned regno,
 {
        u32 value;
 
-       if (regno >= 256)
+       if (regno >= 16)
                return 1;
 
        red >>= 8;
@@ -903,7 +903,7 @@ ffb_init_fix(struct fb_info *info)
 struct all_info {
        struct fb_info info;
        struct ffb_par par;
-       u32 pseudo_palette[256];
+       u32 pseudo_palette[16];
 };
 
 static int ffb_init_one(struct of_device *op)
index 4316c7fe8e21c52d92fa4cca203bb796d7594a54..c3869a96ab5877162ea6e72960f7d0fdf73e9cd1 100644 (file)
@@ -28,7 +28,7 @@ struct s3d_info {
        unsigned int            depth;
        unsigned int            fb_size;
 
-       u32                     pseudo_palette[256];
+       u32                     pseudo_palette[16];
 };
 
 static int __devinit s3d_get_props(struct s3d_info *sp)
@@ -52,15 +52,14 @@ static int s3d_setcolreg(unsigned regno,
 {
        u32 value;
 
-       if (regno >= 256)
-               return 1;
+       if (regno < 16) {
+               red >>= 8;
+               green >>= 8;
+               blue >>= 8;
 
-       red >>= 8;
-       green >>= 8;
-       blue >>= 8;
-
-       value = (blue << 24) | (green << 16) | (red << 8);
-       ((u32 *)info->pseudo_palette)[regno] = value;
+               value = (blue << 24) | (green << 16) | (red << 8);
+               ((u32 *)info->pseudo_palette)[regno] = value;
+       }
 
        return 0;
 }
index 08880a62bfa3302e3983169b73dd461f6c50913d..71bf3f1f00bcf1b9f2aa018281494a9a2a6b0e72 100644 (file)
@@ -50,7 +50,7 @@ struct e3d_info {
        u32                     fb8_0_off;
        u32                     fb8_1_off;
 
-       u32                     pseudo_palette[256];
+       u32                     pseudo_palette[16];
 };
 
 static int __devinit e3d_get_props(struct e3d_info *ep)
@@ -126,7 +126,9 @@ static int e3d_setcolreg(unsigned regno,
        blue_8 = blue >> 8;
 
        value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
-       ((u32 *)info->pseudo_palette)[regno] = value;
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16)
+               ((u32 *)info->pseudo_palette)[regno] = value;
 
 
        red_10 = red >> 6;
index 7b0265d7f3a84a88f537b8e9174a27e4c3e650b6..861141b4f6d6f4cbbfcd96366074db8e4adbeaf3 100644 (file)
@@ -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;
index 0023b31e48a896502fa18ff11764e82def0e9ba3..a480b09c79b916de88252129919bedbbfb10850a 100644 (file)
@@ -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);
index a93620ce4aca80e7444ca01cffd24ee45b16b359..2b205f5d5790e73d281f6fbf7e298d2f7dc3b782 100644 (file)
@@ -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)
index 9345a46ffb325f3dda57a0aeb048e3428475ad0c..5d258c40a2fd9c59fead95c4d3d84d7a4092bce3 100644 (file)
@@ -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))
index 795fcc266228b93f914a42b9a037fb4bb7046003..01b433de22726baabddcfa1ff461a9718cacf60a 100644 (file)
@@ -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 */
index 7251a344c740455a7e627a01e996e89c81b8e5e1..1014e9bf181ff14645d76d2450981a21a349fdba 100644 (file)
@@ -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 */
index aeba24347f8e43355619711b3a4f10e4ec0a8c4d..9e99241f3edf41b12c11a7a99a7abda56adde01c 100644 (file)
@@ -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)
index be303b3eef4096e06be42497583fec69ea097e94..6931af525da3201873274337a993d342d2c9b14b 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
+#include <linux/types.h>
 #include <linux/linkage.h>
 
 struct thread_struct;
index 92e62ef711edbac3d7aeedd7d73ffcccfc705fa4..c5f20df780e927e3146137989000ce0f0b39db9e 100644 (file)
        .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
  */
index daaf9f98fc63ce7547a3660b915cb0ee2599e547..a9db576a9768e0493711dd07ee39e2bdc63b6e5f 100644 (file)
@@ -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. */
index 2f1087b3a20278241d719fa60d594f744780bebf..91c306fcfb725d18b247192cfb310093275bdb20 100644 (file)
 #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
index 3a4acb3e38a15239f695d0f95313977f5cb2f2bc..907c062b4c9a8296eebc5f77964d12296ed35acf 100644 (file)
@@ -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 */
index 03c385de7619e517373fd9216670761354938473..445026fbec35e4619ca3b5a1b005a88f9841d5d6 100644 (file)
@@ -31,7 +31,7 @@ typedef struct {
        unsigned int    ecache_size;
        unsigned int    ecache_line_size;
        int             core_id;
-       unsigned int    __pad3;
+       int             proc_id;
 } cpuinfo_sparc;
 
 DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
index 9329429fb7f6af6ae2c50ad92e24e83482b752f4..4e21c2f3065ca16988802fab9067f80c43e2dddc 100644 (file)
@@ -162,6 +162,22 @@ dma_mapping_error(dma_addr_t dma_addr)
 #else
 
 struct device;
+struct page;
+struct scatterlist;
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+       BUG();
+       return 0;
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       BUG();
+       return 0;
+}
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, gfp_t flag)
@@ -176,6 +192,52 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
        BUG();
 }
 
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+              enum dma_data_direction direction)
+{
+       BUG();
+       return 0;
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+                enum dma_data_direction direction)
+{
+       BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+            unsigned long offset, size_t size,
+            enum dma_data_direction direction)
+{
+       BUG();
+       return 0;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+              enum dma_data_direction direction)
+{
+       BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+          enum dma_data_direction direction)
+{
+       BUG();
+       return 0;
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+            enum dma_data_direction direction)
+{
+       BUG();
+}
+
 static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
                        enum dma_data_direction direction)
@@ -190,6 +252,27 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t siz
        BUG();
 }
 
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+                   enum dma_data_direction direction)
+{
+       BUG();
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+                      enum dma_data_direction direction)
+{
+       BUG();
+}
+
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+       BUG();
+       return 0;
+}
+
 #endif /* PCI */
 
 
index 4a43075a0619c5b5ccca6bdb4fc2516b39ed269e..5c2f9d4b9f06070813dad3cfe907aca906bbe080 100644 (file)
@@ -2798,6 +2798,11 @@ struct hv_mmu_statistics {
  */
 #define HV_FAST_MMUSTAT_INFO           0x103
 
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+extern unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
 /* NCS crypto services  */
 
 /* ncs_request() sub-function numbers */
index f76e1492add5f34aebfb331a86de57aef81083ef..4fb8c4bfb84869bf58c302f811bdb2857aecd69d 100644 (file)
@@ -33,6 +33,8 @@ extern cpumask_t phys_cpu_present_map;
 #define cpu_possible_map phys_cpu_present_map
 
 extern cpumask_t cpu_sibling_map[NR_CPUS];
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern int sparc64_multi_core;
 
 /*
  *     General functions that each host system must provide.
index e0d450d600ec2a7890cc7bca91572f8e56fd472a..290ac75f385bee443a24eb9bba11fb70783edc46 100644 (file)
@@ -1,12 +1,17 @@
 #ifndef _ASM_SPARC64_TOPOLOGY_H
 #define _ASM_SPARC64_TOPOLOGY_H
 
-#include <asm/spitfire.h>
-#define smt_capable()  (tlb_type == hypervisor)
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)      (cpu_data(cpu).proc_id)
+#define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
+#define topology_core_siblings(cpu)            (cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)          (cpu_sibling_map[cpu])
+#define mc_capable()                           (sparc64_multi_core)
+#define smt_capable()                          (sparc64_multi_core)
+#endif /* CONFIG_SMP */
 
 #include <asm-generic/topology.h>
 
-#define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
-#define topology_thread_siblings(cpu)          (cpu_sibling_map[cpu])
+#define cpu_coregroup_map(cpu)                 (cpu_core_map[cpu])
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
index d815649617aadb0701dee98672dd53661d9bb7d2..1c1e0d933eea8311db44907231d94a62b025c334 100644 (file)
@@ -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
 
 #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
index 0f540a5f4c01c7f6ef799a9b1c997348ce3a6b22..765edf17a9a466b5497046c4c78a50185dc83a92 100644 (file)
@@ -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 */
index bd09ec02d57f941182f2de62a4de7476c36250d2..aa2121034558684f3f6a654b383a77bb838ae558 100644 (file)
@@ -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 */
index 20965e3af1dde6117b43811aaf9f319b9ca86c0e..f35678cb0a9b1153cb19bbe109a78d0e5f2b6d2f 100644 (file)
@@ -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 */
index f0f9fd8560a5f905aebd43e321688e771dc572fe..1569b53cec91a38a36643480ea5a1d874cca9e1f 100644 (file)
@@ -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))
index 0609fc691b72b97b3d4511f4993788560561b964..46ab12db57397dfc44a7aa84f9c10ac5e97509d9 100644 (file)
@@ -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>
index 92f948392ebccede88123965b1d71bd91c1a48ca..c0fd8e5b4513562ee5d9884108fbb1723ed7cd8d 100644 (file)
@@ -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>
index c631d006194b476db9d4f307a3e034f20625aa60..1213cde7543803d813f6a87c261525936138b07f 100644 (file)
@@ -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 */
index 6f281392e3f854fc0589b104f9d188f3c4210e3a..ce3a336cad07c188ebe7dc10805c2d6c060212a8 100644 (file)
 #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
index 1b7fe363fad1ea4dda17622cab04471ba5f344a4..77ff02d307bba119141aacfa733d51f01c137168 100644 (file)
@@ -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)
index d3b65bfa71c3b7314ddf3b8cfc6e451696a85f77..c8cc16c3da9e68f8e409eed03db985298a9eca07 100644 (file)
@@ -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,
index a75177291418d5302c72ca2c032a560c90ac23dc..e3381cee5059ae9946f3c53044c8fcac45276651 100644 (file)
@@ -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 */
index 5ae34ab715972a812ef81a8e634e18d8ea50b776..3fa29799b435302e3ca7ddfd4131c4f51d6b2545 100644 (file)
@@ -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 */
index 8a7fb6964ce144319576ce856cfd4d16284abf68..9bd34024431c12a2b7cace88e566402fa7334828 100644 (file)
@@ -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 */
 
index a461f76fb004e874f38ec245c6a6834b333a5004..dc77fed7b28566c585ccc2193f14dfdea8227421 100644 (file)
@@ -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 */
index c0f7aec331c2031f3aa0f1c89db00a7b0b14b699..ae04901aa09a838bef2a20674848f7cb5c72e5fe 100644 (file)
@@ -3,6 +3,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/bitmap.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 
 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);
index 45353d757cd0f1ca57cc266aaf228c549fcfbf48..7a485250591491089549455a60c944aa4be0a5ff 100644 (file)
@@ -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
index 2f46dd728ee1fa9596e4a491782543fc44946012..e992cd6b28f57798e17d4e3c7f7aa9c81554da01 100644 (file)
@@ -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.
  */
index 7c1ffbab78657a105018ffd2c71b8871496255f4..a8a6ea809da096d19fbb0d164c986be671dcef12 100644 (file)
@@ -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;
index d58e74b98367c756e488b1ce3cf88903e078b7e0..693f0e6c54d47595c6f3268d0e20b5de74303d90 100644 (file)
@@ -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 */
index 0764c829d967ab8c1841cddf79ba51204956e4a8..a0ad37463d623ec1a933c7bc7c3cb8c966b15ff6 100644 (file)
@@ -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
index 4f90f5554faccc3bad4dce9d028cb58be3cbe9eb..a6bb94530cfddfbd0e8d3bd10880fdfcd8c996b5 100644 (file)
@@ -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)
 {
index ed3a8872c6cafa25f550ba6dcaa2b2d30328d339..83e41dd15ccde6e88b304687dac539462815d7dd 100644 (file)
@@ -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;
 };
index adff4c898d50ea40d5a4b09afedbf708c0c508f8..b6eaca122db871ab4b269a99dcbabda0fe9bcf90 100644 (file)
@@ -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,
index bb207db03675bbe473b1d7d00e6e3c5c27e1aaf4..abf2820a1125d73af2a83b8dab7a6e66509c88e5 100644 (file)
@@ -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,
index 5a4a0366c24feb89883bcef5898054b0add95fa1..69252cbe05b0392fe392b4ca708784330ba73f29 100644 (file)
@@ -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);
index 83da7e1f0d3db8aeaae7d6e21bdcfe7c3e5d2715..9b7d6f2ac9a3ed9c0107a16131be3e165477e6ed 100644 (file)
@@ -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)
 {
index 0bf325c29aff4803a9dcfed9b53d12cce6ac3ae1..7b510a9edb911a34dbf6b356318cb5a45a09d09d 100644 (file)
@@ -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);
 }
index 496f89d45c8b89eabf7b57bde71016e85552a677..98755ebaf163cfe788b4117167cfeaf1a861f269 100644 (file)
@@ -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,
index 50b4b424d1caab47e79673eb3fa6972c45651e91..635b0eafca95d256e789edb0323cbb8aef759f4f 100644 (file)
@@ -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 */
index 90185e8b335e61b1baad56a27607e02cdc604601..311f25af5e1a7b936a87f8b3a0fd17926688a806 100644 (file)
@@ -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);
index 5b888c24e43e0ce650e554c5cec34a99f699c1fd..5c8ecbaa19a530cc4d417a897457b0d0318bc39b 100644 (file)
@@ -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();
index b7ce15c67e324b468d13599d47df7423adcd69d4..3b7f7713d9a4148e4ee0c9e9a748be0009b7d5c7 100644 (file)
@@ -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);
 
index 12879f6c1ec3b9a53069690f0205082ea581565c..a6fbb41305210c9d3d45c56a670f3fe96af6ce64 100644 (file)
@@ -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;
                }
index acdfc0549c6fd88c254f8d07009edcc123804bfb..fe590e00db8df24823280b0bbf94a1daead4cfb5 100644 (file)
@@ -105,7 +105,11 @@ static int recalc_sigpending_tsk(struct task_struct *t)
                set_tsk_thread_flag(t, TIF_SIGPENDING);
                return 1;
        }
-       clear_tsk_thread_flag(t, TIF_SIGPENDING);
+       /*
+        * We must never clear the flag in another thread, or in current
+        * when it's possible the current syscall is returning -ERESTART*.
+        * So we don't clear it here, and only callers who know they should do.
+        */
        return 0;
 }
 
@@ -121,7 +125,9 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-       recalc_sigpending_tsk(current);
+       if (!recalc_sigpending_tsk(current))
+               clear_thread_flag(TIF_SIGPENDING);
+
 }
 
 /* Given the mask, find the first available signal that should be serviced. */
@@ -385,7 +391,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                        }
                }
        }
-       recalc_sigpending_tsk(tsk);
+       if (likely(tsk == current))
+               recalc_sigpending();
        if (signr && unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
@@ -1580,8 +1587,9 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
        /*
         * Queued signals ignored us while we were stopped for tracing.
         * So check for any that we should take before resuming user mode.
+        * This sets TIF_SIGPENDING, but never clears it.
         */
-       recalc_sigpending();
+       recalc_sigpending_tsk(current);
 }
 
 void ptrace_notify(int exit_code)
index e6da5b7fc29a1f7ad57842e6f477f096f45c89a7..473f5aed6caeebe88e813429a6e690e3c4ba42c9 100644 (file)
  * 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);
index fc5f3f6e73299a27e394294efb4564dea3511c2c..ac1520651b9b457d89e96bd2447aae02d6f8bb46 100644 (file)
@@ -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;
index e537317bec4d5d02977bf92021d87242e2ff549b..b6aae2b33393d96d694145326c6591acf6f83b4b 100644 (file)
@@ -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;
index 2e71a328aa09540a75f83ab289a3da8931920914..6d65cf4e4b2e03fb1cbd860a1932ce0cd5cb2621 100644 (file)
--- 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)) {
index 51663a3c3c243c1afeaba27e21b7333808bc1cff..c9ab68881b43ebe8525fb2fa1e943f9810229c21 100644 (file)
--- 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);
 }
index 545e4d3afcdff14877204b270bf6e671c33d5509..e03b39f3540f79adf384c476f185e7a9da91e4ac 100644 (file)
@@ -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;
@@ -279,27 +300,6 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
                           get_order(sizeof(struct page) * 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
index 5a7f20f7857468aeab6ba56ba391c228a59efc91..26090621ea6b6b6e5c5210a6cfaaa2915a135e5e 100644 (file)
@@ -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;
 }
index 764bccb3d99265b2a014b41167d999cf1574e639..c6a05879d58cd3c87fb854541bb3c3440d858de9 100644 (file)
@@ -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);
index 6f3bb73053c23fc6d4427957567d3a84c6033b62..9df26a07f0672ccabe610f366026fa4b2123524c 100644 (file)
@@ -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 },
index 27da9cdec6a83b5bdcb41110c9dd7a28eac914fc..02e8bf084277963300be7cd68f7a8b6de67cab59 100644 (file)
@@ -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;
index 764a56a13e3831f8a93d7908164c57476d25e874..ab41c1879fd498612f15e5356ab6a06a063d4050 100644 (file)
@@ -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,
index 17a1932216d63f01d8b3d4ff6e802d825eecc008..84ff3dd370709fc8c8c7f2927d1e6f9861019ea5 100644 (file)
@@ -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,
 };
 
index 7110779a0244598b17518c46cc4784370198f3d0..e00767e8ebd94ed4facfc11b3a3b746e84a50345 100644 (file)
@@ -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;
index 86a2b52aad3836c6aef2edf83413c3bda42a1319..ab56a052ce31cb53e873df670a4afdc8dc68972a 100644 (file)
@@ -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) {
@@ -1891,29 +1892,6 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
        return ret_val;
 }
 
-/**
- * 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
@@ -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)
index 7f95e6e9beebd55ff6ade8adfcfcbacf9488f89f..abf6352f990f33ff380a27f364325b4f57153b56 100644 (file)
 #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) {
index 9ad1f6252a9729fd5bc9e9ec1af69e690ad75e3e..311d633f7f397b545b6a0839319c1d446c18eb27 100644 (file)
@@ -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 },
index 33083ad52e9ff2d0678f9a2914c230a98b1a40d5..2a947840210ece1a1e218972725e5bda5b21ea6f 100644 (file)
@@ -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 },
 };
index f4dd47453108e5041dd4394308d64567522ec1ac..a646409c2d068040ac0054b9f2cf3a29472a495d 100644 (file)
  * 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);
index d6427d9185125c34140f5306b98a692b255a6619..34ea4547ebbea10cda26bca8a6f05307218b9518 100644 (file)
@@ -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) {
index 0ebae413ae873c733d21880c8ceadf5ebbde18b1..d96582acdf69a7b4110cc4dfafc2d2c290d7a379 100644 (file)
@@ -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;
index e3f83bf160d9ebf01d518664237c8864bee58a22..9bacf1a0363085793544d85a1658f8ce91f2d8ba 100644 (file)
@@ -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,
@@ -1448,6 +1450,31 @@ compat_check_calc_match(struct ipt_entry_match *m,
        return 0;
 }
 
+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,
@@ -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();
index fd62a41d69cc82e3cc2da81b088ac36d4316a265..6dc72a815f77623a2973f94a5d3a84eafae1f80f 100644 (file)
@@ -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,
index cdbc6c1358494c616d8146c9a23712ca6c92e308..3b690cf2a4ee62263a16c11c6f69d861f42e1056 100644 (file)
@@ -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",
index 8603cfb271f2c49d673d6ac24999872597a2f080..29ca63e81ced23877fe568573b8522e0ce16d8a1 100644 (file)
@@ -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) {
index 6817d6485df5c195430ab808c2c345e8d6e15ba4..53ef0f4bbdaa507137d0a99b7a120fe43bddf1bb 100644 (file)
@@ -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,
index 47c61055eb601ae73a68b899fdccf5bb8e1921b2..97e294e8267913477987ef38d473cf5ff534df2c 100644 (file)
@@ -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);
 
index 760165a0800c317884015f7997b3106aa7ad8562..d9323dfff82620487b413ce9e6b61fa426108e37 100644 (file)
@@ -62,6 +62,9 @@ struct {
  * Print to log with timestamps.
  * 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;
@@ -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.
index e61340150ba6c3aacdf9d5012b7e50f382e5be4d..e9b151b3a598e46dfd162bdc4645bdb083d48e83 100644 (file)
@@ -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);
                }
index 5da703e699da243afcf6e660d0e6a3df09979981..facb7e29304e7df9a7a172d2e4ad2f63acfa1074 100644 (file)
@@ -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);
index 06d94195e644848fa464f54456c4abb450496a25..820a477cfaa6e9899234b03ee8120c9ca158babd 100644 (file)
@@ -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);
index 3653b32dce2d79f6ec18eb2a484aaf325448578a..f34fd686a8f15ac6e49b687742701c1037ab1417 100644 (file)
@@ -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)
index 329de679ac383c656122a80013076133d7643fc6..5a5f8bd4597a71362570316cfbeb068d2ad5af24 100644 (file)
@@ -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) },
index fc3882c906049ce8b051b30c1658fa20e1f6fce6..53b3998a486ced67d9eae000cff6c9a1269ecf66 100644 (file)
@@ -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,
 };
 
index dc442fb791b0c2c7dcc58a2c8d45eca3dc76ff4a..1b1797f1f33d0e839926dab7b3fcc88cfacb85c8 100644 (file)
@@ -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:
index 1324b06796c0b10aeb8915daebece85e55c854ed..fe8d9837f9f89a2067b5f633d5a9cdd992385bf2 100644 (file)
@@ -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 },
index d1fbddd172e76c277625254641e59ae884488f0a..4210951edb6e9f0d6b8d88d917d99dd34689c5db 100644 (file)
 
 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,
index 36b0c11a28a312dcad2bfa6f82d4bbd057dd307e..6e252f318f7c91c81f5cdf04d2822b476f26a8ae 100644 (file)
@@ -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 []);
index c40a51362f89ed6861d64acccdf371712ca7c61b..f54016a55004d2d931471c06f14db922efa5f84d 100644 (file)
@@ -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 = {
index d302ddae580c567b19dc7edc3925f883453bc126..0f8304b0246bac224f241d7036341bf83db55532 100644 (file)
@@ -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;
index b8869eab7650f233ae50181838f93323ec121290..0568f2e86b5990cc713bd4a374fe3995a04dc898 100644 (file)
@@ -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;
 }
 
index 483e927a9ca4130182815670c138b87eca3a856b..7a15e30356f2284613c708dc081ceebfeff94e23 100644 (file)
@@ -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);
 }
index 117cbfdb910c57bf08b4f62e1a254cccb32df7c1..504fb6c083f99bc30a9fac847943fa2dac4c51cb 100644 (file)
@@ -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.. */
index 0743be4434b019d201a0caa4dc5826d7061d4f75..f868b7fbd9b4caee49d1e49b560ff6daeaa185bf 100644 (file)
@@ -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;
 }
index d6d39e2413278b5b8fa9a60523be7a74ded14979..3f73327794ab40a7bb4ae05d0a8b3334458f9eea 100644 (file)
@@ -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;
 
index 5434472420fe68dc83cc231cbc6436d5d47854d9..339c397d1b5facb318419deeeb6fb2e1e876de62 100644 (file)
@@ -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++) {
index 07e47dbcb0a9cd1fa455ef8b7f7d60c19ac33971..24b660f16ce3b5c74bb74035ed935f7a2f96ed86 100644 (file)
@@ -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 },
index f2535e7f286979bf5488b7464a39a64c7d79ace7..b165712aaa702ae09d4d35c252c089ac5506a906 100644 (file)
@@ -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;
@@ -308,30 +307,6 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
        return netlbl_unlabel_getattr(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
index e8c80f33f3d717ee91e43dd2f41388d914564bbb..e00fc219c72b7c70cd6c581ccd474e0a8c3b2034 100644 (file)
@@ -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 },
index b931edee4b8be1c3836a200461915a0ed9d4e8a9..5c303c68af1d074e003e778b25360160f71b986f 100644 (file)
@@ -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 },
 };
 
index df5f820a4c325be1547b778031b1f9bfcd159ca7..c591212793ee4d7cbd981cabe753a5825f68b4fc 100644 (file)
@@ -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;
index 6e31234a41966e0df32becfe61613036ac6fd2bd..b9ab62f938d07111f2b7489ad9f5ca9d31dbb746 100644 (file)
@@ -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 },
index be7d299acd73e8f9ab3d39b8ffd9c6469db89419..d1c383fca82c277b2d7c2138b9f4226d25500a5f 100644 (file)
@@ -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);
index a294542cb8e4724eba3f3995e775568123cb481b..ee2d5967d109bdd61c7eb67c4ec04d585974b1f5 100644 (file)
@@ -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;
 
index 87c794d8fa2d55a272934e72330abc346335e5e5..d70fa30d4294383f4cbdc45feec8a1df90f65a2b 100644 (file)
@@ -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 */
index 64a375178c5f28b2b4adb61ed9a76a62a9e15a09..157bfbd250ba62f2c451805106b25a1f13b581bf 100644 (file)
@@ -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
-
index 372f06eb8bb7e389298c555999f785232a92ff94..85f3f43a6cca402a3339aa4ef8317d7b41eaaa00 100644 (file)
@@ -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);
 
index b14c7e590c31b8e5898ba2f389f7accbe17ec853..c06883bf620ee21fa896654847fc4ee85f445e33 100644 (file)
@@ -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;
old mode 100644 (file)
new mode 100755 (executable)
index e216d49..aea90d3
@@ -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;
                }
index bf8750791dd19613a6ae40a77dc9be4feb167c90..e64eca246f1ab25ce57cb1190cc578fa643421e9 100644 (file)
@@ -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 to label
  * @sid: the SID to use
  *
  * Description:
  * this function and rcu_read_unlock() after this function returns.
  *
  */
-static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
+static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
 {
        int rc;
-       struct sk_security_struct *sksec = sock->sk->sk_security;
+       struct sk_security_struct *sksec = sk->sk_security;
        struct netlbl_lsm_secattr secattr;
 
        rc = security_netlbl_sid_to_secattr(sid, &secattr);
        if (rc != 0)
                return rc;
 
-       rc = netlbl_socket_setattr(sock, &secattr);
+       rc = netlbl_sock_setattr(sk, &secattr);
        if (rc == 0) {
                spin_lock_bh(&sksec->nlbl_lock);
                sksec->nlbl_state = NLBL_LABELED;
@@ -206,7 +206,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
        /* Try to set the NetLabel on the socket to save time later, if we fail
         * here we will pick up the pieces in later calls to
         * selinux_netlbl_inode_permission(). */
-       selinux_netlbl_socket_setsid(sock, sksec->sid);
+       selinux_netlbl_sock_setsid(sk, sksec->sid);
 
        rcu_read_unlock();
 }
@@ -223,14 +223,15 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
 int selinux_netlbl_socket_post_create(struct socket *sock)
 {
        int rc = 0;
+       struct sock *sk = sock->sk;
        struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
-       struct sk_security_struct *sksec = sock->sk->sk_security;
+       struct sk_security_struct *sksec = sk->sk_security;
 
        sksec->sclass = isec->sclass;
 
        rcu_read_lock();
        if (sksec->nlbl_state == NLBL_REQUIRE)
-               rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
+               rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
        rcu_read_unlock();
 
        return rc;
@@ -251,14 +252,16 @@ int selinux_netlbl_socket_post_create(struct socket *sock)
 int selinux_netlbl_inode_permission(struct inode *inode, int mask)
 {
        int rc;
-       struct sk_security_struct *sksec;
+       struct sock *sk;
        struct socket *sock;
+       struct sk_security_struct *sksec;
 
        if (!S_ISSOCK(inode->i_mode) ||
            ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
                return 0;
        sock = SOCKET_I(inode);
-       sksec = sock->sk->sk_security;
+       sk = sock->sk;
+       sksec = sk->sk_security;
 
        rcu_read_lock();
        if (sksec->nlbl_state != NLBL_REQUIRE) {
@@ -266,9 +269,9 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
                return 0;
        }
        local_bh_disable();
-       bh_lock_sock_nested(sock->sk);
-       rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
-       bh_unlock_sock(sock->sk);
+       bh_lock_sock_nested(sk);
+       rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+       bh_unlock_sock(sk);
        local_bh_enable();
        rcu_read_unlock();
 
@@ -345,14 +348,17 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
                                     int optname)
 {
        int rc = 0;
-       struct sk_security_struct *sksec = sock->sk->sk_security;
+       struct sock *sk = sock->sk;
+       struct sk_security_struct *sksec = sk->sk_security;
        struct netlbl_lsm_secattr secattr;
 
        rcu_read_lock();
        if (level == IPPROTO_IP && optname == IP_OPTIONS &&
            sksec->nlbl_state == NLBL_LABELED) {
                netlbl_secattr_init(&secattr);
-               rc = netlbl_socket_getattr(sock, &secattr);
+               lock_sock(sk);
+               rc = netlbl_sock_getattr(sk, &secattr);
+               release_sock(sk);
                if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
                        rc = -EACCES;
                netlbl_secattr_destroy(&secattr);