]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Pull randconfig into release branch
authorLen Brown <len.brown@intel.com>
Wed, 10 Oct 2007 04:27:26 +0000 (00:27 -0400)
committerLen Brown <len.brown@intel.com>
Wed, 10 Oct 2007 04:27:26 +0000 (00:27 -0400)
265 files changed:
Documentation/crypto/async-tx-api.txt [new file with mode: 0644]
Documentation/devices.txt
Documentation/input/iforce-protocol.txt
Documentation/kernel-parameters.txt
Documentation/lguest/lguest.c
Documentation/lockstat.txt [new file with mode: 0644]
Documentation/sysrq.txt
MAINTAINERS
Makefile
arch/arm/kernel/bios32.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mm/cache-l2x0.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/mach-common/entry.S
arch/i386/boot/header.S
arch/i386/boot/memory.c
arch/i386/boot/video.c
arch/i386/kernel/acpi/wakeup.S
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/xen/enlighten.c
arch/i386/xen/mmu.c
arch/mips/au1000/common/pci.c
arch/mips/au1000/mtx-1/board_setup.c
arch/mips/au1000/pb1000/board_setup.c
arch/mips/au1000/pb1100/board_setup.c
arch/mips/au1000/pb1500/board_setup.c
arch/mips/dec/setup.c
arch/mips/kernel/cpu-bugs64.c
arch/mips/kernel/i8259.c
arch/mips/kernel/irq-msc01.c
arch/mips/kernel/irq.c
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smtc.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/mm/pg-r4k.c
arch/mips/pci/ops-mace.c
arch/mips/sgi-ip32/ip32-platform.c
arch/mips/sibyte/bcm1480/setup.c
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/kernel/process.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/vdso.c
arch/powerpc/platforms/83xx/usb.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/commproc.c
arch/ppc/8xx_io/commproc.c
arch/sparc/kernel/ebus.c
arch/sparc64/kernel/binfmt_aout32.c
arch/sparc64/kernel/ebus.c
arch/sparc64/kernel/pci_common.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/vio.c
arch/sparc64/lib/NGcopy_from_user.S
arch/sparc64/lib/NGcopy_to_user.S
arch/sparc64/lib/NGmemcpy.S
arch/um/include/kern_util.h
arch/um/kernel/irq.c
arch/um/os-Linux/file.c
arch/um/os-Linux/signal.c
arch/x86_64/Kconfig
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/acpi/wakeup.S
arch/x86_64/kernel/process.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/smp.c
arch/x86_64/mm/fault.c
arch/x86_64/vdso/voffset.h
crypto/async_tx/async_tx.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/sleep/Makefile
drivers/acpi/sleep/main.c
drivers/acpi/sleep/poweroff.c [deleted file]
drivers/acpi/video.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-sff.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_marvell.c
drivers/ata/pata_sis.c
drivers/ata/sata_mv.c
drivers/ata/sata_sil24.c
drivers/base/core.c
drivers/block/DAC960.c
drivers/cdrom/cdrom.c
drivers/char/Makefile
drivers/char/agp/agp.h
drivers/char/agp/intel-agp.c
drivers/char/drm/i915_drv.h
drivers/char/drm/i915_irq.c
drivers/char/hpet.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/mspec.c
drivers/char/random.c
drivers/char/vt_ioctl.c
drivers/firewire/Kconfig
drivers/ide/ide-disk.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ohci1394.c
drivers/infiniband/hw/mlx4/qp.c
drivers/input/joystick/Kconfig
drivers/input/mouse/appletouch.c
drivers/isdn/i4l/isdn_common.c
drivers/kvm/Kconfig
drivers/lguest/lguest_asm.S
drivers/md/raid5.c
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/usbvision/usbvision-cards.c
drivers/media/video/usbvision/usbvision-video.c
drivers/mtd/nand/cafe_nand.c
drivers/net/bnx2.c
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/mv643xx_eth.c
drivers/net/mv643xx_eth.h
drivers/net/myri10ge/myri10ge.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/phy/phy.c
drivers/net/ppp_mppe.c
drivers/net/pppoe.c
drivers/net/pppol2tp.c
drivers/net/qla3xxx.c
drivers/net/r8169.c
drivers/net/sky2.c
drivers/net/sky2.h
drivers/net/usb/dm9601.c
drivers/net/wireless/Makefile
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/pci/quirks.c
drivers/power/power_supply_sysfs.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/esp_scsi.c
drivers/scsi/megaraid.c
drivers/scsi/scsi_transport_spi.c
drivers/serial/cpm_uart/cpm_uart_cpm1.h
drivers/serial/serial_cs.c
drivers/serial/sunsab.c
drivers/video/intelfb/intelfbhw.c
drivers/w1/w1.c
fs/aio.c
fs/binfmt_flat.c
fs/compat_ioctl.c
fs/exec.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/lockd/svclock.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/getroot.c
fs/nfs/super.c
fs/ocfs2/aops.c
fs/ocfs2/file.c
fs/ocfs2/localalloc.c
fs/ocfs2/localalloc.h
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/vote.c
fs/signalfd.c
fs/splice.c
fs/ufs/super.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/xfs_filestream.c
fs/xfs/xfs_mru_cache.c
fs/xfs/xfs_mru_cache.h
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_drivers.h
include/acpi/processor.h
include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
include/asm-blackfin/mach-bf537/portmux.h
include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
include/asm-blackfin/portmux.h
include/asm-blackfin/unistd.h
include/asm-h8300/flat.h
include/asm-i386/system.h
include/asm-m32r/flat.h
include/asm-m68knommu/flat.h
include/asm-mips/cmpxchg.h [new file with mode: 0644]
include/asm-mips/compiler.h
include/asm-mips/fcntl.h
include/asm-mips/irq.h
include/asm-mips/local.h
include/asm-mips/page.h
include/asm-mips/system.h
include/asm-powerpc/time.h
include/asm-sh/flat.h
include/asm-v850/flat.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor.h
include/linux/cpufreq.h
include/linux/init_task.h
include/linux/mempolicy.h
include/linux/sched.h
include/linux/signalfd.h
include/linux/user_namespace.h
include/linux/writeback.h
include/net/rose.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/tcp.h
init/Kconfig
init/do_mounts_initrd.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/futex_compat.c
kernel/power/Kconfig
kernel/sched.c
kernel/sched_fair.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/time/tick-broadcast.c
kernel/time/timer_stats.c
kernel/user.c
kernel/user_namespace.c
kernel/utsname.c
lib/Kconfig.debug
lib/Makefile
mm/Kconfig
mm/filemap.c
mm/fremap.c
mm/hugetlb.c
mm/memory.c
mm/mempolicy.c
mm/page-writeback.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_wx.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/ndisc.c
net/ipv6/tcp_ipv6.c
net/mac80211/ieee80211.c
net/mac80211/rc80211_simple.c
net/mac80211/wme.c
net/netfilter/nfnetlink_log.c
net/rose/rose_loopback.c
net/rose/rose_route.c
net/sched/cls_u32.c
net/sched/sch_sfq.c
net/sctp/bind_addr.c
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/sctp/sm_statetable.c
net/socket.c
net/sunrpc/svcsock.c
net/wireless/core.c
net/wireless/sysfs.c
security/selinux/hooks.c
sound/core/memalloc.c

diff --git a/Documentation/crypto/async-tx-api.txt b/Documentation/crypto/async-tx-api.txt
new file mode 100644 (file)
index 0000000..c1e9545
--- /dev/null
@@ -0,0 +1,219 @@
+                Asynchronous Transfers/Transforms API
+
+1 INTRODUCTION
+
+2 GENEALOGY
+
+3 USAGE
+3.1 General format of the API
+3.2 Supported operations
+3.3 Descriptor management
+3.4 When does the operation execute?
+3.5 When does the operation complete?
+3.6 Constraints
+3.7 Example
+
+4 DRIVER DEVELOPER NOTES
+4.1 Conformance points
+4.2 "My application needs finer control of hardware channels"
+
+5 SOURCE
+
+---
+
+1 INTRODUCTION
+
+The async_tx API provides methods for describing a chain of asynchronous
+bulk memory transfers/transforms with support for inter-transactional
+dependencies.  It is implemented as a dmaengine client that smooths over
+the details of different hardware offload engine implementations.  Code
+that is written to the API can optimize for asynchronous operation and
+the API will fit the chain of operations to the available offload
+resources.
+
+2 GENEALOGY
+
+The API was initially designed to offload the memory copy and
+xor-parity-calculations of the md-raid5 driver using the offload engines
+present in the Intel(R) Xscale series of I/O processors.  It also built
+on the 'dmaengine' layer developed for offloading memory copies in the
+network stack using Intel(R) I/OAT engines.  The following design
+features surfaced as a result:
+1/ implicit synchronous path: users of the API do not need to know if
+   the platform they are running on has offload capabilities.  The
+   operation will be offloaded when an engine is available and carried out
+   in software otherwise.
+2/ cross channel dependency chains: the API allows a chain of dependent
+   operations to be submitted, like xor->copy->xor in the raid5 case.  The
+   API automatically handles cases where the transition from one operation
+   to another implies a hardware channel switch.
+3/ dmaengine extensions to support multiple clients and operation types
+   beyond 'memcpy'
+
+3 USAGE
+
+3.1 General format of the API:
+struct dma_async_tx_descriptor *
+async_<operation>(<op specific parameters>,
+                 enum async_tx_flags flags,
+                 struct dma_async_tx_descriptor *dependency,
+                 dma_async_tx_callback callback_routine,
+                 void *callback_parameter);
+
+3.2 Supported operations:
+memcpy       - memory copy between a source and a destination buffer
+memset       - fill a destination buffer with a byte value
+xor          - xor a series of source buffers and write the result to a
+              destination buffer
+xor_zero_sum - xor a series of source buffers and set a flag if the
+              result is zero.  The implementation attempts to prevent
+              writes to memory
+
+3.3 Descriptor management:
+The return value is non-NULL and points to a 'descriptor' when the operation
+has been queued to execute asynchronously.  Descriptors are recycled
+resources, under control of the offload engine driver, to be reused as
+operations complete.  When an application needs to submit a chain of
+operations it must guarantee that the descriptor is not automatically recycled
+before the dependency is submitted.  This requires that all descriptors be
+acknowledged by the application before the offload engine driver is allowed to
+recycle (or free) the descriptor.  A descriptor can be acked by one of the
+following methods:
+1/ setting the ASYNC_TX_ACK flag if no child operations are to be submitted
+2/ setting the ASYNC_TX_DEP_ACK flag to acknowledge the parent
+   descriptor of a new operation.
+3/ calling async_tx_ack() on the descriptor.
+
+3.4 When does the operation execute?
+Operations do not immediately issue after return from the
+async_<operation> call.  Offload engine drivers batch operations to
+improve performance by reducing the number of mmio cycles needed to
+manage the channel.  Once a driver-specific threshold is met the driver
+automatically issues pending operations.  An application can force this
+event by calling async_tx_issue_pending_all().  This operates on all
+channels since the application has no knowledge of channel to operation
+mapping.
+
+3.5 When does the operation complete?
+There are two methods for an application to learn about the completion
+of an operation.
+1/ Call dma_wait_for_async_tx().  This call causes the CPU to spin while
+   it polls for the completion of the operation.  It handles dependency
+   chains and issuing pending operations.
+2/ Specify a completion callback.  The callback routine runs in tasklet
+   context if the offload engine driver supports interrupts, or it is
+   called in application context if the operation is carried out
+   synchronously in software.  The callback can be set in the call to
+   async_<operation>, or when the application needs to submit a chain of
+   unknown length it can use the async_trigger_callback() routine to set a
+   completion interrupt/callback at the end of the chain.
+
+3.6 Constraints:
+1/ Calls to async_<operation> are not permitted in IRQ context.  Other
+   contexts are permitted provided constraint #2 is not violated.
+2/ Completion callback routines cannot submit new operations.  This
+   results in recursion in the synchronous case and spin_locks being
+   acquired twice in the asynchronous case.
+
+3.7 Example:
+Perform a xor->copy->xor operation where each operation depends on the
+result from the previous operation:
+
+void complete_xor_copy_xor(void *param)
+{
+       printk("complete\n");
+}
+
+int run_xor_copy_xor(struct page **xor_srcs,
+                    int xor_src_cnt,
+                    struct page *xor_dest,
+                    size_t xor_len,
+                    struct page *copy_src,
+                    struct page *copy_dest,
+                    size_t copy_len)
+{
+       struct dma_async_tx_descriptor *tx;
+
+       tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len,
+                      ASYNC_TX_XOR_DROP_DST, NULL, NULL, NULL);
+       tx = async_memcpy(copy_dest, copy_src, 0, 0, copy_len,
+                         ASYNC_TX_DEP_ACK, tx, NULL, NULL);
+       tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len,
+                      ASYNC_TX_XOR_DROP_DST | ASYNC_TX_DEP_ACK | ASYNC_TX_ACK,
+                      tx, complete_xor_copy_xor, NULL);
+
+       async_tx_issue_pending_all();
+}
+
+See include/linux/async_tx.h for more information on the flags.  See the
+ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more
+implementation examples.
+
+4 DRIVER DEVELOPMENT NOTES
+4.1 Conformance points:
+There are a few conformance points required in dmaengine drivers to
+accommodate assumptions made by applications using the async_tx API:
+1/ Completion callbacks are expected to happen in tasklet context
+2/ dma_async_tx_descriptor fields are never manipulated in IRQ context
+3/ Use async_tx_run_dependencies() in the descriptor clean up path to
+   handle submission of dependent operations
+
+4.2 "My application needs finer control of hardware channels"
+This requirement seems to arise from cases where a DMA engine driver is
+trying to support device-to-memory DMA.  The dmaengine and async_tx
+implementations were designed for offloading memory-to-memory
+operations; however, there are some capabilities of the dmaengine layer
+that can be used for platform-specific channel management.
+Platform-specific constraints can be handled by registering the
+application as a 'dma_client' and implementing a 'dma_event_callback' to
+apply a filter to the available channels in the system.  Before showing
+how to implement a custom dma_event callback some background of
+dmaengine's client support is required.
+
+The following routines in dmaengine support multiple clients requesting
+use of a channel:
+- dma_async_client_register(struct dma_client *client)
+- dma_async_client_chan_request(struct dma_client *client)
+
+dma_async_client_register takes a pointer to an initialized dma_client
+structure.  It expects that the 'event_callback' and 'cap_mask' fields
+are already initialized.
+
+dma_async_client_chan_request triggers dmaengine to notify the client of
+all channels that satisfy the capability mask.  It is up to the client's
+event_callback routine to track how many channels the client needs and
+how many it is currently using.  The dma_event_callback routine returns a
+dma_state_client code to let dmaengine know the status of the
+allocation.
+
+Below is the example of how to extend this functionality for
+platform-specific filtering of the available channels beyond the
+standard capability mask:
+
+static enum dma_state_client
+my_dma_client_callback(struct dma_client *client,
+                       struct dma_chan *chan, enum dma_state state)
+{
+       struct dma_device *dma_dev;
+       struct my_platform_specific_dma *plat_dma_dev;
+       
+       dma_dev = chan->device;
+       plat_dma_dev = container_of(dma_dev,
+                                   struct my_platform_specific_dma,
+                                   dma_dev);
+
+       if (!plat_dma_dev->platform_specific_capability)
+               return DMA_DUP;
+
+       . . .
+}
+
+5 SOURCE
+include/linux/dmaengine.h: core header file for DMA drivers and clients
+drivers/dma/dmaengine.c: offload engine channel management routines
+drivers/dma/: location for offload engine drivers
+include/linux/async_tx.h: core header file for the async_tx api
+crypto/async_tx/async_tx.c: async_tx interface to dmaengine and common code
+crypto/async_tx/async_memcpy.c: copy offload
+crypto/async_tx/async_memset.c: memory fill offload
+crypto/async_tx/async_xor.c: xor and xor zero sum offload
index 8de132a02ba952867020a846229b0818ee73d214..6c46730c631a6952fc34beb4302011463d754011 100644 (file)
@@ -94,6 +94,8 @@ Your cooperation is appreciated.
                  9 = /dev/urandom      Faster, less secure random number gen.
                 10 = /dev/aio          Asynchronous I/O notification interface
                 11 = /dev/kmsg         Writes to this come out as printk's
+                12 = /dev/oldmem       Used by crashdump kernels to access
+                                       the memory of the kernel that crashed.
 
   1 block      RAM disk
                  0 = /dev/ram0         First RAM disk
index 95df4ca70e717865cb23e7520a1ab8e8f978fb21..8777d2d321e38437424896c9f45e26ddff81ebbc 100644 (file)
-** Introduction\r
-This document describes what I managed to discover about the protocol used to\r
-specify force effects to I-Force 2.0 devices.  None of this information comes\r
-from Immerse. That's why you should not trust what is written in this\r
-document. This document is intended to help understanding the protocol.\r
-This is not a reference. Comments and corrections are welcome.  To contact me,\r
-send an email to: deneux@ifrance.com\r
-\r
-** WARNING **\r
-I may not be held responsible for any dammage or harm caused if you try to\r
-send data to your I-Force device based on what you read in this document.\r
-\r
-** Preliminary Notes:\r
-All values are hexadecimal with big-endian encoding (msb on the left). Beware,\r
-values inside packets are encoded using little-endian.  Bytes whose roles are\r
-unknown are marked ???  Information that needs deeper inspection is marked (?)\r
-\r
-** General form of a packet **\r
-This is how packets look when the device uses the rs232 to communicate.\r
-2B OP LEN DATA CS\r
-CS is the checksum. It is equal to the exclusive or of all bytes.\r
-\r
-When using USB:\r
-OP DATA\r
-The 2B, LEN and CS fields have disappeared, probably because USB handles frames and\r
-data corruption is handled or unsignificant.\r
-\r
-First, I describe effects that are sent by the device to the computer\r
-\r
-** Device input state\r
-This packet is used to indicate the state of each button and the value of each\r
-axis\r
-OP= 01 for a joystick, 03 for a wheel\r
-LEN= Varies from device to device\r
-00 X-Axis lsb\r
-01 X-Axis msb\r
-02 Y-Axis lsb, or gas pedal for a wheel\r
-03 Y-Axis msb, or brake pedal for a wheel\r
-04 Throttle\r
-05 Buttons\r
-06 Lower 4 bits: Buttons\r
-   Upper 4 bits: Hat\r
-07 Rudder\r
-\r
-** Device effects states\r
-OP= 02\r
-LEN= Varies\r
-00 ? Bit 1 (Value 2) is the value of the deadman switch\r
-01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id.\r
-02 ??\r
-03 Address of parameter block changed (lsb)\r
-04 Address of parameter block changed (msb)\r
-05 Address of second parameter block changed (lsb)\r
-... depending on the number of parameter blocks updated\r
-\r
-** Force effect **\r
-OP=  01\r
-LEN= 0e\r
-00 Channel (when playing several effects at the same time, each must be assigned a channel)\r
-01 Wave form\r
-       Val 00 Constant\r
-       Val 20 Square\r
-       Val 21 Triangle\r
-       Val 22 Sine\r
-       Val 23 Sawtooth up\r
-       Val 24 Sawtooth down\r
-       Val 40 Spring (Force = f(pos))\r
-       Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration))\r
-\r
-       \r
-02 Axes affected and trigger\r
-       Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction\r
-                 Val 4 = X axis only. Byte 05 must contain 5a\r
-                 Val 8 = Y axis only. Byte 05 must contain b4\r
-                 Val c = X and Y axes. Bytes 05 must contain 60\r
-       Bits 0-3: Val 0 = No trigger\r
-                 Val x+1 = Button x triggers the effect\r
-       When the whole byte is 0, cancel the previously set trigger\r
-\r
-03-04 Duration of effect (little endian encoding, in ms)\r
-\r
-05 Direction of effect, if applicable. Else, see 02 for value to assign.\r
-\r
-06-07 Minimum time between triggering.\r
-\r
-08-09 Address of periodicity or magnitude parameters\r
-0a-0b Address of attack and fade parameters, or ffff if none.\r
-*or*\r
-08-09 Address of interactive parameters for X-axis, or ffff if not applicable\r
-0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable\r
-\r
-0c-0d Delay before execution of effect (little endian encoding, in ms)\r
-\r
-\r
-** Time based parameters **\r
-\r
-*** Attack and fade ***\r
-OP=  02\r
-LEN= 08\r
-00-01 Address where to store the parameteres\r
-02-03 Duration of attack (little endian encoding, in ms)\r
-04 Level at end of attack. Signed byte.\r
-05-06 Duration of fade.\r
-07 Level at end of fade.\r
-\r
-*** Magnitude ***\r
-OP=  03\r
-LEN= 03\r
-00-01 Address\r
-02 Level. Signed byte.\r
-\r
-*** Periodicity ***\r
-OP=  04\r
-LEN= 07\r
-00-01 Address\r
-02 Magnitude. Signed byte.\r
-03 Offset. Signed byte.\r
-04 Phase. Val 00 = 0 deg, Val 40 = 90 degs.\r
-05-06 Period (little endian encoding, in ms)\r
-\r
-** Interactive parameters **\r
-OP=  05\r
-LEN= 0a\r
-00-01 Address\r
-02 Positive Coeff\r
-03 Negative Coeff\r
-04+05 Offset (center)\r
-06+07 Dead band (Val 01F4 = 5000 (decimal))\r
-08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal))\r
-09 Negative saturation\r
-\r
-The encoding is a bit funny here: For coeffs, these are signed values. The\r
-maximum value is 64 (100 decimal), the min is 9c.\r
-For the offset, the minimum value is FE0C, the maximum value is 01F4.\r
-For the deadband, the minimum value is 0, the max is 03E8.\r
-\r
-** Controls **\r
-OP=  41\r
-LEN= 03\r
-00 Channel\r
-01 Start/Stop\r
-       Val 00: Stop\r
-       Val 01: Start and play once.\r
-       Val 41: Start and play n times (See byte 02 below)\r
-02 Number of iterations n.\r
-\r
-** Init **\r
-\r
-*** Querying features ***\r
-OP=  ff\r
-Query command. Length varies according to the query type.\r
-The general format of this packet is:\r
-ff 01 QUERY [INDEX] CHECKSUM\r
-reponses are of the same form:\r
-FF LEN QUERY VALUE_QUERIED CHECKSUM2\r
-where LEN = 1 + length(VALUE_QUERIED)\r
-\r
-**** Query ram size ****\r
-QUERY = 42 ('B'uffer size)\r
-The device should reply with the same packet plus two additionnal bytes\r
-containing the size of the memory:\r
-ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available.\r
-\r
-**** Query number of effects ****\r
-QUERY = 4e ('N'umber of effects)\r
-The device should respond by sending the number of effects that can be played\r
-at the same time (one byte)\r
-ff 02 4e 14 CS would stand for 20 effects.\r
-\r
-**** Vendor's id ****\r
-QUERY = 4d ('M'anufacturer)\r
-Query the vendors'id (2 bytes)\r
-\r
-**** Product id *****\r
-QUERY = 50 ('P'roduct)\r
-Query the product id (2 bytes)\r
-\r
-**** Open device ****\r
-QUERY = 4f ('O'pen) \r
-No data returned.\r
-\r
-**** Close device *****\r
-QUERY = 43 ('C')lose\r
-No data returned.\r
-\r
-**** Query effect ****\r
-QUERY = 45 ('E') \r
-Send effect type.\r
-Returns nonzero if supported (2 bytes)\r
-\r
-**** Firmware Version ****\r
-QUERY = 56 ('V'ersion)\r
-Sends back 3 bytes - major, minor, subminor\r
-\r
-*** Initialisation of the device ***\r
-\r
-**** Set Control ****\r
-!!! Device dependent, can be different on different models !!!\r
-OP=  40 <idx> <val> [<val>]\r
-LEN= 2 or 3\r
-00 Idx\r
-   Idx 00 Set dead zone (0..2048) \r
-   Idx 01 Ignore Deadman sensor (0..1)     \r
-   Idx 02 Enable comm watchdog (0..1)     \r
-   Idx 03 Set the strength of the spring (0..100)   \r
-   Idx 04 Enable or disable the spring (0/1)\r
-   Idx 05 Set axis saturation threshold (0..2048) \r
-\r
-**** Set Effect State ****\r
-OP=  42 <val>\r
-LEN= 1\r
-00 State\r
-   Bit 3 Pause force feedback\r
-   Bit 2 Enable force feedback\r
-   Bit 0 Stop all effects\r
-\r
-**** Set overall gain ****\r
-OP=  43 <val>\r
-LEN= 1\r
-00 Gain\r
-   Val 00 = 0%\r
-   Val 40 = 50%\r
-   Val 80 = 100%\r
-\r
-** Parameter memory **\r
-\r
-Each device has a certain amount of memory to store parameters of effects.\r
-The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below\r
-is the amount of memory apparently needed for every set of parameters:\r
- - period : 0c\r
- - magnitude : 02\r
- - attack and fade : 0e\r
- - interactive : 08\r
-\r
-** Appendix: How to study the protocol ? **\r
-\r
-1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com)\r
-2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!)\r
-3. Play the effect, and watch what happens on the spy screen.\r
-\r
-A few words about ComPortSpy:\r
-At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect.\r
-Remember it's free (as in free beer) and alpha!\r
-\r
-** URLS **\r
-Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy.\r
-\r
-** Author of this document **\r
-Johann Deneux <deneux@ifrance.com>\r
-Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/\r
-\r
-Additions by Vojtech Pavlik.\r
-\r
-I-Force is trademark of Immersion Corp.\r
+** Introduction
+This document describes what I managed to discover about the protocol used to
+specify force effects to I-Force 2.0 devices.  None of this information comes
+from Immerse. That's why you should not trust what is written in this
+document. This document is intended to help understanding the protocol.
+This is not a reference. Comments and corrections are welcome.  To contact me,
+send an email to: deneux@ifrance.com
+
+** WARNING **
+I may not be held responsible for any dammage or harm caused if you try to
+send data to your I-Force device based on what you read in this document.
+
+** Preliminary Notes:
+All values are hexadecimal with big-endian encoding (msb on the left). Beware,
+values inside packets are encoded using little-endian.  Bytes whose roles are
+unknown are marked ???  Information that needs deeper inspection is marked (?)
+
+** General form of a packet **
+This is how packets look when the device uses the rs232 to communicate.
+2B OP LEN DATA CS
+CS is the checksum. It is equal to the exclusive or of all bytes.
+
+When using USB:
+OP DATA
+The 2B, LEN and CS fields have disappeared, probably because USB handles frames and
+data corruption is handled or unsignificant.
+
+First, I describe effects that are sent by the device to the computer
+
+** Device input state
+This packet is used to indicate the state of each button and the value of each
+axis
+OP= 01 for a joystick, 03 for a wheel
+LEN= Varies from device to device
+00 X-Axis lsb
+01 X-Axis msb
+02 Y-Axis lsb, or gas pedal for a wheel
+03 Y-Axis msb, or brake pedal for a wheel
+04 Throttle
+05 Buttons
+06 Lower 4 bits: Buttons
+   Upper 4 bits: Hat
+07 Rudder
+
+** Device effects states
+OP= 02
+LEN= Varies
+00 ? Bit 1 (Value 2) is the value of the deadman switch
+01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id.
+02 ??
+03 Address of parameter block changed (lsb)
+04 Address of parameter block changed (msb)
+05 Address of second parameter block changed (lsb)
+... depending on the number of parameter blocks updated
+
+** Force effect **
+OP=  01
+LEN= 0e
+00 Channel (when playing several effects at the same time, each must be assigned a channel)
+01 Wave form
+       Val 00 Constant
+       Val 20 Square
+       Val 21 Triangle
+       Val 22 Sine
+       Val 23 Sawtooth up
+       Val 24 Sawtooth down
+       Val 40 Spring (Force = f(pos))
+       Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration))
+
+
+02 Axes affected and trigger
+       Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction
+                 Val 4 = X axis only. Byte 05 must contain 5a
+                 Val 8 = Y axis only. Byte 05 must contain b4
+                 Val c = X and Y axes. Bytes 05 must contain 60
+       Bits 0-3: Val 0 = No trigger
+                 Val x+1 = Button x triggers the effect
+       When the whole byte is 0, cancel the previously set trigger
+
+03-04 Duration of effect (little endian encoding, in ms)
+
+05 Direction of effect, if applicable. Else, see 02 for value to assign.
+
+06-07 Minimum time between triggering.
+
+08-09 Address of periodicity or magnitude parameters
+0a-0b Address of attack and fade parameters, or ffff if none.
+*or*
+08-09 Address of interactive parameters for X-axis, or ffff if not applicable
+0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable
+
+0c-0d Delay before execution of effect (little endian encoding, in ms)
+
+
+** Time based parameters **
+
+*** Attack and fade ***
+OP=  02
+LEN= 08
+00-01 Address where to store the parameteres
+02-03 Duration of attack (little endian encoding, in ms)
+04 Level at end of attack. Signed byte.
+05-06 Duration of fade.
+07 Level at end of fade.
+
+*** Magnitude ***
+OP=  03
+LEN= 03
+00-01 Address
+02 Level. Signed byte.
+
+*** Periodicity ***
+OP=  04
+LEN= 07
+00-01 Address
+02 Magnitude. Signed byte.
+03 Offset. Signed byte.
+04 Phase. Val 00 = 0 deg, Val 40 = 90 degs.
+05-06 Period (little endian encoding, in ms)
+
+** Interactive parameters **
+OP=  05
+LEN= 0a
+00-01 Address
+02 Positive Coeff
+03 Negative Coeff
+04+05 Offset (center)
+06+07 Dead band (Val 01F4 = 5000 (decimal))
+08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal))
+09 Negative saturation
+
+The encoding is a bit funny here: For coeffs, these are signed values. The
+maximum value is 64 (100 decimal), the min is 9c.
+For the offset, the minimum value is FE0C, the maximum value is 01F4.
+For the deadband, the minimum value is 0, the max is 03E8.
+
+** Controls **
+OP=  41
+LEN= 03
+00 Channel
+01 Start/Stop
+       Val 00: Stop
+       Val 01: Start and play once.
+       Val 41: Start and play n times (See byte 02 below)
+02 Number of iterations n.
+
+** Init **
+
+*** Querying features ***
+OP=  ff
+Query command. Length varies according to the query type.
+The general format of this packet is:
+ff 01 QUERY [INDEX] CHECKSUM
+reponses are of the same form:
+FF LEN QUERY VALUE_QUERIED CHECKSUM2
+where LEN = 1 + length(VALUE_QUERIED)
+
+**** Query ram size ****
+QUERY = 42 ('B'uffer size)
+The device should reply with the same packet plus two additionnal bytes
+containing the size of the memory:
+ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available.
+
+**** Query number of effects ****
+QUERY = 4e ('N'umber of effects)
+The device should respond by sending the number of effects that can be played
+at the same time (one byte)
+ff 02 4e 14 CS would stand for 20 effects.
+
+**** Vendor's id ****
+QUERY = 4d ('M'anufacturer)
+Query the vendors'id (2 bytes)
+
+**** Product id *****
+QUERY = 50 ('P'roduct)
+Query the product id (2 bytes)
+
+**** Open device ****
+QUERY = 4f ('O'pen)
+No data returned.
+
+**** Close device *****
+QUERY = 43 ('C')lose
+No data returned.
+
+**** Query effect ****
+QUERY = 45 ('E')
+Send effect type.
+Returns nonzero if supported (2 bytes)
+
+**** Firmware Version ****
+QUERY = 56 ('V'ersion)
+Sends back 3 bytes - major, minor, subminor
+
+*** Initialisation of the device ***
+
+**** Set Control ****
+!!! Device dependent, can be different on different models !!!
+OP=  40 <idx> <val> [<val>]
+LEN= 2 or 3
+00 Idx
+   Idx 00 Set dead zone (0..2048)
+   Idx 01 Ignore Deadman sensor (0..1)
+   Idx 02 Enable comm watchdog (0..1)
+   Idx 03 Set the strength of the spring (0..100)
+   Idx 04 Enable or disable the spring (0/1)
+   Idx 05 Set axis saturation threshold (0..2048)
+
+**** Set Effect State ****
+OP=  42 <val>
+LEN= 1
+00 State
+   Bit 3 Pause force feedback
+   Bit 2 Enable force feedback
+   Bit 0 Stop all effects
+
+**** Set overall gain ****
+OP=  43 <val>
+LEN= 1
+00 Gain
+   Val 00 = 0%
+   Val 40 = 50%
+   Val 80 = 100%
+
+** Parameter memory **
+
+Each device has a certain amount of memory to store parameters of effects.
+The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below
+is the amount of memory apparently needed for every set of parameters:
+ - period : 0c
+ - magnitude : 02
+ - attack and fade : 0e
+ - interactive : 08
+
+** Appendix: How to study the protocol ? **
+
+1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com)
+2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!)
+3. Play the effect, and watch what happens on the spy screen.
+
+A few words about ComPortSpy:
+At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect.
+Remember it's free (as in free beer) and alpha!
+
+** URLS **
+Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy.
+
+** Author of this document **
+Johann Deneux <deneux@ifrance.com>
+Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/
+
+Additions by Vojtech Pavlik.
+
+I-Force is trademark of Immersion Corp.
index 586b6f85d4e035e55db1aef41ca010b346c846f9..4d175c7512464671e14731239d5bf943b72c5614 100644 (file)
@@ -1,5 +1,5 @@
-                         Kernel Parameters
-                         ~~~~~~~~~~~~~~~~~
+                          Kernel Parameters
+                          ~~~~~~~~~~~~~~~~~
 
 The following is a consolidated list of the kernel parameters as implemented
 (mostly) by the __setup() macro and sorted into English Dictionary order
@@ -1462,7 +1462,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        reboot=         [BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
                        Format: <reboot_mode>[,<reboot_mode2>[,...]]
-                       See arch/*/kernel/reboot.c or arch/*/kernel/process.c
+                       See arch/*/kernel/reboot.c or arch/*/kernel/process.c                   
 
        reserve=        [KNL,BUGS] Force the kernel to ignore some iomem area
 
@@ -1550,12 +1550,12 @@ and is between 256 and 4096 characters. It is defined in the file
 
        selinux_compat_net =
                        [SELINUX] Set initial selinux_compat_net flag value.
-                       Format: { "0" | "1" }
-                       0 -- use new secmark-based packet controls
-                       1 -- use legacy packet controls
-                       Default value is 0 (preferred).
-                       Value can be changed at runtime via
-                       /selinux/compat_net.
+                        Format: { "0" | "1" }
+                        0 -- use new secmark-based packet controls
+                        1 -- use legacy packet controls
+                        Default value is 0 (preferred).
+                        Value can be changed at runtime via
+                        /selinux/compat_net.
 
        serialnumber    [BUGS=X86-32]
 
@@ -1954,7 +1954,7 @@ and is between 256 and 4096 characters. It is defined in the file
        norandmaps      Don't use address space randomization
                        Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
 
-       unwind_debug=N  N > 0 will enable dwarf2 unwinder debugging
+       unwind_debug=N  N > 0 will enable dwarf2 unwinder debugging
                        This is useful to get more information why
                        you got a "dwarf2 unwinder stuck"
 
index f7918401a0072c9b08bf81bb07434b66a96f6085..73c5f1f3d5d2e726c287396224df53cfca1bc65d 100644 (file)
@@ -882,7 +882,7 @@ static u32 handle_block_output(int fd, const struct iovec *iov,
                 * of the block file (possibly extending it). */
                if (off + len > device_len) {
                        /* Trim it back to the correct length */
-                       ftruncate(dev->fd, device_len);
+                       ftruncate64(dev->fd, device_len);
                        /* Die, bad Guest, die. */
                        errx(1, "Write past end %llu+%u", off, len);
                }
diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt
new file mode 100644 (file)
index 0000000..4ba4664
--- /dev/null
@@ -0,0 +1,120 @@
+
+LOCK STATISTICS
+
+- WHAT
+
+As the name suggests, it provides statistics on locks.
+
+- WHY
+
+Because things like lock contention can severely impact performance.
+
+- HOW
+
+Lockdep already has hooks in the lock functions and maps lock instances to
+lock classes. We build on that. The graph below shows the relation between
+the lock functions and the various hooks therein.
+
+        __acquire
+            |
+           lock _____
+            |        \
+            |    __contended
+            |         |
+            |       <wait>
+            | _______/
+            |/
+            |
+       __acquired
+            |
+            .
+          <hold>
+            .
+            |
+       __release
+            |
+         unlock
+
+lock, unlock   - the regular lock functions
+__*            - the hooks
+<>             - states
+
+With these hooks we provide the following statistics:
+
+ con-bounces       - number of lock contention that involved x-cpu data
+ contentions       - number of lock acquisitions that had to wait
+ wait time min     - shortest (non-0) time we ever had to wait for a lock
+           max     - longest time we ever had to wait for a lock
+           total   - total time we spend waiting on this lock
+ acq-bounces       - number of lock acquisitions that involved x-cpu data
+ acquisitions      - number of times we took the lock
+ hold time min     - shortest (non-0) time we ever held the lock
+           max     - longest time we ever held the lock
+           total   - total time this lock was held
+
+From these number various other statistics can be derived, such as:
+
+ hold time average = hold time total / acquisitions
+
+These numbers are gathered per lock class, per read/write state (when
+applicable).
+
+It also tracks 4 contention points per class. A contention point is a call site
+that had to wait on lock acquisition.
+
+ - USAGE
+
+Look at the current lock statistics:
+
+( line numbers not part of actual output, done for clarity in the explanation
+  below )
+
+# less /proc/lock_stat
+
+01 lock_stat version 0.2
+02 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+03                               class name    con-bounces    contentions   waittime-min   waittime-max waittime-total    acq-bounces   acquisitions   holdtime-min   holdtime-max holdtime-total
+04 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+05
+06               &inode->i_data.tree_lock-W:            15          21657           0.18     1093295.30 11547131054.85             58          10415           0.16          87.51        6387.60
+07               &inode->i_data.tree_lock-R:             0              0           0.00           0.00           0.00          23302         231198           0.25           8.45       98023.38
+08               --------------------------
+09                 &inode->i_data.tree_lock              0          [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190
+10
+11 ...............................................................................................................................................................................................
+12
+13                              dcache_lock:          1037           1161           0.38          45.32         774.51           6611         243371           0.15         306.48       77387.24
+14                              -----------
+15                              dcache_lock            180          [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230
+16                              dcache_lock            165          [<ffffffff802c002a>] d_alloc+0x15a/0x210
+17                              dcache_lock             33          [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70
+18                              dcache_lock              1          [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130
+
+This excerpt shows the first two lock class statistics. Line 01 shows the
+output version - each time the format changes this will be updated. Line 02-04
+show the header with column descriptions. Lines 05-10 and 13-18 show the actual
+statistics. These statistics come in two parts; the actual stats separated by a
+short separator (line 08, 14) from the contention points.
+
+The first lock (05-10) is a read/write lock, and shows two lines above the
+short separator. The contention points don't match the column descriptors,
+they have two: contentions and [<IP>] symbol.
+
+
+View the top contending locks:
+
+# grep : /proc/lock_stat | head
+              &inode->i_data.tree_lock-W:            15          21657           0.18     1093295.30 11547131054.85             58          10415           0.16          87.51        6387.60
+              &inode->i_data.tree_lock-R:             0              0           0.00           0.00           0.00          23302         231198           0.25           8.45       98023.38
+                             dcache_lock:          1037           1161           0.38          45.32         774.51           6611         243371           0.15         306.48       77387.24
+                         &inode->i_mutex:           161            286 18446744073709       62882.54     1244614.55           3653          20598 18446744073709       62318.60     1693822.74
+                         &zone->lru_lock:            94             94           0.53           7.33          92.10           4366          32690           0.29          59.81       16350.06
+              &inode->i_data.i_mmap_lock:            79             79           0.40           3.77          53.03          11779          87755           0.28         116.93       29898.44
+                        &q->__queue_lock:            48             50           0.52          31.62          86.31            774          13131           0.17         113.08       12277.52
+                        &rq->rq_lock_key:            43             47           0.74          68.50         170.63           3706          33929           0.22         107.99       17460.62
+                      &rq->rq_lock_key#2:            39             46           0.75           6.68          49.03           2979          32292           0.17         125.17       17137.63
+                         tasklist_lock-W:            15             15           1.45          10.87          32.70           1201           7390           0.58          62.55       13648.47
+
+Clear the statistics:
+
+# echo 0 > /proc/lock_stat
index ef19142896ca0688ca82b62a82a51fd13b7e7700..10c8f6922ef40d7a0a49b85ae6367be1a0edfd91 100644 (file)
@@ -43,7 +43,7 @@ On x86   - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
            keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
            also known as the 'Print Screen' key. Also some keyboards cannot
           handle so many keys being pressed at the same time, so you might
-          have better luck with "press Alt", "press SysRq", "release Alt",
+          have better luck with "press Alt", "press SysRq", "release SysRq",
           "press <command key>", release everything.
 
 On SPARC - You press 'ALT-STOP-<command key>', I believe.
index 9c54a5ef0ba7560232ee24fff40c3728fb277ecb..9a91d9e3f1f25c2e0aaded950fae19e4d6fa7e08 100644 (file)
@@ -2622,8 +2622,8 @@ P:        Harald Welte
 P:     Jozsef Kadlecsik
 P:     Patrick McHardy
 M:     kaber@trash.net
-L:     netfilter-devel@lists.netfilter.org
-L:     netfilter@lists.netfilter.org (subscribers-only)
+L:     netfilter-devel@vger.kernel.org
+L:     netfilter@vger.kernel.org
 L:     coreteam@netfilter.org
 W:     http://www.netfilter.org/
 W:     http://www.iptables.org/
@@ -2676,7 +2676,7 @@ M:        jmorris@namei.org
 P:     Hideaki YOSHIFUJI
 M:     yoshfuji@linux-ipv6.org
 P:     Patrick McHardy
-M:     kaber@coreworks.de
+M:     kaber@trash.net
 L:     netdev@vger.kernel.org
 T:     git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Maintained
index e0fdf499ef2075675ed39dd9058833343840772e..4635a64da36c356e70896d3fd78acddd0a29f147 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 23
-EXTRAVERSION =-rc6
-NAME = Pink Farting Weasel
+EXTRAVERSION =
+NAME = Arr Matey! A Hairy Bilge Rat!
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 240c448ec31cf15a40222d2ab8e9414fc65bf7b6..a2dd930d11efd5d9ee8f1f691a101e09c591f07e 100644 (file)
@@ -338,7 +338,7 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
  * pcibios_fixup_bus - Called after each bus is probed,
  * but before its children are examined.
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_sys_data *root = bus->sysdata;
        struct pci_dev *dev;
@@ -419,7 +419,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 /*
  * Convert from Linux-centric to bus-centric addresses for bridge devices.
  */
-void __devinit
+void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                         struct resource *res)
 {
index 851cc7158ca305bbaa1bc707979cd276a93807f7..70b2c78011102a7dea24b05f99bd97473942f1d0 100644 (file)
@@ -336,7 +336,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
        if (line >= 0 && line < 16) {
                gpio_line_config(line, GPIO_IN);
        } else {
-               gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
+               gpio_line_config(EP93XX_GPIO_LINE_F(line-16), GPIO_IN);
        }
 
        port = line >> 3;
index 0ba7e9060c7bba3ece0df5d9eacbdbeb86d71eac..c326983f4a8f5b66dcee243def28998c560d2bb2 100644 (file)
@@ -276,7 +276,21 @@ static unsigned char pm_osiris_ctrl0;
 
 static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
 {
+       unsigned int tmp;
+
        pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
+       tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL;
+
+       /* ensure correct NAND slot is selected on resume */
+       if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0)
+               tmp |= 2;
+
+       __raw_writeb(tmp, OSIRIS_VA_CTRL0);
+
+       /* ensure that an nRESET is not generated on resume. */
+       s3c2410_gpio_setpin(S3C2410_GPA21, 1);
+       s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT);
+
        return 0;
 }
 
@@ -285,6 +299,10 @@ static int osiris_pm_resume(struct sys_device *sd)
        if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
                __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
 
+       __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
+
+       s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT);
+
        return 0;
 }
 
index b4e9b734e0bd939cddcdc392889368fe43f30846..76b800a951917d96b7aad433c344562f484743df 100644 (file)
@@ -57,7 +57,17 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
 {
        unsigned long addr;
 
-       start &= ~(CACHE_LINE_SIZE - 1);
+       if (start & (CACHE_LINE_SIZE - 1)) {
+               start &= ~(CACHE_LINE_SIZE - 1);
+               sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1);
+               start += CACHE_LINE_SIZE;
+       }
+
+       if (end & (CACHE_LINE_SIZE - 1)) {
+               end &= ~(CACHE_LINE_SIZE - 1);
+               sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1);
+       }
+
        for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
                sync_writel(addr, L2X0_INV_LINE_PA, 1);
        cache_sync();
index bafcfa52142ba0731f5caf3ecc71e672d7678285..5d488ef965ce771a95e6db2567752f10c806f052 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/err.h>
 #include <asm/blackfin.h>
 #include <asm/gpio.h>
+#include <asm/portmux.h>
 #include <linux/irq.h>
 
 #ifdef BF533_FAMILY
@@ -115,7 +116,11 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
 };
 #endif
 
-static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)];
+char *str_ident = NULL;
+
+#define RESOURCE_LABEL_SIZE 16
 
 #ifdef CONFIG_PM
 static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -143,22 +148,100 @@ inline int check_gpio(unsigned short gpio)
        return 0;
 }
 
+static void set_label(unsigned short ident, const char *label)
+{
+
+       if (label && str_ident) {
+               strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label,
+                        RESOURCE_LABEL_SIZE);
+               str_ident[ident * RESOURCE_LABEL_SIZE +
+                        RESOURCE_LABEL_SIZE - 1] = 0;
+       }
+}
+
+static char *get_label(unsigned short ident)
+{
+       if (!str_ident)
+               return "UNKNOWN";
+
+       return (str_ident[ident * RESOURCE_LABEL_SIZE] ?
+               (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN");
+}
+
+static int cmp_label(unsigned short ident, const char *label)
+{
+       if (label && str_ident)
+               return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE,
+                                label, strlen(label));
+       else
+               return -EINVAL;
+}
+
 #ifdef BF537_FAMILY
 static void port_setup(unsigned short gpio, unsigned short usage)
 {
-       if (usage == GPIO_USAGE) {
-               if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio))
-                       printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral "
-                              "usage and GPIO %d detected!\n", gpio);
-               *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
-       } else
-               *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
-       SSYNC();
+       if (!check_gpio(gpio)) {
+               if (usage == GPIO_USAGE) {
+                       *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+               } else
+                       *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
+               SSYNC();
+       }
 }
 #else
 # define port_setup(...)  do { } while (0)
 #endif
 
+#ifdef BF537_FAMILY
+
+#define PMUX_LUT_RES           0
+#define PMUX_LUT_OFFSET                1
+#define PMUX_LUT_ENTRIES       41
+#define PMUX_LUT_SIZE          2
+
+static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = {
+       {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11},
+       {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11},
+       {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10},
+       {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10},
+       {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9},
+       {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7},
+       {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5},
+       {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4},
+       {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3},
+       {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1},
+       {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1},
+       {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0},
+       {P_SPI0_SSEL3, 0}
+};
+
+static void portmux_setup(unsigned short per, unsigned short function)
+{
+       u16 y, muxreg, offset;
+
+       for (y = 0; y < PMUX_LUT_ENTRIES; y++) {
+               if (port_mux_lut[y][PMUX_LUT_RES] == per) {
+
+                       /* SET PORTMUX REG */
+
+                       offset = port_mux_lut[y][PMUX_LUT_OFFSET];
+                       muxreg = bfin_read_PORT_MUX();
+
+                       if (offset != 1) {
+                               muxreg &= ~(1 << offset);
+                       } else {
+                               muxreg &= ~(3 << 1);
+                       }
+
+                       muxreg |= (function << offset);
+                       bfin_write_PORT_MUX(muxreg);
+               }
+       }
+}
+
+#else
+# define portmux_setup(...)  do { } while (0)
+#endif
 
 static void default_gpio(unsigned short gpio)
 {
@@ -179,22 +262,15 @@ static void default_gpio(unsigned short gpio)
 
 static int __init bfin_gpio_init(void)
 {
-       int i;
-
-       printk(KERN_INFO "Blackfin GPIO Controller\n");
 
-       for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE)
-               reserved_map[gpio_bank(i)] = 0;
+       str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL);
+       if (!str_ident)
+               return -ENOMEM;
 
-#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
-# if defined(CONFIG_BFIN_MAC_RMII)
-       reserved_map[gpio_bank(PORT_H)] = 0xC373;
-# else
-       reserved_map[gpio_bank(PORT_H)] = 0xFFFF;
-# endif
-#endif
+       printk(KERN_INFO "Blackfin GPIO Controller\n");
 
        return 0;
+
 }
 
 arch_initcall(bfin_gpio_init);
@@ -223,7 +299,7 @@ arch_initcall(bfin_gpio_init);
 void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
 { \
        unsigned long flags; \
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
        local_irq_save(flags); \
        if (arg) \
                gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
@@ -243,7 +319,7 @@ SET_GPIO(both)
 #define SET_GPIO_SC(name) \
 void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
 { \
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
        if (arg) \
                gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
        else \
@@ -258,7 +334,7 @@ SET_GPIO_SC(maskb)
 void set_gpio_data(unsigned short gpio, unsigned short arg)
 {
        unsigned long flags;
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
        local_irq_save(flags);
        if (arg)
                gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
@@ -277,7 +353,7 @@ SET_GPIO_SC(data)
 void set_gpio_toggle(unsigned short gpio)
 {
        unsigned long flags;
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
        local_irq_save(flags);
        gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
        bfin_read_CHIPID();
@@ -286,7 +362,7 @@ void set_gpio_toggle(unsigned short gpio)
 #else
 void set_gpio_toggle(unsigned short gpio)
 {
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
        gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
 }
 #endif
@@ -350,7 +426,7 @@ unsigned short get_gpio_data(unsigned short gpio)
 {
        unsigned long flags;
        unsigned short ret;
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
        local_irq_save(flags);
        ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
        bfin_read_CHIPID();
@@ -494,13 +570,14 @@ u32 gpio_pm_setup(void)
                        gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
                        gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
                        gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
-                       gpio_bank_saved[bank].reserved = reserved_map[bank];
+                       gpio_bank_saved[bank].reserved =
+                                               reserved_gpio_map[bank];
 
                        gpio = i;
 
                        while (mask) {
                                if (mask & 1) {
-                                       reserved_map[gpio_bank(gpio)] |=
+                                       reserved_gpio_map[gpio_bank(gpio)] |=
                                                        gpio_bit(gpio);
                                        bfin_gpio_wakeup_type(gpio,
                                                wakeup_flags_map[gpio]);
@@ -540,7 +617,8 @@ void gpio_pm_restore(void)
                        gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
                        gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
 
-                       reserved_map[bank] = gpio_bank_saved[bank].reserved;
+                       reserved_gpio_map[bank] =
+                                       gpio_bank_saved[bank].reserved;
 
                }
 
@@ -550,6 +628,141 @@ void gpio_pm_restore(void)
 
 #endif
 
+
+
+
+int peripheral_request(unsigned short per, const char *label)
+{
+       unsigned long flags;
+       unsigned short ident = P_IDENT(per);
+
+       /*
+        * Don't cares are pins with only one dedicated function
+        */
+
+       if (per & P_DONTCARE)
+               return 0;
+
+       if (!(per & P_DEFINED))
+               return -ENODEV;
+
+       local_irq_save(flags);
+
+       if (!check_gpio(ident)) {
+
+       if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+               printk(KERN_ERR
+                      "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+                      __FUNCTION__, ident, get_label(ident));
+               dump_stack();
+               local_irq_restore(flags);
+               return -EBUSY;
+       }
+
+       }
+
+       if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+
+       /*
+        * Pin functions like AMC address strobes my
+        * be requested and used by several drivers
+        */
+
+       if (!(per & P_MAYSHARE)) {
+
+       /*
+        * Allow that the identical pin function can
+        * be requested from the same driver twice
+        */
+
+               if (cmp_label(ident, label) == 0)
+                       goto anyway;
+
+                       printk(KERN_ERR
+                              "%s: Peripheral %d function %d is already"
+                              "reserved by %s !\n",
+                              __FUNCTION__, ident, P_FUNCT2MUX(per),
+                               get_label(ident));
+                       dump_stack();
+                       local_irq_restore(flags);
+                       return -EBUSY;
+               }
+
+       }
+
+anyway:
+
+
+       portmux_setup(per, P_FUNCT2MUX(per));
+
+       port_setup(ident, PERIPHERAL_USAGE);
+
+       reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+       local_irq_restore(flags);
+       set_label(ident, label);
+
+       return 0;
+}
+EXPORT_SYMBOL(peripheral_request);
+
+int peripheral_request_list(unsigned short per[], const char *label)
+{
+       u16 cnt;
+       int ret;
+
+       for (cnt = 0; per[cnt] != 0; cnt++) {
+               ret = peripheral_request(per[cnt], label);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(peripheral_request_list);
+
+void peripheral_free(unsigned short per)
+{
+       unsigned long flags;
+       unsigned short ident = P_IDENT(per);
+
+       if (per & P_DONTCARE)
+               return;
+
+       if (!(per & P_DEFINED))
+               return;
+
+       if (check_gpio(ident) < 0)
+               return;
+
+       local_irq_save(flags);
+
+       if (unlikely(!(reserved_peri_map[gpio_bank(ident)]
+                        & gpio_bit(ident)))) {
+               local_irq_restore(flags);
+               return;
+       }
+
+       if (!(per & P_MAYSHARE)) {
+               port_setup(ident, GPIO_USAGE);
+       }
+
+       reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(peripheral_free);
+
+void peripheral_free_list(unsigned short per[])
+{
+       u16 cnt;
+
+       for (cnt = 0; per[cnt] != 0; cnt++) {
+               peripheral_free(per[cnt]);
+       }
+
+}
+EXPORT_SYMBOL(peripheral_free_list);
+
 /***********************************************************
 *
 * FUNCTIONS: Blackfin GPIO Driver
@@ -574,13 +787,13 @@ int gpio_request(unsigned short gpio, const char *label)
 
        local_irq_save(flags);
 
-       if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+       if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
                dump_stack();
                local_irq_restore(flags);
                return -EBUSY;
        }
-       reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+       reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
 
        local_irq_restore(flags);
 
@@ -599,7 +812,7 @@ void gpio_free(unsigned short gpio)
 
        local_irq_save(flags);
 
-       if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+       if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
                printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
                dump_stack();
                local_irq_restore(flags);
@@ -608,7 +821,7 @@ void gpio_free(unsigned short gpio)
 
        default_gpio(gpio);
 
-       reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+       reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
 
        local_irq_restore(flags);
 }
@@ -618,7 +831,7 @@ void gpio_direction_input(unsigned short gpio)
 {
        unsigned long flags;
 
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
 
        local_irq_save(flags);
        gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
@@ -631,7 +844,7 @@ void gpio_direction_output(unsigned short gpio)
 {
        unsigned long flags;
 
-       BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+       BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
 
        local_irq_save(flags);
        gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
index d61bba98fb548b8baf63980e11aca302902419d4..9604588083446d6c866595e4336d0e63fc6c7b97 100644 (file)
@@ -815,7 +815,7 @@ _extable:
 
 ALIGN
 ENTRY(_sys_call_table)
-       .long _sys_ni_syscall   /* 0  -  old "setup()" system call*/
+       .long _sys_restart_syscall      /* 0 */
        .long _sys_exit
        .long _sys_fork
        .long _sys_read
@@ -978,13 +978,13 @@ ENTRY(_sys_call_table)
        .long _sys_sched_get_priority_min  /* 160 */
        .long _sys_sched_rr_get_interval
        .long _sys_nanosleep
-       .long _sys_ni_syscall   /* sys_mremap */
+       .long _sys_mremap
        .long _sys_setresuid    /* setresuid16 */
        .long _sys_getresuid    /* getresuid16 */       /* 165 */
        .long _sys_ni_syscall   /* for vm86 */
        .long _sys_ni_syscall   /* old "query_module" */
        .long _sys_ni_syscall   /* sys_poll */
-       .long _sys_ni_syscall   /* sys_nfsservctl */
+       .long _sys_nfsservctl
        .long _sys_setresgid    /* setresgid16 */       /* 170 */
        .long _sys_getresgid    /* getresgid16 */
        .long _sys_prctl
@@ -1040,7 +1040,7 @@ ENTRY(_sys_call_table)
        .long _sys_ni_syscall   /* reserved for TUX */
        .long _sys_ni_syscall
        .long _sys_gettid
-       .long _sys_ni_syscall   /* 225 */ /* sys_readahead */
+       .long _sys_readahead    /* 225 */
        .long _sys_setxattr
        .long _sys_lsetxattr
        .long _sys_fsetxattr
@@ -1157,6 +1157,21 @@ ENTRY(_sys_call_table)
        .long _sys_shmctl
        .long _sys_shmdt        /* 340 */
        .long _sys_shmget
+       .long _sys_splice
+       .long _sys_sync_file_range
+       .long _sys_tee
+       .long _sys_vmsplice     /* 345 */
+       .long _sys_epoll_pwait
+       .long _sys_utimensat
+       .long _sys_signalfd
+       .long _sys_timerfd
+       .long _sys_eventfd      /* 350 */
+       .long _sys_pread64
+       .long _sys_pwrite64
+       .long _sys_fadvise64
+       .long _sys_set_robust_list
+       .long _sys_get_robust_list      /* 355 */
+       .long _sys_fallocate
        .rept NR_syscalls-(.-_sys_call_table)/4
        .long _sys_ni_syscall
        .endr
index 7f4a2c53bd762b91746216ac44cbe957d938fa33..f3140e596d407d892eb75aa0c486bd7411e1dcb2 100644 (file)
@@ -275,7 +275,7 @@ die:
        hlt
        jmp     die
 
-       .size   die, .-due
+       .size   die, .-die
 
        .section ".initdata", "a"
 setup_corrupt:
index 1a2e62db8bed48df0e613066c9efb69f2509d0e0..378353956b5dfc86469b66419b9680e1770a7410 100644 (file)
@@ -20,6 +20,7 @@
 
 static int detect_memory_e820(void)
 {
+       int count = 0;
        u32 next = 0;
        u32 size, id;
        u8 err;
@@ -27,20 +28,33 @@ static int detect_memory_e820(void)
 
        do {
                size = sizeof(struct e820entry);
-               id = SMAP;
+
+               /* Important: %edx is clobbered by some BIOSes,
+                  so it must be either used for the error output
+                  or explicitly marked clobbered. */
                asm("int $0x15; setc %0"
-                   : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
+                   : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
                      "=m" (*desc)
-                   : "D" (desc), "a" (0xe820));
+                   : "D" (desc), "d" (SMAP), "a" (0xe820));
+
+               /* Some BIOSes stop returning SMAP in the middle of
+                  the search loop.  We don't know exactly how the BIOS
+                  screwed up the map at that point, we might have a
+                  partial map, the full map, or complete garbage, so
+                  just return failure. */
+               if (id != SMAP) {
+                       count = 0;
+                       break;
+               }
 
-               if (err || id != SMAP)
+               if (err)
                        break;
 
-               boot_params.e820_entries++;
+               count++;
                desc++;
-       } while (next && boot_params.e820_entries < E820MAX);
+       } while (next && count < E820MAX);
 
-       return boot_params.e820_entries;
+       return boot_params.e820_entries = count;
 }
 
 static int detect_memory_e801(void)
@@ -89,11 +103,16 @@ static int detect_memory_88(void)
 
 int detect_memory(void)
 {
+       int err = -1;
+
        if (detect_memory_e820() > 0)
-               return 0;
+               err = 0;
 
        if (!detect_memory_e801())
-               return 0;
+               err = 0;
+
+       if (!detect_memory_88())
+               err = 0;
 
-       return detect_memory_88();
+       return err;
 }
index 693f20d3102e9322759adca6834f2de4e159d0a1..e4ba897bf9a3748c89e442141887ea9e0dbba721 100644 (file)
@@ -147,7 +147,7 @@ int mode_defined(u16 mode)
 }
 
 /* Set mode (without recalc) */
-static int raw_set_mode(u16 mode)
+static int raw_set_mode(u16 mode, u16 *real_mode)
 {
        int nmode, i;
        struct card_info *card;
@@ -165,8 +165,10 @@ static int raw_set_mode(u16 mode)
 
                        if ((mode == nmode && visible) ||
                            mode == mi->mode ||
-                           mode == (mi->y << 8)+mi->x)
+                           mode == (mi->y << 8)+mi->x) {
+                               *real_mode = mi->mode;
                                return card->set_mode(mi);
+                       }
 
                        if (visible)
                                nmode++;
@@ -178,7 +180,7 @@ static int raw_set_mode(u16 mode)
                if (mode >= card->xmode_first &&
                    mode < card->xmode_first+card->xmode_n) {
                        struct mode_info mix;
-                       mix.mode = mode;
+                       *real_mode = mix.mode = mode;
                        mix.x = mix.y = 0;
                        return card->set_mode(&mix);
                }
@@ -223,6 +225,7 @@ static void vga_recalc_vertical(void)
 static int set_mode(u16 mode)
 {
        int rv;
+       u16 real_mode;
 
        /* Very special mode numbers... */
        if (mode == VIDEO_CURRENT_MODE)
@@ -232,13 +235,16 @@ static int set_mode(u16 mode)
        else if (mode == EXTENDED_VGA)
                mode = VIDEO_8POINT;
 
-       rv = raw_set_mode(mode);
+       rv = raw_set_mode(mode, &real_mode);
        if (rv)
                return rv;
 
        if (mode & VIDEO_RECALC)
                vga_recalc_vertical();
 
+       /* Save the canonical mode number for the kernel, not
+          an alias, size specification or menu position */
+       boot_params.hdr.vid_mode = real_mode;
        return 0;
 }
 
index ed0a0f2c1597a8b739f28081850c3f8b5b8c6248..f22ba8534d26ee19488753eacd2e1057ab841a33 100644 (file)
@@ -151,51 +151,30 @@ bogus_real_magic:
 #define VIDEO_FIRST_V7 0x0900
 
 # Setting of user mode (AX=mode ID) => CF=success
+
+# For now, we only handle VESA modes (0x0200..0x03ff).  To handle other
+# modes, we should probably compile in the video code from the boot
+# directory.
 mode_set:
        movw    %ax, %bx
-#if 0
-       cmpb    $0xff, %ah
-       jz      setalias
-
-       testb   $VIDEO_RECALC>>8, %ah
-       jnz     _setrec
-
-       cmpb    $VIDEO_FIRST_RESOLUTION>>8, %ah
-       jnc     setres
-       
-       cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
-       jz      setspc
-
-       cmpb    $VIDEO_FIRST_V7>>8, %ah
-       jz      setv7
-#endif
-       
-       cmpb    $VIDEO_FIRST_VESA>>8, %ah
-       jnc     check_vesa
-#if 0  
-       orb     %ah, %ah
-       jz      setmenu
-#endif
-       
-       decb    %ah
-#      jz      setbios                           Add bios modes later
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       cmpb    $2, %bh
+       jb      check_vesa
 
-setbad:        clc
+setbad:
+       clc
        ret
 
 check_vesa:
-       subb    $VIDEO_FIRST_VESA>>8, %bh
        orw     $0x4000, %bx                    # Use linear frame buffer
        movw    $0x4f02, %ax                    # VESA BIOS mode set call
        int     $0x10
        cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     _setbad                         # AH=0 if OK
+       jnz     setbad                          # AH=0 if OK
 
        stc
        ret
 
-_setbad: jmp setbad
-
        .code32
        ALIGN
 
index ef8f0bc3fc71bd2b7ebdd936cd09960592af5870..f0cce3c2dc3a4fe33916f2c1ff5c34bae77237e6 100644 (file)
@@ -76,6 +76,7 @@ static unsigned int longhaul_index;
 /* Module parameters */
 static int scale_voltage;
 static int disable_acpi_c3;
+static int revid_errata;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
@@ -168,7 +169,10 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
 
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        /* Setup new frequency */
-       longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+       if (!revid_errata)
+               longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+       else
+               longhaul.bits.RevisionKey = 0;
        longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
        longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
        /* Setup new voltage */
@@ -272,7 +276,7 @@ static void longhaul_setstate(unsigned int table_index)
 
        dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
                        fsb, mult/10, mult%10, print_speed(speed/1000));
-
+retry_loop:
        preempt_disable();
        local_irq_save(flags);
 
@@ -344,6 +348,47 @@ static void longhaul_setstate(unsigned int table_index)
        preempt_enable();
 
        freqs.new = calc_speed(longhaul_get_cpu_mult());
+       /* Check if requested frequency is set. */
+       if (unlikely(freqs.new != speed)) {
+               printk(KERN_INFO PFX "Failed to set requested frequency!\n");
+               /* Revision ID = 1 but processor is expecting revision key
+                * equal to 0. Jumpers at the bottom of processor will change
+                * multiplier and FSB, but will not change bits in Longhaul
+                * MSR nor enable voltage scaling. */
+               if (!revid_errata) {
+                       printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" "
+                                               "option.\n");
+                       revid_errata = 1;
+                       msleep(200);
+                       goto retry_loop;
+               }
+               /* Why ACPI C3 sometimes doesn't work is a mystery for me.
+                * But it does happen. Processor is entering ACPI C3 state,
+                * but it doesn't change frequency. I tried poking various
+                * bits in northbridge registers, but without success. */
+               if (longhaul_flags & USE_ACPI_C3) {
+                       printk(KERN_INFO PFX "Disabling ACPI C3 support.\n");
+                       longhaul_flags &= ~USE_ACPI_C3;
+                       if (revid_errata) {
+                               printk(KERN_INFO PFX "Disabling \"Ignore "
+                                               "Revision ID\" option.\n");
+                               revid_errata = 0;
+                       }
+                       msleep(200);
+                       goto retry_loop;
+               }
+               /* This shouldn't happen. Longhaul ver. 2 was reported not
+                * working on processors without voltage scaling, but with
+                * RevID = 1. RevID errata will make things right. Just
+                * to be 100% sure. */
+               if (longhaul_version == TYPE_LONGHAUL_V2) {
+                       printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n");
+                       longhaul_version = TYPE_LONGHAUL_V1;
+                       msleep(200);
+                       goto retry_loop;
+               }
+       }
+       /* Report true CPU frequency */
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
        if (!bm_timeout)
@@ -956,11 +1001,20 @@ static void __exit longhaul_exit(void)
        kfree(longhaul_table);
 }
 
+/* Even if BIOS is exporting ACPI C3 state, and it is used
+ * with success when CPU is idle, this state doesn't
+ * trigger frequency transition in some cases. */
 module_param (disable_acpi_c3, int, 0644);
 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
-
+/* Change CPU voltage with frequency. Very usefull to save
+ * power, but most VIA C3 processors aren't supporting it. */
 module_param (scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
+/* Force revision key to 0 for processors which doesn't
+ * support voltage scaling, but are introducing itself as
+ * such. */
+module_param(revid_errata, int, 0644);
+MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
 
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
index f0c37511d8da82d6e30650a6d7f0cc6cbd6dd368..f01bfcd4bdee4c63059ff2a2fd9f8ec4b1b0d1e1 100644 (file)
@@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void)
 
 static void xen_write_cr4(unsigned long cr4)
 {
-       /* never allow TSC to be disabled */
-       native_write_cr4(cr4 & ~X86_CR4_TSD);
+       /* Just ignore cr4 changes; Xen doesn't allow us to do
+          anything anyway. */
 }
 
 static unsigned long xen_read_cr3(void)
index 4ae038aa6c244b91ac0d244f84c62ade47fee424..874db0cd1d2a5f6fc1c9f9a172863edb9c260339 100644 (file)
@@ -559,6 +559,9 @@ void xen_exit_mmap(struct mm_struct *mm)
        put_cpu();
 
        spin_lock(&mm->page_table_lock);
-       xen_pgd_unpin(mm->pgd);
+
+       /* pgd may not be pinned in the error exit path of execve */
+       if (PagePinned(virt_to_page(mm->pgd)))
+               xen_pgd_unpin(mm->pgd);
        spin_unlock(&mm->page_table_lock);
 }
index 6c25e6c09f7835ed4c3183b316e157d86d2db174..9be99a68932aca8c83d7aba6b548a1b161b4a531 100644 (file)
@@ -74,6 +74,7 @@ static int __init au1x_pci_setup(void)
                printk(KERN_ERR "Unable to ioremap pci space\n");
                return 1;
        }
+       au1x_controller.io_map_base = virt_io_addr;
 
 #ifdef CONFIG_DMA_NONCOHERENT
        {
index 7bc5af8917dafacde69719fa6fafb14ff0eed8d1..2c460c1165700eaa7cdd020d291a1015d1196e84 100644 (file)
@@ -54,11 +54,11 @@ void board_reset (void)
 
 void __init board_setup(void)
 {
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        // enable USB power switch
        au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR );
        au_writel( 0x100000, GPIO2_OUTPUT );
-#endif // defined (CONFIG_USB_OHCI)
+#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 #ifdef CONFIG_PCI
 #if defined(__MIPSEB__)
index 824cfafaff92ad8ac32217601a79cf43ca05423b..0aed89114bfcf9e8ab411bb071f1f6c65e32736e 100644 (file)
@@ -54,7 +54,7 @@ void __init board_setup(void)
        au_writel(0, SYS_PINSTATERD);
        udelay(100);
 
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        /* zero and disable FREQ2 */
        sys_freqctrl = au_readl(SYS_FREQCTRL0);
        sys_freqctrl &= ~0xFFF00000;
@@ -102,7 +102,7 @@ void __init board_setup(void)
        /*
         * Route 48MHz FREQ2 into USB Host and/or Device
         */
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
 #endif
        au_writel(sys_clksrc, SYS_CLKSRC);
@@ -116,7 +116,7 @@ void __init board_setup(void)
        au_writel(pin_func, SYS_PINFUNC);
        au_writel(0x2800, SYS_TRIOUTCLR);
        au_writel(0x0030, SYS_OUTPUTCLR);
-#endif // defined (CONFIG_USB_OHCI)
+#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
        // make gpio 15 an input (for interrupt line)
        pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
index 6bc1f8e1b608175b431f6927d47aa42558d8f1cc..259ca05860c32a8844636407dd5290ac9092a6f0 100644 (file)
@@ -54,7 +54,7 @@ void __init board_setup(void)
        au_writel(0, SYS_PININPUTEN);
        udelay(100);
 
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        {
                u32 pin_func, sys_freqctrl, sys_clksrc;
 
@@ -98,7 +98,7 @@ void __init board_setup(void)
                pin_func |= 0x8000;
                au_writel(pin_func, SYS_PINFUNC);
        }
-#endif // defined (CONFIG_USB_OHCI)
+#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
        /* Enable sys bus clock divider when IDLE state or no bus activity. */
        au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
index c9b655616fb38f38ebd656242cb1a9c84f287e22..a2d850db8902d1d6eae89d8eead76eb31af7a597 100644 (file)
@@ -56,7 +56,7 @@ void __init board_setup(void)
        au_writel(0, SYS_PINSTATERD);
        udelay(100);
 
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 
        /* GPIO201 is input for PCMCIA card detect */
        /* GPIO203 is input for PCMCIA interrupt request */
@@ -85,7 +85,7 @@ void __init board_setup(void)
        /*
         * Route 48MHz FREQ2 into USB Host and/or Device
         */
-#ifdef CONFIG_USB_OHCI
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
 #endif
        au_writel(sys_clksrc, SYS_CLKSRC);
@@ -95,7 +95,7 @@ void __init board_setup(void)
        // 2nd USB port is USB host
        pin_func |= 0x8000;
        au_writel(pin_func, SYS_PINFUNC);
-#endif // defined (CONFIG_USB_OHCI)
+#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 
 
index b8a5e75ba0ab4b6bce2bc979a8c7527f050c571d..3e634f2f5443585c98a6f360ac595b7f3774d6d2 100644 (file)
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
 
 int dec_tc_bus;
 
-spinlock_t ioasic_ssr_lock;
+DEFINE_SPINLOCK(ioasic_ssr_lock);
 
 volatile u32 *ioasic_base;
 
index ac04f0adc408b45548cc9bd720797d29dec94878..6648fde20b965d839a7e9978ff830662dc5c0d92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2004  Maciej W. Rozycki
+ * Copyright (C) 2003, 2004, 2007  Maciej W. Rozycki
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,7 +29,7 @@ static inline void align_mod(const int align, const int mod)
                ".endr\n\t"
                ".set   pop"
                :
-               : "rn" (align), "rn" (mod));
+               : GCC_IMM_ASM (align), GCC_IMM_ASM (mod));
 }
 
 static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
index b6c30800c66774170f719bba39948613a7a118c3..3a2d255361bcc364031652eb02261a57994bd0db 100644 (file)
@@ -177,10 +177,7 @@ handle_real_irq:
                outb(cached_master_mask, PIC_MASTER_IMR);
                outb(0x60+irq,PIC_MASTER_CMD);  /* 'Specific EOI to master */
        }
-#ifdef CONFIG_MIPS_MT_SMTC
-       if (irq_hwmask[irq] & ST0_IM)
-               set_c0_status(irq_hwmask[irq] & ST0_IM);
-#endif /* CONFIG_MIPS_MT_SMTC */
+       smtc_im_ack_irq(irq);
        spin_unlock_irqrestore(&i8259A_lock, flags);
        return;
 
index 410868b5ea5f499df73f497f104edb33405cbb02..1ecdd50bfc60333a82d2b60fba9181967a1ae277 100644 (file)
@@ -52,11 +52,8 @@ static void level_mask_and_ack_msc_irq(unsigned int irq)
        mask_msc_irq(irq);
        if (!cpu_has_veic)
                MSCIC_WRITE(MSC01_IC_EOI, 0);
-#ifdef CONFIG_MIPS_MT_SMTC
        /* This actually needs to be a call into platform code */
-       if (irq_hwmask[irq] & ST0_IM)
-               set_c0_status(irq_hwmask[irq] & ST0_IM);
-#endif /* CONFIG_MIPS_MT_SMTC */
+       smtc_im_ack_irq(irq);
 }
 
 /*
@@ -73,10 +70,7 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq)
                MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
                MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
        }
-#ifdef CONFIG_MIPS_MT_SMTC
-       if (irq_hwmask[irq] & ST0_IM)
-               set_c0_status(irq_hwmask[irq] & ST0_IM);
-#endif /* CONFIG_MIPS_MT_SMTC */
+       smtc_im_ack_irq(irq);
 }
 
 /*
index aeded6c17de52af0ed308cacd953aa3936363f14..a990aad2f0492746375f06ee6f932a2643b4597a 100644 (file)
@@ -74,20 +74,12 @@ EXPORT_SYMBOL_GPL(free_irqno);
  */
 void ack_bad_irq(unsigned int irq)
 {
+       smtc_im_ack_irq(irq);
        printk("unexpected IRQ # %d\n", irq);
 }
 
 atomic_t irq_err_count;
 
-#ifdef CONFIG_MIPS_MT_SMTC
-/*
- * SMTC Kernel needs to manipulate low-level CPU interrupt mask
- * in do_IRQ. These are passed in setup_irq_smtc() and stored
- * in this table.
- */
-unsigned long irq_hwmask[NR_IRQS];
-#endif /* CONFIG_MIPS_MT_SMTC */
-
 /*
  * Generic, controller-independent functions:
  */
index b3ed731a24c6ad41c293101826f56958a8d4d7ca..dd68afce7da5782dc0f59766b04eb3afcb7eb647 100644 (file)
@@ -525,5 +525,5 @@ sys_call_table:
        PTR     compat_sys_signalfd
        PTR     compat_sys_timerfd
        PTR     sys_eventfd
-       PTR     sys_fallocate                   /* 4320 */
+       PTR     sys32_fallocate                 /* 4320 */
        .size   sys_call_table,.-sys_call_table
index 43826c16101d15ee3f556c67e055749cfb7fcce4..f09404377ef18397840c6dba44f4cd00449b8493 100644 (file)
 #include <asm/smtc_proc.h>
 
 /*
- * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
  */
+unsigned long irq_hwmask[NR_IRQS];
 
 #define LOCK_MT_PRA() \
        local_irq_save(flags); \
index 60bbaecde1873d8d653664351692ca93576be2e5..087ab997487d9f766f3e4d1e088a63a9a09a62fb 100644 (file)
@@ -45,6 +45,8 @@ SECTIONS
   __dbe_table : { *(__dbe_table) }
   __stop___dbe_table = .;
 
+  NOTES
+
   RODATA
 
   /* writeable */
index dc795be62807d1d1bf22af966ad961d0918794bf..e47e9e9486bf962cef8e44aa4d265a875c6f94d0 100644 (file)
@@ -209,7 +209,7 @@ static inline void build_cdex_p(void)
        }
 
        if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
-               build_insn_word(0x3c01a000);    /* lui     $at, 0xa000  */
+               build_insn_word(0x8c200000);    /* lw      $zero, ($at) */
 
        mi.c_format.opcode     = cache_op;
        mi.c_format.rs         = 4;             /* $a0 */
index 8008e31c5e81ce3ff17adac4aef6c98655c9182b..fe54514493044d8a9c70d9686518617531838d23 100644 (file)
  * 4  N/C
  */
 
-#define chkslot(_bus,_devfn)                                   \
-do {                                                           \
-       if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \
-           || PCI_SLOT (_devfn) > 3)                           \
-               return PCIBIOS_DEVICE_NOT_FOUND;                \
-} while (0)
+static inline int mkaddr(struct pci_bus *bus, unsigned int devfn,
+       unsigned int reg)
+{
+       return ((bus->number & 0xff) << 16) |
+               ((devfn & 0xff) << 8) |
+               (reg & 0xfc);
+}
 
-#define mkaddr(_devfn, _reg) \
-((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL))
 
 static int
 mace_pci_read_config(struct pci_bus *bus, unsigned int devfn,
                     int reg, int size, u32 *val)
 {
-       chkslot(bus, devfn);
-       mace->pci.config_addr = mkaddr(devfn, reg);
+       mace->pci.config_addr = mkaddr(bus, devfn, reg);
        switch (size) {
        case 1:
                *val = mace->pci.config_data.b[(reg & 3) ^ 3];
@@ -66,8 +64,7 @@ static int
 mace_pci_write_config(struct pci_bus *bus, unsigned int devfn,
                      int reg, int size, u32 val)
 {
-       chkslot(bus, devfn);
-       mace->pci.config_addr = mkaddr(devfn, reg);
+       mace->pci.config_addr = mkaddr(bus, devfn, reg);
        switch (size) {
        case 1:
                mace->pci.config_data.b[(reg & 3) ^ 3] = val;
index ba3697ee7ff65ecc70bf15f30653fa54a5cc63b9..7309e48d163d1535facc87aef51ee4608ed3f3fc 100644 (file)
@@ -41,8 +41,8 @@ static struct platform_device uart8250_device = {
 
 static int __init uart8250_init(void)
 {
-       uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1;
-       uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1;
+       uart8250_data[0].membase = (void __iomem *) &mace->isa.serial1;
+       uart8250_data[1].membase = (void __iomem *) &mace->isa.serial1;
 
        return platform_device_register(&uart8250_device);
 }
index bb28f28e8042254da6c19bbd6ece9da20bba8de8..7e1aa348b8e078d41302a86979789f654eaf33f3 100644 (file)
@@ -15,6 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/reboot.h>
@@ -35,6 +36,7 @@ unsigned int soc_type;
 EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
 unsigned int zbbus_mhz;
+EXPORT_SYMBOL(zbbus_mhz);
 
 static unsigned int part_type;
 
index 502f47c01797215f80fb2f8cef3938c152a149c5..44c065a6b5e71a2ea1fe318a5062a2d8d79f3ff8 100644 (file)
@@ -99,6 +99,7 @@
                        #size-cells = <0>;
                        interrupt-parent = < &ipic >;
                        interrupts = <26 8>;
+                       dr_mode = "peripheral";
                        phy_type = "ulpi";
                };
 
index e477c9d0498bed92efd0ebad78db4db4187afd9f..8a1b001d0b110fa5a31a3fb53ed215312680f04c 100644 (file)
@@ -605,6 +605,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
        regs->ccr = 0;
        regs->gpr[1] = sp;
 
+       /*
+        * We have just cleared all the nonvolatile GPRs, so make
+        * FULL_REGS(regs) return true.  This is necessary to allow
+        * ptrace to examine the thread immediately after exec.
+        */
+       regs->trap &= ~1UL;
+
 #ifdef CONFIG_PPC32
        regs->mq = 0;
        regs->nip = start;
index 727a6699f2f41c36ffaac9a205a1aaf3405ec554..c627cf86d1e3d1c7ae4501cdb1057f8d81522f25 100644 (file)
@@ -239,7 +239,7 @@ static void snapshot_tb_and_purr(void *data)
        struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
 
        local_irq_save(flags);
-       p->tb = mftb();
+       p->tb = get_tb_or_rtc();
        p->purr = mfspr(SPRN_PURR);
        wmb();
        p->initialized = 1;
@@ -317,7 +317,7 @@ static void snapshot_purr(void)
  */
 void snapshot_timebase(void)
 {
-       __get_cpu_var(last_jiffy) = get_tb();
+       __get_cpu_var(last_jiffy) = get_tb_or_rtc();
        snapshot_purr();
 }
 
@@ -684,6 +684,8 @@ void timer_interrupt(struct pt_regs * regs)
 
                write_seqlock(&xtime_lock);
                tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
+               if (__USE_RTC() && tb_next_jiffy >= 1000000000)
+                       tb_next_jiffy -= 1000000000;
                if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
                        tb_last_jiffy = tb_next_jiffy;
                        do_timer(1);
@@ -977,7 +979,7 @@ void __init time_init(void)
        tb_to_ns_scale = scale;
        tb_to_ns_shift = shift;
        /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
-       boot_tb = get_tb();
+       boot_tb = get_tb_or_rtc();
 
        tm = get_boot_time();
 
index cef01e4e898916483f289238e7d4bc3ac79c59bb..213fa31ac53785155b4293536b198437e6457182 100644 (file)
@@ -98,6 +98,18 @@ static struct vdso_patch_def vdso_patches[] = {
                CPU_FTR_USE_TB, 0,
                "__kernel_gettimeofday", NULL
        },
+       {
+               CPU_FTR_USE_TB, 0,
+               "__kernel_clock_gettime", NULL
+       },
+       {
+               CPU_FTR_USE_TB, 0,
+               "__kernel_clock_getres", NULL
+       },
+       {
+               CPU_FTR_USE_TB, 0,
+               "__kernel_get_tbfreq", NULL
+       },
 };
 
 /*
index e7fdf013cd393b59ddd74cad96a91096f424a183..eafe7605cdaca6f3d10b8966c8682ceeec0167c3 100644 (file)
@@ -76,14 +76,14 @@ int mpc834x_usb_cfg(void)
                        if (port0_is_dr)
                                printk(KERN_WARNING
                                        "834x USB port0 can't be used by both DR and MPH!\n");
-                       sicrl |= MPC834X_SICRL_USB0;
+                       sicrl &= ~MPC834X_SICRL_USB0;
                }
                prop = of_get_property(np, "port1", NULL);
                if (prop) {
                        if (port1_is_dr)
                                printk(KERN_WARNING
                                        "834x USB port1 can't be used by both DR and MPH!\n");
-                       sicrl |= MPC834X_SICRL_USB1;
+                       sicrl &= ~MPC834X_SICRL_USB1;
                }
                of_node_put(np);
        }
index 4100ddc52f0227fb0fcb300fb50da78bffa9b9d3..7de4e919687b48b717bdb6001f30c088cfe49997 100644 (file)
@@ -2177,8 +2177,8 @@ struct tree_descr spufs_dir_contents[] = {
        { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
        { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
        { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
-       { "signal1", &spufs_signal1_nosched_fops, 0222, },
-       { "signal2", &spufs_signal2_nosched_fops, 0222, },
+       { "signal1", &spufs_signal1_fops, 0666, },
+       { "signal2", &spufs_signal2_fops, 0666, },
        { "signal1_type", &spufs_signal1_type, 0666, },
        { "signal2_type", &spufs_signal2_type, 0666, },
        { "cntl", &spufs_cntl_fops,  0666, },
index c784edd40ea748c74518d0d4bf9d7e4ac1ce4636..5bebe7fbe056de17a39a8b78d419f67580735f74 100644 (file)
@@ -579,7 +579,7 @@ static struct spu *find_victim(struct spu_context *ctx)
                list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
                        struct spu_context *tmp = spu->ctx;
 
-                       if (tmp->prio > ctx->prio &&
+                       if (tmp && tmp->prio > ctx->prio &&
                            (!victim || tmp->prio > victim->prio))
                                victim = spu->ctx;
                }
@@ -611,9 +611,9 @@ static struct spu *find_victim(struct spu_context *ctx)
 
                        mutex_lock(&cbe_spu_info[node].list_mutex);
                        cbe_spu_info[node].nr_active--;
+                       spu_unbind_context(spu, victim);
                        mutex_unlock(&cbe_spu_info[node].list_mutex);
 
-                       spu_unbind_context(spu, victim);
                        victim->stats.invol_ctx_switch++;
                        spu->stats.invol_ctx_switch++;
                        mutex_unlock(&victim->state_mutex);
index 5bd90a7eb763327e06300d7dd51aef3eb6ff4123..f0b5ff17d8609a83b2f68ed928111e13f0daf046 100644 (file)
@@ -419,7 +419,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
         * For the moment only implement delivery to all cpus or one cpu.
         * Get current irq_server for the given irq
         */
-       irq_server = get_irq_server(irq, 1);
+       irq_server = get_irq_server(virq, 1);
        if (irq_server == -1) {
                char cpulist[128];
                cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
index 4f67b89ba1d0a0bcf532229b8027962ccce93a95..dd5417aec1b456db3fe29024eee35e7fece31167 100644 (file)
@@ -395,4 +395,4 @@ uint cpm_dpram_phys(u8* addr)
 {
        return (dpram_pbase + (uint)(addr - dpram_vbase));
 }
-EXPORT_SYMBOL(cpm_dpram_addr);
+EXPORT_SYMBOL(cpm_dpram_phys);
index 7088428e1fe22e32e9abd27bbb015b5639123d6c..9da880be4dc0f408df58f39c1424b0eee31117f4 100644 (file)
@@ -459,7 +459,7 @@ EXPORT_SYMBOL(cpm_dpdump);
 
 void *cpm_dpram_addr(unsigned long offset)
 {
-       return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset;
+       return (void *)(dpram_vbase + offset);
 }
 EXPORT_SYMBOL(cpm_dpram_addr);
 
index e2d02fd13f35f6284d7f54fe4352d60b9279dd12..d850785b20808716b5d843af7877712db1b9dc7d 100644 (file)
@@ -156,6 +156,8 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d
        dev->prom_node = dp;
 
        regs = of_get_property(dp, "reg", &len);
+       if (!regs)
+               len = 0;
        if (len % sizeof(struct linux_prom_registers)) {
                prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
                            dev->prom_node->name, len,
index f205fc7cbcd0da686c38f732be25bf52740ee58d..d208cc7804f234583fc8e457f871a96610dfede6 100644 (file)
@@ -177,7 +177,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr
                        get_user(c,p++);
                } while (c);
        }
-       put_user(NULL,argv);
+       put_user(0,argv);
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
        while (envc-->0) {
                char c;
@@ -186,7 +186,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr
                        get_user(c,p++);
                } while (c);
        }
-       put_user(NULL,envp);
+       put_user(0,envp);
        current->mm->env_end = (unsigned long) p;
        return sp;
 }
index bc9ae36f7a43cd1de77cf6469762f21fc4ce6bd3..04ab81cb4f483f24e78c6d74c40e044d29383203 100644 (file)
@@ -375,7 +375,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
                dev->num_addrs = 0;
                dev->num_irqs = 0;
        } else {
-               (void) of_get_property(dp, "reg", &len);
+               const int *regs = of_get_property(dp, "reg", &len);
+
+               if (!regs)
+                       len = 0;
                dev->num_addrs = len / sizeof(struct linux_prom_registers);
 
                for (i = 0; i < dev->num_addrs; i++)
index 2f61c4b1259606ee45ab004cd8e10d91bcb3b5ae..c76bfbb7da085cd5538391713c13e9b86f9ed148 100644 (file)
@@ -264,7 +264,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
        unsigned int func = PCI_FUNC(devfn);
        unsigned long ret;
 
-       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+       if (!bus && devfn == 0x00)
                return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
                                                    size, value);
        if (config_out_of_range(pbm, bus, devfn, where)) {
@@ -300,7 +300,7 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
        unsigned int func = PCI_FUNC(devfn);
        unsigned long ret;
 
-       if (bus_dev == pbm->pci_bus && devfn == 0x00)
+       if (!bus && devfn == 0x00)
                return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
                                                     size, value);
        if (config_out_of_range(pbm, bus, devfn, where)) {
index 0614dff63d7c095b0e80711f09b336583439c0df..a246e962e5a73591d546d8d6c7ac2f950ad075d4 100644 (file)
@@ -1046,7 +1046,8 @@ static void __init irq_trans_init(struct device_node *dp)
        if (!strcmp(dp->name, "fhc") &&
            !strcmp(dp->parent->name, "central"))
                return central_irq_trans_init(dp);
-       if (!strcmp(dp->name, "virtual-devices"))
+       if (!strcmp(dp->name, "virtual-devices") ||
+           !strcmp(dp->name, "niu"))
                return sun4v_vdev_irq_trans_init(dp);
 }
 
index b84c49e3697c608c826c529739328ae633a860a8..c73b7a48b0369ae970edf7d103672621eacb2e21 100644 (file)
@@ -353,6 +353,8 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
        int timeout, ret;
 
        p = fork_idle(cpu);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
        callin_flag = 0;
        cpu_new_thread = task_thread_info(p);
 
index 1550ac5673da99d4db56bd76c6afb9f9664ad726..0c1ee619d814c1f1e2330ef276c6271356fbe5c5 100644 (file)
@@ -292,7 +292,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
        }
        vdev->dp = dp;
 
-       printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id);
+       printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id);
 
        err = device_register(&vdev->dev);
        if (err) {
@@ -342,8 +342,33 @@ static struct mdesc_notifier_client vio_device_notifier = {
        .node_name      = "virtual-device-port",
 };
 
+/* We are only interested in domain service ports under the
+ * "domain-services" node.  On control nodes there is another port
+ * under "openboot" that we should not mess with as aparently that is
+ * reserved exclusively for OBP use.
+ */
+static void vio_add_ds(struct mdesc_handle *hp, u64 node)
+{
+       int found;
+       u64 a;
+
+       found = 0;
+       mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
+               u64 target = mdesc_arc_target(hp, a);
+               const char *name = mdesc_node_name(hp, target);
+
+               if (!strcmp(name, "domain-services")) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found)
+               (void) vio_create_one(hp, node, &root_vdev->dev);
+}
+
 static struct mdesc_notifier_client vio_ds_notifier = {
-       .add            = vio_add,
+       .add            = vio_add_ds,
        .remove         = vio_remove,
        .node_name      = "domain-services-port",
 };
index 2d93456f76dd1f957fc1dfe90b0f05a00a9e4b3a..e7f433f71b42bd473b06e22e7b70e0e40e111c9b 100644 (file)
@@ -1,6 +1,6 @@
 /* NGcopy_from_user.S: Niagara optimized copy from userspace.
  *
- * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #define EX_LD(x)               \
@@ -8,8 +8,8 @@
        .section .fixup;        \
        .align 4;               \
 99:    wr      %g0, ASI_AIUS, %asi;\
-       retl;                   \
-        mov    1, %o0;         \
+       ret                   \
+        restore %g0, 1, %o0;   \
        .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
@@ -24,7 +24,7 @@
 #define LOAD(type,addr,dest)   type##a [addr] ASI_AIUS, dest
 #define LOAD_TWIN(addr_reg,dest0,dest1)        \
        ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_AIUS, dest0
-#define EX_RETVAL(x)           0
+#define EX_RETVAL(x)           %g0
 
 #ifdef __KERNEL__
 #define PREAMBLE                                       \
index 34112d5054ef9895e21d365284ce76b0042bbab0..6ea01c5532a0a87e30f4a737dee0a44b55da3df1 100644 (file)
@@ -1,6 +1,6 @@
 /* NGcopy_to_user.S: Niagara optimized copy to userspace.
  *
- * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #define EX_ST(x)               \
@@ -8,8 +8,8 @@
        .section .fixup;        \
        .align 4;               \
 99:    wr      %g0, ASI_AIUS, %asi;\
-       retl;                   \
-        mov    1, %o0;         \
+       ret                   \
+        restore %g0, 1, %o0;   \
        .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
@@ -23,7 +23,7 @@
 #define FUNC_NAME              NGcopy_to_user
 #define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
 #define STORE_ASI              ASI_BLK_INIT_QUAD_LDD_AIUS
-#define EX_RETVAL(x)           0
+#define EX_RETVAL(x)           %g0
 
 #ifdef __KERNEL__
        /* Writing to %asi is _expensive_ so we hardcode it.
index 66063a9a66b87146524809d2fcd932e7107bda08..96a14caf6966282cab2d97071f7c3837b2a6727a 100644 (file)
@@ -1,6 +1,6 @@
 /* NGmemcpy.S: Niagara optimized memcpy.
  *
- * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #ifdef __KERNEL__
        wr      %g0, ASI_PNF, %asi
 #endif
 
+#ifdef __sparc_v9__
+#define SAVE_AMOUNT    128
+#else
+#define SAVE_AMOUNT    64
+#endif
+
 #ifndef STORE_ASI
 #define STORE_ASI      ASI_BLK_INIT_QUAD_LDD_P
 #endif
 #endif
 
 #ifndef STORE_INIT
+#ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA
 #define STORE_INIT(src,addr)   stxa src, [addr] %asi
+#else
+#define STORE_INIT(src,addr)   stx src, [addr + 0x00]
+#endif
 #endif
 
 #ifndef FUNC_NAME
 
        .globl  FUNC_NAME
        .type   FUNC_NAME,#function
-FUNC_NAME:     /* %o0=dst, %o1=src, %o2=len */
-       srlx            %o2, 31, %g2
+FUNC_NAME:     /* %i0=dst, %i1=src, %i2=len */
+       PREAMBLE
+       save            %sp, -SAVE_AMOUNT, %sp
+       srlx            %i2, 31, %g2
        cmp             %g2, 0
        tne             %xcc, 5
-       PREAMBLE
-       mov             %o0, GLOBAL_SPARE
-       cmp             %o2, 0
+       mov             %i0, %o0
+       cmp             %i2, 0
        be,pn           %XCC, 85f
-        or             %o0, %o1, %o3
-       cmp             %o2, 16
+        or             %o0, %i1, %i3
+       cmp             %i2, 16
        blu,a,pn        %XCC, 80f
-        or             %o3, %o2, %o3
+        or             %i3, %i2, %i3
 
        /* 2 blocks (128 bytes) is the minimum we can do the block
         * copy with.  We need to ensure that we'll iterate at least
@@ -93,31 +104,31 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
         * to (64 - 1) bytes from the length before we perform the
         * block copy loop.
         */
-       cmp             %o2, (2 * 64)
+       cmp             %i2, (2 * 64)
        blu,pt          %XCC, 70f
-        andcc          %o3, 0x7, %g0
+        andcc          %i3, 0x7, %g0
 
        /* %o0: dst
-        * %o1: src
-        * %o2: len  (known to be >= 128)
+        * %i1: src
+        * %i2: len  (known to be >= 128)
         *
-        * The block copy loops will use %o4/%o5,%g2/%g3 as
+        * The block copy loops will use %i4/%i5,%g2/%g3 as
         * temporaries while copying the data.
         */
 
-       LOAD(prefetch, %o1, #one_read)
+       LOAD(prefetch, %i1, #one_read)
        wr              %g0, STORE_ASI, %asi
 
        /* Align destination on 64-byte boundary.  */
-       andcc           %o0, (64 - 1), %o4
+       andcc           %o0, (64 - 1), %i4
        be,pt           %XCC, 2f
-        sub            %o4, 64, %o4
-       sub             %g0, %o4, %o4   ! bytes to align dst
-       sub             %o2, %o4, %o2
-1:     subcc           %o4, 1, %o4
-       EX_LD(LOAD(ldub, %o1, %g1))
+        sub            %i4, 64, %i4
+       sub             %g0, %i4, %i4   ! bytes to align dst
+       sub             %i2, %i4, %i2
+1:     subcc           %i4, 1, %i4
+       EX_LD(LOAD(ldub, %i1, %g1))
        EX_ST(STORE(stb, %g1, %o0))
-       add             %o1, 1, %o1
+       add             %i1, 1, %i1
        bne,pt          %XCC, 1b
        add             %o0, 1, %o0
 
@@ -136,111 +147,155 @@ FUNC_NAME:      /* %o0=dst, %o1=src, %o2=len */
         * aligned store data at a time, this is easy to ensure.
         */
 2:
-       andcc           %o1, (16 - 1), %o4
-       andn            %o2, (64 - 1), %g1      ! block copy loop iterator
-       sub             %o2, %g1, %o2           ! final sub-block copy bytes
+       andcc           %i1, (16 - 1), %i4
+       andn            %i2, (64 - 1), %g1      ! block copy loop iterator
        be,pt           %XCC, 50f
-        cmp            %o4, 8
-       be,a,pt         %XCC, 10f
-        sub            %o1, 0x8, %o1
+        sub            %i2, %g1, %i2           ! final sub-block copy bytes
+
+       cmp             %i4, 8
+       be,pt           %XCC, 10f
+        sub            %i1, %i4, %i1
 
        /* Neither 8-byte nor 16-byte aligned, shift and mask.  */
-       mov             %g1, %o4
-       and             %o1, 0x7, %g1
-       sll             %g1, 3, %g1
-       mov             64, %o3
-       andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1, %g2))
-       sub             %o3, %g1, %o3
-       sllx            %g2, %g1, %g2
+       and             %i4, 0x7, GLOBAL_SPARE
+       sll             GLOBAL_SPARE, 3, GLOBAL_SPARE
+       mov             64, %i5
+       EX_LD(LOAD_TWIN(%i1, %g2, %g3))
+       sub             %i5, GLOBAL_SPARE, %i5
+       mov             16, %o4
+       mov             32, %o5
+       mov             48, %o7
+       mov             64, %i3
+
+       bg,pn           %XCC, 9f
+        nop
 
-#define SWIVEL_ONE_DWORD(SRC, TMP1, TMP2, PRE_VAL, PRE_SHIFT, POST_SHIFT, DST)\
-       EX_LD(LOAD(ldx, SRC, TMP1)); \
-       srlx            TMP1, PRE_SHIFT, TMP2; \
-       or              TMP2, PRE_VAL, TMP2; \
-       EX_ST(STORE_INIT(TMP2, DST)); \
-       sllx            TMP1, POST_SHIFT, PRE_VAL;
-
-1:     add             %o1, 0x8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x00)
-       add             %o1, 0x8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x08)
-       add             %o1, 0x8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x10)
-       add             %o1, 0x8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x18)
-       add             %o1, 32, %o1
-       LOAD(prefetch, %o1, #one_read)
-       sub             %o1, 32 - 8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x20)
-       add             %o1, 8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x28)
-       add             %o1, 8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x30)
-       add             %o1, 8, %o1
-       SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x38)
-       subcc           %o4, 64, %o4
-       bne,pt          %XCC, 1b
+#define MIX_THREE_WORDS(WORD1, WORD2, WORD3, PRE_SHIFT, POST_SHIFT, TMP) \
+       sllx            WORD1, POST_SHIFT, WORD1; \
+       srlx            WORD2, PRE_SHIFT, TMP; \
+       sllx            WORD2, POST_SHIFT, WORD2; \
+       or              WORD1, TMP, WORD1; \
+       srlx            WORD3, PRE_SHIFT, TMP; \
+       or              WORD2, TMP, WORD2;
+
+8:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+       MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
+       LOAD(prefetch, %i1 + %i3, #one_read)
+
+       EX_ST(STORE_INIT(%g2, %o0 + 0x00))
+       EX_ST(STORE_INIT(%g3, %o0 + 0x08))
+
+       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+       MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%o2, %o0 + 0x10))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x18))
+
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%g2, %o0 + 0x20))
+       EX_ST(STORE_INIT(%g3, %o0 + 0x28))
+
+       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+       add             %i1, 64, %i1
+       MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%o2, %o0 + 0x30))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x38))
+
+       subcc           %g1, 64, %g1
+       bne,pt          %XCC, 8b
         add            %o0, 64, %o0
 
-#undef SWIVEL_ONE_DWORD
+       ba,pt           %XCC, 60f
+        add            %i1, %i4, %i1
+
+9:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+       MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
+       LOAD(prefetch, %i1 + %i3, #one_read)
+
+       EX_ST(STORE_INIT(%g3, %o0 + 0x00))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x08))
+
+       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+       MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%o3, %o0 + 0x10))
+       EX_ST(STORE_INIT(%g2, %o0 + 0x18))
+
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%g3, %o0 + 0x20))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x28))
+
+       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+       add             %i1, 64, %i1
+       MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
+
+       EX_ST(STORE_INIT(%o3, %o0 + 0x30))
+       EX_ST(STORE_INIT(%g2, %o0 + 0x38))
+
+       subcc           %g1, 64, %g1
+       bne,pt          %XCC, 9b
+        add            %o0, 64, %o0
 
-       srl             %g1, 3, %g1
        ba,pt           %XCC, 60f
-        add            %o1, %g1, %o1
+        add            %i1, %i4, %i1
 
 10:    /* Destination is 64-byte aligned, source was only 8-byte
         * aligned but it has been subtracted by 8 and we perform
         * one twin load ahead, then add 8 back into source when
         * we finish the loop.
         */
-       EX_LD(LOAD_TWIN(%o1, %o4, %o5))
-1:     add             %o1, 16, %o1
-       EX_LD(LOAD_TWIN(%o1, %g2, %g3))
-       add             %o1, 16 + 32, %o1
-       LOAD(prefetch, %o1, #one_read)
-       sub             %o1, 32, %o1
+       EX_LD(LOAD_TWIN(%i1, %o4, %o5))
+       mov     16, %o7
+       mov     32, %g2
+       mov     48, %g3
+       mov     64, %o1
+1:     EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       LOAD(prefetch, %i1 + %o1, #one_read)
        EX_ST(STORE_INIT(%o5, %o0 + 0x00))      ! initializes cache line
-       EX_ST(STORE_INIT(%g2, %o0 + 0x08))
-       EX_LD(LOAD_TWIN(%o1, %o4, %o5))
-       add             %o1, 16, %o1
-       EX_ST(STORE_INIT(%g3, %o0 + 0x10))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x08))
+       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x10))
        EX_ST(STORE_INIT(%o4, %o0 + 0x18))
-       EX_LD(LOAD_TWIN(%o1, %g2, %g3))
-       add             %o1, 16, %o1
+       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
        EX_ST(STORE_INIT(%o5, %o0 + 0x20))
-       EX_ST(STORE_INIT(%g2, %o0 + 0x28))
-       EX_LD(LOAD_TWIN(%o1, %o4, %o5))
-       EX_ST(STORE_INIT(%g3, %o0 + 0x30))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x28))
+       EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5))
+       add             %i1, 64, %i1
+       EX_ST(STORE_INIT(%o3, %o0 + 0x30))
        EX_ST(STORE_INIT(%o4, %o0 + 0x38))
        subcc           %g1, 64, %g1
        bne,pt          %XCC, 1b
         add            %o0, 64, %o0
 
        ba,pt           %XCC, 60f
-        add            %o1, 0x8, %o1
+        add            %i1, 0x8, %i1
 
 50:    /* Destination is 64-byte aligned, and source is 16-byte
         * aligned.
         */
-1:     EX_LD(LOAD_TWIN(%o1, %o4, %o5))
-       add     %o1, 16, %o1
-       EX_LD(LOAD_TWIN(%o1, %g2, %g3))
-       add     %o1, 16 + 32, %o1
-       LOAD(prefetch, %o1, #one_read)
-       sub     %o1, 32, %o1
+       mov     16, %o7
+       mov     32, %g2
+       mov     48, %g3
+       mov     64, %o1
+1:     EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5))
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       LOAD(prefetch, %i1 + %o1, #one_read)
        EX_ST(STORE_INIT(%o4, %o0 + 0x00))      ! initializes cache line
        EX_ST(STORE_INIT(%o5, %o0 + 0x08))
-       EX_LD(LOAD_TWIN(%o1, %o4, %o5))
-       add     %o1, 16, %o1
-       EX_ST(STORE_INIT(%g2, %o0 + 0x10))
-       EX_ST(STORE_INIT(%g3, %o0 + 0x18))
-       EX_LD(LOAD_TWIN(%o1, %g2, %g3))
-       add     %o1, 16, %o1
+       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x10))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x18))
+       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
+       add     %i1, 64, %i1
        EX_ST(STORE_INIT(%o4, %o0 + 0x20))
        EX_ST(STORE_INIT(%o5, %o0 + 0x28))
-       EX_ST(STORE_INIT(%g2, %o0 + 0x30))
-       EX_ST(STORE_INIT(%g3, %o0 + 0x38))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x30))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x38))
        subcc   %g1, 64, %g1
        bne,pt  %XCC, 1b
         add    %o0, 64, %o0
@@ -249,47 +304,47 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 60:    
        membar          #Sync
 
-       /* %o2 contains any final bytes still needed to be copied
+       /* %i2 contains any final bytes still needed to be copied
         * over. If anything is left, we copy it one byte at a time.
         */
-       RESTORE_ASI(%o3)
-       brz,pt          %o2, 85f
-        sub            %o0, %o1, %o3
+       RESTORE_ASI(%i3)
+       brz,pt          %i2, 85f
+        sub            %o0, %i1, %i3
        ba,a,pt         %XCC, 90f
 
        .align          64
 70: /* 16 < len <= 64 */
        bne,pn          %XCC, 75f
-        sub            %o0, %o1, %o3
+        sub            %o0, %i1, %i3
 
 72:
-       andn            %o2, 0xf, %o4
-       and             %o2, 0xf, %o2
-1:     subcc           %o4, 0x10, %o4
-       EX_LD(LOAD(ldx, %o1, %o5))
-       add             %o1, 0x08, %o1
-       EX_LD(LOAD(ldx, %o1, %g1))
-       sub             %o1, 0x08, %o1
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
-       add             %o1, 0x8, %o1
-       EX_ST(STORE(stx, %g1, %o1 + %o3))
+       andn            %i2, 0xf, %i4
+       and             %i2, 0xf, %i2
+1:     subcc           %i4, 0x10, %i4
+       EX_LD(LOAD(ldx, %i1, %o4))
+       add             %i1, 0x08, %i1
+       EX_LD(LOAD(ldx, %i1, %g1))
+       sub             %i1, 0x08, %i1
+       EX_ST(STORE(stx, %o4, %i1 + %i3))
+       add             %i1, 0x8, %i1
+       EX_ST(STORE(stx, %g1, %i1 + %i3))
        bgu,pt          %XCC, 1b
-        add            %o1, 0x8, %o1
-73:    andcc           %o2, 0x8, %g0
+        add            %i1, 0x8, %i1
+73:    andcc           %i2, 0x8, %g0
        be,pt           %XCC, 1f
         nop
-       sub             %o2, 0x8, %o2
-       EX_LD(LOAD(ldx, %o1, %o5))
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
-       add             %o1, 0x8, %o1
-1:     andcc           %o2, 0x4, %g0
+       sub             %i2, 0x8, %i2
+       EX_LD(LOAD(ldx, %i1, %o4))
+       EX_ST(STORE(stx, %o4, %i1 + %i3))
+       add             %i1, 0x8, %i1
+1:     andcc           %i2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
-       sub             %o2, 0x4, %o2
-       EX_LD(LOAD(lduw, %o1, %o5))
-       EX_ST(STORE(stw, %o5, %o1 + %o3))
-       add             %o1, 0x4, %o1
-1:     cmp             %o2, 0
+       sub             %i2, 0x4, %i2
+       EX_LD(LOAD(lduw, %i1, %i5))
+       EX_ST(STORE(stw, %i5, %i1 + %i3))
+       add             %i1, 0x4, %i1
+1:     cmp             %i2, 0
        be,pt           %XCC, 85f
         nop
        ba,pt           %xcc, 90f
@@ -300,71 +355,71 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        sub             %g1, 0x8, %g1
        be,pn           %icc, 2f
         sub            %g0, %g1, %g1
-       sub             %o2, %g1, %o2
+       sub             %i2, %g1, %i2
 
 1:     subcc           %g1, 1, %g1
-       EX_LD(LOAD(ldub, %o1, %o5))
-       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       EX_LD(LOAD(ldub, %i1, %i5))
+       EX_ST(STORE(stb, %i5, %i1 + %i3))
        bgu,pt          %icc, 1b
-        add            %o1, 1, %o1
+        add            %i1, 1, %i1
 
-2:     add             %o1, %o3, %o0
-       andcc           %o1, 0x7, %g1
+2:     add             %i1, %i3, %o0
+       andcc           %i1, 0x7, %g1
        bne,pt          %icc, 8f
         sll            %g1, 3, %g1
 
-       cmp             %o2, 16
+       cmp             %i2, 16
        bgeu,pt         %icc, 72b
         nop
        ba,a,pt         %xcc, 73b
 
-8:     mov             64, %o3
-       andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1, %g2))
-       sub             %o3, %g1, %o3
-       andn            %o2, 0x7, %o4
+8:     mov             64, %i3
+       andn            %i1, 0x7, %i1
+       EX_LD(LOAD(ldx, %i1, %g2))
+       sub             %i3, %g1, %i3
+       andn            %i2, 0x7, %i4
        sllx            %g2, %g1, %g2
-1:     add             %o1, 0x8, %o1
-       EX_LD(LOAD(ldx, %o1, %g3))
-       subcc           %o4, 0x8, %o4
-       srlx            %g3, %o3, %o5
-       or              %o5, %g2, %o5
-       EX_ST(STORE(stx, %o5, %o0))
+1:     add             %i1, 0x8, %i1
+       EX_LD(LOAD(ldx, %i1, %g3))
+       subcc           %i4, 0x8, %i4
+       srlx            %g3, %i3, %i5
+       or              %i5, %g2, %i5
+       EX_ST(STORE(stx, %i5, %o0))
        add             %o0, 0x8, %o0
        bgu,pt          %icc, 1b
         sllx           %g3, %g1, %g2
 
        srl             %g1, 3, %g1
-       andcc           %o2, 0x7, %o2
+       andcc           %i2, 0x7, %i2
        be,pn           %icc, 85f
-        add            %o1, %g1, %o1
+        add            %i1, %g1, %i1
        ba,pt           %xcc, 90f
-        sub            %o0, %o1, %o3
+        sub            %o0, %i1, %i3
 
        .align          64
 80: /* 0 < len <= 16 */
-       andcc           %o3, 0x3, %g0
+       andcc           %i3, 0x3, %g0
        bne,pn          %XCC, 90f
-        sub            %o0, %o1, %o3
+        sub            %o0, %i1, %i3
 
 1:
-       subcc           %o2, 4, %o2
-       EX_LD(LOAD(lduw, %o1, %g1))
-       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       subcc           %i2, 4, %i2
+       EX_LD(LOAD(lduw, %i1, %g1))
+       EX_ST(STORE(stw, %g1, %i1 + %i3))
        bgu,pt          %XCC, 1b
-        add            %o1, 4, %o1
+        add            %i1, 4, %i1
 
-85:    retl
-        mov            EX_RETVAL(GLOBAL_SPARE), %o0
+85:    ret
+        restore        EX_RETVAL(%i0), %g0, %o0
 
        .align          32
 90:
-       subcc           %o2, 1, %o2
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       subcc           %i2, 1, %i2
+       EX_LD(LOAD(ldub, %i1, %g1))
+       EX_ST(STORE(stb, %g1, %i1 + %i3))
        bgu,pt          %XCC, 90b
-        add            %o1, 1, %o1
-       retl
-        mov            EX_RETVAL(GLOBAL_SPARE), %o0
+        add            %i1, 1, %i1
+       ret
+        restore        EX_RETVAL(%i0), %g0, %o0
 
        .size           FUNC_NAME, .-FUNC_NAME
index 8d7f7c1cb9c64e40dd96cd17f8e65fe3b9a323da..6c2be26f1d7db94647ba856f8217b03b86e9e63b 100644 (file)
@@ -117,7 +117,7 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs);
 
 extern void copy_sc(union uml_pt_regs *regs, void *from);
 
-unsigned long to_irq_stack(int sig, unsigned long *mask_out);
+extern unsigned long to_irq_stack(unsigned long *mask_out);
 unsigned long from_irq_stack(int nested);
 
 #endif
index 9870febdbead3897b2ed9257ba0548d7e0389159..cf0dd9cf8c430e5cb7578d1166277d74970859ae 100644 (file)
@@ -518,13 +518,13 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
 
 static unsigned long pending_mask;
 
-unsigned long to_irq_stack(int sig, unsigned long *mask_out)
+unsigned long to_irq_stack(unsigned long *mask_out)
 {
        struct thread_info *ti;
        unsigned long mask, old;
        int nested;
 
-       mask = xchg(&pending_mask, 1 << sig);
+       mask = xchg(&pending_mask, *mask_out);
        if(mask != 0){
                /* If any interrupts come in at this point, we want to
                 * make sure that their bits aren't lost by our
@@ -534,7 +534,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
                 * and pending_mask contains a bit for each interrupt
                 * that came in.
                 */
-               old = 1 << sig;
+               old = *mask_out;
                do {
                        old |= mask;
                        mask = xchg(&pending_mask, old);
@@ -550,6 +550,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
 
                task = cpu_tasks[ti->cpu].task;
                tti = task_thread_info(task);
+
                *ti = *tti;
                ti->real_thread = tti;
                task->stack = ti;
index 6f92f732d25346aef20f43eda05efe8d7f9d8c12..c3ecc2a84e0cb29b3b1a95908cca588fdfc11201 100644 (file)
@@ -320,7 +320,8 @@ int os_file_size(char *file, unsigned long long *size_out)
        }
 
        if(S_ISBLK(buf.ust_mode)){
-               int fd, blocks;
+               int fd;
+               long blocks;
 
                fd = os_open_file(file, of_read(OPENFLAGS()), 0);
                if(fd < 0){
index 18e5c8b67eb8cebbe84db25bed7e64e623522dc9..b98f7ea2d2f6562ce894e4a4fe6f57b003af7768 100644 (file)
@@ -119,7 +119,7 @@ void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
 
 void handle_signal(int sig, struct sigcontext *sc)
 {
-       unsigned long pending = 0;
+       unsigned long pending = 1UL << sig;
 
        do {
                int nested, bail;
@@ -134,7 +134,7 @@ void handle_signal(int sig, struct sigcontext *sc)
                 * have to return, and the upper handler will deal
                 * with this interrupt.
                 */
-               bail = to_irq_stack(sig, &pending);
+               bail = to_irq_stack(&pending);
                if(bail)
                        return;
 
index ffa036406289cee0e9734f558d6e57ffa9bb0b7e..b4d9089a6a06736cf5c8b9fc2ac1955a8ad19360 100644 (file)
@@ -60,14 +60,6 @@ config ZONE_DMA
        bool
        default y
 
-config QUICKLIST
-       bool
-       default y
-
-config NR_QUICK
-       int
-       default 2
-
 config ISA
        bool
 
index 938278697e206bdb10027918f5aff8a587383be0..18b23181090808b953f91568d6183345b8028fd1 100644 (file)
        movq    %rax,R8(%rsp)
        .endm
 
+       .macro LOAD_ARGS32 offset
+       movl \offset(%rsp),%r11d
+       movl \offset+8(%rsp),%r10d
+       movl \offset+16(%rsp),%r9d
+       movl \offset+24(%rsp),%r8d
+       movl \offset+40(%rsp),%ecx
+       movl \offset+48(%rsp),%edx
+       movl \offset+56(%rsp),%esi
+       movl \offset+64(%rsp),%edi
+       movl \offset+72(%rsp),%eax
+       .endm
+       
        .macro CFI_STARTPROC32 simple
        CFI_STARTPROC   \simple
        CFI_UNDEFINED   r8
@@ -152,7 +164,7 @@ sysenter_tracesys:
        movq    $-ENOSYS,RAX(%rsp)      /* really needed? */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        movl    %ebp, %ebp
        /* no need to do an access_ok check here because rbp has been
@@ -255,7 +267,7 @@ cstar_tracesys:
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        movl RSP-ARGOFFSET(%rsp), %r8d
        /* no need to do an access_ok check here because r8 has been
@@ -334,7 +346,7 @@ ia32_tracesys:
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        jmp ia32_do_syscall
 END(ia32_syscall)
index 13f1480cbec93bbfb8fd2d8f9a7aa8f9a3ba6f48..a06f2bcabef9d5f3cfe0928c31d0b753894d6aca 100644 (file)
@@ -81,7 +81,7 @@ wakeup_code:
        testl   $2, realmode_flags - wakeup_code
        jz      1f
        mov     video_mode - wakeup_code, %ax
-       call    mode_seta
+       call    mode_set
 1:
 
        movw    $0xb800, %ax
@@ -291,52 +291,31 @@ no_longmode:
 #define VIDEO_FIRST_V7 0x0900
 
 # Setting of user mode (AX=mode ID) => CF=success
+
+# For now, we only handle VESA modes (0x0200..0x03ff).  To handle other
+# modes, we should probably compile in the video code from the boot
+# directory.
 .code16
-mode_seta:
+mode_set:
        movw    %ax, %bx
-#if 0
-       cmpb    $0xff, %ah
-       jz      setalias
-
-       testb   $VIDEO_RECALC>>8, %ah
-       jnz     _setrec
-
-       cmpb    $VIDEO_FIRST_RESOLUTION>>8, %ah
-       jnc     setres
-       
-       cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
-       jz      setspc
-
-       cmpb    $VIDEO_FIRST_V7>>8, %ah
-       jz      setv7
-#endif
-       
-       cmpb    $VIDEO_FIRST_VESA>>8, %ah
-       jnc     check_vesaa
-#if 0  
-       orb     %ah, %ah
-       jz      setmenu
-#endif
-       
-       decb    %ah
-#      jz      setbios                           Add bios modes later
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       cmpb    $2, %bh
+       jb      check_vesa
 
-setbada:       clc
+setbad:
+       clc
        ret
 
-check_vesaa:
-       subb    $VIDEO_FIRST_VESA>>8, %bh
+check_vesa:
        orw     $0x4000, %bx                    # Use linear frame buffer
        movw    $0x4f02, %ax                    # VESA BIOS mode set call
        int     $0x10
        cmpw    $0x004f, %ax                    # AL=4f if implemented
-       jnz     _setbada                                # AH=0 if OK
+       jnz     setbad                          # AH=0 if OK
 
        stc
        ret
 
-_setbada: jmp setbada
-
 wakeup_stack_begin:    # Stack grows down
 
 .org   0xff0
index 2842f50cbe3fde220dfc33a61b720720aa7a7e7f..98956555450beff2c49d22eed79a63aecff87175 100644 (file)
@@ -208,7 +208,6 @@ void cpu_idle (void)
                        if (__get_cpu_var(cpu_idle_state))
                                __get_cpu_var(cpu_idle_state) = 0;
 
-                       check_pgt_cache();
                        rmb();
                        idle = pm_idle;
                        if (!idle)
index e83cc67155ac253cbbec207b8ef246bc55f0a408..eea3702427b409d28c83c7e02a88c093a5c26232 100644 (file)
@@ -232,10 +232,6 @@ static int putreg(struct task_struct *child,
 {
        unsigned long tmp; 
        
-       /* Some code in the 64bit emulation may not be 64bit clean.
-          Don't take any chances. */
-       if (test_tsk_thread_flag(child, TIF_IA32))
-               value &= 0xffffffff;
        switch (regno) {
                case offsetof(struct user_regs_struct,fs):
                        if (value && (value & 3) != 3)
index 673a300b59442df7dcc193f6fb78e7aaa30eceda..df4a82812adbbad89fe7d491c3ac7347553cb281 100644 (file)
@@ -241,7 +241,7 @@ void flush_tlb_mm (struct mm_struct * mm)
        }
        if (!cpus_empty(cpu_mask))
                flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
-       check_pgt_cache();
+
        preempt_enable();
 }
 EXPORT_SYMBOL(flush_tlb_mm);
index 327c9f2fa6269f3020f94f856cd8e0b8b36ab494..54816adb8e933c8c09e41afcf3008331afb5adc6 100644 (file)
@@ -374,6 +374,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        if (unlikely(in_atomic() || !mm))
                goto bad_area_nosemaphore;
 
+       /*
+        * User-mode registers count as a user access even for any
+        * potential system fault or CPU buglet.
+        */
+       if (user_mode_vm(regs))
+               error_code |= PF_USER;
+
  again:
        /* When running in the kernel we expect faults to occur only to
         * addresses in user space.  All other faults represent errors in the
index 5304204911f231f9e513ebcc7e71d425bd3507df..4af67c79085f27f090867c3a1b1fab6bd821b4a9 100644 (file)
@@ -1 +1 @@
-#define VDSO_TEXT_OFFSET 0x500
+#define VDSO_TEXT_OFFSET 0x600
index 035007145e780d2cedd3e38cbb1a34e39345d3c2..bc18cbb8ea79562ce05401a5734d8310cf2ea938 100644 (file)
@@ -80,6 +80,7 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
 {
        enum dma_status status;
        struct dma_async_tx_descriptor *iter;
+       struct dma_async_tx_descriptor *parent;
 
        if (!tx)
                return DMA_SUCCESS;
@@ -87,8 +88,15 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
        /* poll through the dependency chain, return when tx is complete */
        do {
                iter = tx;
-               while (iter->cookie == -EBUSY)
-                       iter = iter->parent;
+
+               /* find the root of the unsubmitted dependency chain */
+               while (iter->cookie == -EBUSY) {
+                       parent = iter->parent;
+                       if (parent && parent->cookie == -EBUSY)
+                               iter = iter->parent;
+                       else
+                               break;
+               }
 
                status = dma_sync_wait(iter->chan, iter->cookie);
        } while (status == DMA_IN_PROGRESS || (iter != tx));
index 2afb3d2086b3d03b3e4858caffba20f6f456c90f..9f11dc296cdd7bc29f5545cd8524eb03ede594e3 100644 (file)
@@ -102,6 +102,8 @@ static struct acpi_driver acpi_processor_driver = {
                .add = acpi_processor_add,
                .remove = acpi_processor_remove,
                .start = acpi_processor_start,
+               .suspend = acpi_processor_suspend,
+               .resume = acpi_processor_resume,
                },
 };
 
index d9b8af763e1ec59e64671655fda51e0601b55da9..f18261368e76e87059606d8d8dfc4e753266b99a 100644 (file)
@@ -325,6 +325,23 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr,
 
 #endif
 
+/*
+ * Suspend / resume control
+ */
+static int acpi_idle_suspend;
+
+int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
+{
+       acpi_idle_suspend = 1;
+       return 0;
+}
+
+int acpi_processor_resume(struct acpi_device * device)
+{
+       acpi_idle_suspend = 0;
+       return 0;
+}
+
 static void acpi_processor_idle(void)
 {
        struct acpi_processor *pr = NULL;
@@ -355,7 +372,7 @@ static void acpi_processor_idle(void)
        }
 
        cx = pr->power.state;
-       if (!cx) {
+       if (!cx || acpi_idle_suspend) {
                if (pm_idle_save)
                        pm_idle_save();
                else
index 195a4f69c0f773d4ba73119d3efd0512c9d10454..f1fb888c2d293752448d7124e8308740afc7d534 100644 (file)
@@ -1,5 +1,5 @@
-obj-y                                  := poweroff.o wakeup.o
-obj-$(CONFIG_ACPI_SLEEP)               += main.o
+obj-y                                  := wakeup.o
+obj-y                                  += main.o
 obj-$(CONFIG_ACPI_SLEEP)               += proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
index c52ade816fb494768000d11cfb0b277c37483071..2cbb9aabd00eba4c8eeb395deb922dcc36fb6980 100644 (file)
 #include <linux/dmi.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
+
+#include <asm/io.h>
+
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include "sleep.h"
 
 u8 sleep_states[ACPI_S_STATE_COUNT];
 
+#ifdef CONFIG_PM_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+#endif
+
+int acpi_sleep_prepare(u32 acpi_state)
+{
+#ifdef CONFIG_ACPI_SLEEP
+       /* do we have a wakeup address for S2 and S3? */
+       if (acpi_state == ACPI_STATE_S3) {
+               if (!acpi_wakeup_address) {
+                       return -EFAULT;
+               }
+               acpi_set_firmware_waking_vector((acpi_physical_address)
+                                               virt_to_phys((void *)
+                                                            acpi_wakeup_address));
+
+       }
+       ACPI_FLUSH_CPU_CACHE();
+       acpi_enable_wakeup_device_prep(acpi_state);
+#endif
+       acpi_gpe_sleep_prepare(acpi_state);
+       acpi_enter_sleep_state_prep(acpi_state);
+       return 0;
+}
 
 #ifdef CONFIG_SUSPEND
 static struct pm_ops acpi_pm_ops;
@@ -275,6 +301,7 @@ int acpi_suspend(u32 acpi_state)
        return -EINVAL;
 }
 
+#ifdef CONFIG_PM_SLEEP
 /**
  *     acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *             in the system sleep state given by %acpi_target_sleep_state
@@ -349,6 +376,21 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
                *d_min_p = d_min;
        return d_max;
 }
+#endif
+
+static void acpi_power_off_prepare(void)
+{
+       /* Prepare to power off the system */
+       acpi_sleep_prepare(ACPI_STATE_S5);
+}
+
+static void acpi_power_off(void)
+{
+       /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
+       printk("%s called\n", __FUNCTION__);
+       local_irq_disable();
+       acpi_enter_sleep_state(ACPI_STATE_S5);
+}
 
 int __init acpi_sleep_init(void)
 {
@@ -363,16 +405,17 @@ int __init acpi_sleep_init(void)
        if (acpi_disabled)
                return 0;
 
+       sleep_states[ACPI_STATE_S0] = 1;
+       printk(KERN_INFO PREFIX "(supports S0");
+
 #ifdef CONFIG_SUSPEND
-       printk(KERN_INFO PREFIX "(supports");
-       for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) {
+       for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
                status = acpi_get_sleep_type_data(i, &type_a, &type_b);
                if (ACPI_SUCCESS(status)) {
                        sleep_states[i] = 1;
                        printk(" S%d", i);
                }
        }
-       printk(")\n");
 
        pm_set_ops(&acpi_pm_ops);
 #endif
@@ -382,10 +425,16 @@ int __init acpi_sleep_init(void)
        if (ACPI_SUCCESS(status)) {
                hibernation_set_ops(&acpi_hibernation_ops);
                sleep_states[ACPI_STATE_S4] = 1;
+               printk(" S4");
        }
-#else
-       sleep_states[ACPI_STATE_S4] = 0;
 #endif
-
+       status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
+       if (ACPI_SUCCESS(status)) {
+               sleep_states[ACPI_STATE_S5] = 1;
+               printk(" S5");
+               pm_power_off_prepare = acpi_power_off_prepare;
+               pm_power_off = acpi_power_off;
+       }
+       printk(")\n");
        return 0;
 }
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
deleted file mode 100644 (file)
index 39e40d5..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * poweroff.c - ACPI handler for powering off the system.
- *
- * AKA S5, but it is independent of whether or not the kernel supports
- * any other sleep support in the system.
- *
- * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
- *
- * This file is released under the GPLv2.
- */
-
-#include <linux/pm.h>
-#include <linux/init.h>
-#include <acpi/acpi_bus.h>
-#include <linux/sysdev.h>
-#include <asm/io.h>
-#include "sleep.h"
-
-int acpi_sleep_prepare(u32 acpi_state)
-{
-#ifdef CONFIG_ACPI_SLEEP
-       /* do we have a wakeup address for S2 and S3? */
-       if (acpi_state == ACPI_STATE_S3) {
-               if (!acpi_wakeup_address) {
-                       return -EFAULT;
-               }
-               acpi_set_firmware_waking_vector((acpi_physical_address)
-                                               virt_to_phys((void *)
-                                                            acpi_wakeup_address));
-
-       }
-       ACPI_FLUSH_CPU_CACHE();
-       acpi_enable_wakeup_device_prep(acpi_state);
-#endif
-       acpi_gpe_sleep_prepare(acpi_state);
-       acpi_enter_sleep_state_prep(acpi_state);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-static void acpi_power_off_prepare(void)
-{
-       /* Prepare to power off the system */
-       acpi_sleep_prepare(ACPI_STATE_S5);
-}
-
-static void acpi_power_off(void)
-{
-       /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
-       printk("%s called\n", __FUNCTION__);
-       local_irq_disable();
-       /* Some SMP machines only can poweroff in boot CPU */
-       acpi_enter_sleep_state(ACPI_STATE_S5);
-}
-
-static int acpi_poweroff_init(void)
-{
-       if (!acpi_disabled) {
-               u8 type_a, type_b;
-               acpi_status status;
-
-               status =
-                   acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
-               if (ACPI_SUCCESS(status)) {
-                       pm_power_off_prepare = acpi_power_off_prepare;
-                       pm_power_off = acpi_power_off;
-               }
-       }
-       return 0;
-}
-
-late_initcall(acpi_poweroff_init);
-
-#endif                         /* CONFIG_PM */
index 3c9bb85a6a93f9465917876a856c42c30e4f15bf..d05891f16282338d96d5cf5a5f3f22d30d6cd5c0 100644 (file)
@@ -417,7 +417,6 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
        arg0.integer.value = level;
        status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL);
 
-       printk(KERN_DEBUG "set_level status: %x\n", status);
        return status;
 }
 
@@ -1754,7 +1753,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
 
 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
 {
-       return acpi_video_bus_DOS(video, 1, 0);
+       return acpi_video_bus_DOS(video, 0, 0);
 }
 
 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
index 06f212ff2b4f2093e6d954c169c8c2454136dbb7..c16820325d7bf127fc1989e3dede84665cc3fed6 100644 (file)
@@ -418,10 +418,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 
        /* ATI */
        { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
-       { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 IDE */
-       { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700 AHCI */
-       { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700 nraid5 */
-       { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700 raid5 */
+       { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700/800 */
+       { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700/800 */
+       { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700/800 */
+       { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700/800 */
+       { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb600 }, /* ATI SB700/800 */
+       { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb600 }, /* ATI SB700/800 */
 
        /* VIA */
        { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
index 3b8bf1812dc8588a8b02ae47e49abfdcc9bdb7a0..6996eb5b75068c05f2f4aa78d70e6a64e54f6c8d 100644 (file)
@@ -920,6 +920,13 @@ static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 static int piix_broken_suspend(void)
 {
        static struct dmi_system_id sysids[] = {
+               {
+                       .ident = "TECRA M3",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"),
+                       },
+               },
                {
                        .ident = "TECRA M5",
                        .matches = {
index c43de9a710db95266f8d49f1e2f12cbb7cb93bdc..772be09b468966277c7d1a41960d52b758cd7480 100644 (file)
@@ -3778,6 +3778,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "Maxtor 6L250S0",     "BANC1G10",     ATA_HORKAGE_NONCQ },
        { "Maxtor 6B200M0",     "BANC1BM0",     ATA_HORKAGE_NONCQ },
        { "Maxtor 6B200M0",     "BANC1B10",     ATA_HORKAGE_NONCQ },
+       { "Maxtor 7B250S0",     "BANC1B70",     ATA_HORKAGE_NONCQ, },
+       { "Maxtor 7B300S0",     "BANC1B70",     ATA_HORKAGE_NONCQ },
+       { "Maxtor 7V300F0",     "VA111630",     ATA_HORKAGE_NONCQ },
        { "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
         ATA_HORKAGE_NONCQ },
        /* NCQ hard hangs device under heavier load, needs hard power cycle */
@@ -3794,6 +3797,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "WDC WD740ADFD-00NLR1", NULL,         ATA_HORKAGE_NONCQ, },
        { "FUJITSU MHV2080BH",  "00840028",     ATA_HORKAGE_NONCQ, },
        { "ST9160821AS",        "3.CLF",        ATA_HORKAGE_NONCQ, },
+       { "ST3160812AS",        "3.AD",         ATA_HORKAGE_NONCQ, },
        { "SAMSUNG HD401LJ",    "ZZ100-15",     ATA_HORKAGE_NONCQ, },
 
        /* devices which puke on READ_NATIVE_MAX */
index 1cce2198baaf1203deb7e1e7e6df305e215501df..8023167bbbeb68623fd9939887010fb74362cb70 100644 (file)
@@ -297,7 +297,7 @@ void ata_bmdma_start (struct ata_queued_cmd *qc)
        dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
        iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
-       /* Strictly, one may wish to issue a readb() here, to
+       /* Strictly, one may wish to issue an ioread8() here, to
         * flush the mmio write.  However, control also passes
         * to the hardware at this point, and it will interrupt
         * us when we are to resume control.  So, in effect,
@@ -307,6 +307,9 @@ void ata_bmdma_start (struct ata_queued_cmd *qc)
         * is expected, so I think it is best to not add a readb()
         * without first all the MMIO ATA cards/mobos.
         * Or maybe I'm just being paranoid.
+        *
+        * FIXME: The posting of this write means I/O starts are
+        * unneccessarily delayed for MMIO
         */
 }
 
index 4ca7fd6118d50f6d52a1b7c464d1266614282b2d..5dea3584c6c2fc439846b190b2d3627bf22a6156 100644 (file)
@@ -189,6 +189,9 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
        data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
        data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
 
+       if (!data->cs0 || !data->cs1)
+               return -ENOMEM;
+
        irq = platform_get_irq(pdev, 0);
        if (irq)
                set_irq_type(irq, IRQT_RISING);
index ae206f35f747a677e54675847e6fb049c4043569..b45506f1ef73e0db979a1614ffaa58048a63f721 100644 (file)
@@ -44,10 +44,10 @@ static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline)
                return -ENOMEM;
        printk("BAR5:");
        for(i = 0; i <= 0x0F; i++)
-               printk("%02X:%02X ", i, readb(barp + i));
+               printk("%02X:%02X ", i, ioread8(barp + i));
        printk("\n");
 
-       devices = readl(barp + 0x0C);
+       devices = ioread32(barp + 0x0C);
        pci_iounmap(pdev, barp);
 
        if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
index 2bd7645f1a8846a49cbefb3019aace5dae70a73f..cce2834b2b60990140071be8ad10ec3fbcee2b84 100644 (file)
@@ -375,8 +375,9 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
        int drive_pci = sis_old_port_base(adev);
        u16 timing;
 
+       /* MWDMA 0-2 and UDMA 0-5 */
        const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
-       const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000};
+       const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
 
        pci_read_config_word(pdev, drive_pci, &timing);
 
index 11bf6c7ac12260d4ba40551b5eef854022ab8eb3..cb7dec97fee6ab39215ada12c8f0a5372927b523 100644 (file)
@@ -313,7 +313,10 @@ enum {
 #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
 
 enum {
-       MV_DMA_BOUNDARY         = 0xffffffffU,
+       /* DMA boundary 0xffff is required by the s/g splitting
+        * we need on /length/ in mv_fill-sg().
+        */
+       MV_DMA_BOUNDARY         = 0xffffU,
 
        /* mask of register bits containing lower 32 bits
         * of EDMA request queue DMA address
@@ -448,7 +451,7 @@ static struct scsi_host_template mv5_sht = {
        .queuecommand           = ata_scsi_queuecmd,
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = MV_MAX_SG_CT,
+       .sg_tablesize           = MV_MAX_SG_CT / 2,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = 1,
@@ -466,7 +469,7 @@ static struct scsi_host_template mv6_sht = {
        .queuecommand           = ata_scsi_queuecmd,
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = MV_MAX_SG_CT,
+       .sg_tablesize           = MV_MAX_SG_CT / 2,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = 1,
@@ -1139,15 +1142,27 @@ static unsigned int mv_fill_sg(struct ata_queued_cmd *qc)
                dma_addr_t addr = sg_dma_address(sg);
                u32 sg_len = sg_dma_len(sg);
 
-               mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
-               mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
-               mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff);
+               while (sg_len) {
+                       u32 offset = addr & 0xffff;
+                       u32 len = sg_len;
+
+                       if ((offset + sg_len > 0x10000))
+                               len = 0x10000 - offset;
+
+                       mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
+                       mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
+                       mv_sg->flags_size = cpu_to_le32(len);
 
-               if (ata_sg_is_last(sg, qc))
-                       mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+                       sg_len -= len;
+                       addr += len;
+
+                       if (!sg_len && ata_sg_is_last(sg, qc))
+                               mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+
+                       mv_sg++;
+                       n_sg++;
+               }
 
-               mv_sg++;
-               n_sg++;
        }
 
        return n_sg;
index ef83e6b1e314d1aaf3842ca673012425b92bd66f..233e886933959c63f3a5d8d1ea04df0f0a2dfb6b 100644 (file)
@@ -888,6 +888,16 @@ static inline void sil24_host_intr(struct ata_port *ap)
        u32 slot_stat, qc_active;
        int rc;
 
+       /* If PCIX_IRQ_WOC, there's an inherent race window between
+        * clearing IRQ pending status and reading PORT_SLOT_STAT
+        * which may cause spurious interrupts afterwards.  This is
+        * unavoidable and much better than losing interrupts which
+        * happens if IRQ pending is cleared after reading
+        * PORT_SLOT_STAT.
+        */
+       if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+               writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
+
        slot_stat = readl(port + PORT_SLOT_STAT);
 
        if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
@@ -895,9 +905,6 @@ static inline void sil24_host_intr(struct ata_port *ap)
                return;
        }
 
-       if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
-               writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
-
        qc_active = slot_stat & ~HOST_SSTAT_ATTN;
        rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
        if (rc > 0)
@@ -910,7 +917,8 @@ static inline void sil24_host_intr(struct ata_port *ap)
                return;
        }
 
-       if (ata_ratelimit())
+       /* spurious interrupts are expected if PCIX_IRQ_WOC */
+       if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
                ata_port_printk(ap, KERN_INFO, "spurious interrupt "
                        "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
                        slot_stat, ap->active_tag, ap->sactive);
index e6738bcbe5a9b2da343e5d20a67b51a6b28545ee..ec86d6fc2360bbb3fa6286a1972a7f82f36c3699 100644 (file)
@@ -284,6 +284,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
 
        /* let the kset specific function add its keys */
        pos = data;
+       memset(envp, 0, sizeof(envp));
        retval = kset->uevent_ops->uevent(kset, &dev->kobj,
                                          envp, ARRAY_SIZE(envp),
                                          pos, PAGE_SIZE);
@@ -585,9 +586,13 @@ void device_initialize(struct device *dev)
 static struct kobject * get_device_parent(struct device *dev,
                                          struct device *parent)
 {
-       /* Set the parent to the class, not the parent device */
-       /* this keeps sysfs from having a symlink to make old udevs happy */
-       if (dev->class)
+       /*
+        * Set the parent to the class, not the parent device
+        * for topmost devices in class hierarchy.
+        * This keeps sysfs from having a symlink to make old
+        * udevs happy
+        */
+       if (dev->class && (!parent || parent->class != dev->class))
                return &dev->class->subsys.kobj;
        else if (parent)
                return &parent->kobj;
@@ -679,14 +684,26 @@ static int device_add_class_symlinks(struct device *dev)
                        goto out_subsys;
        }
        if (dev->parent) {
-               error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
-                                         "device");
-               if (error)
-                       goto out_busid;
 #ifdef CONFIG_SYSFS_DEPRECATED
                {
-                       char * class_name = make_class_name(dev->class->name,
-                                                               &dev->kobj);
+                       struct device *parent = dev->parent;
+                       char *class_name;
+
+                       /*
+                        * In old sysfs stacked class devices had 'device'
+                        * link pointing to real device instead of parent
+                        */
+                       while (parent->class && !parent->bus && parent->parent)
+                               parent = parent->parent;
+
+                       error = sysfs_create_link(&dev->kobj,
+                                                 &parent->kobj,
+                                                 "device");
+                       if (error)
+                               goto out_busid;
+
+                       class_name = make_class_name(dev->class->name,
+                                                       &dev->kobj);
                        if (class_name)
                                error = sysfs_create_link(&dev->parent->kobj,
                                                        &dev->kobj, class_name);
@@ -694,6 +711,11 @@ static int device_add_class_symlinks(struct device *dev)
                        if (error)
                                goto out_device;
                }
+#else
+               error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
+                                         "device");
+               if (error)
+                       goto out_busid;
 #endif
        }
        return 0;
index 504a95d888b2ce1863c61c901885c4bd8c033212..84d6aa500e26b24a3e73ada55c87d4c44efb6be9 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
index 67ee3d4b2878c1d2916dbc55f1d60757add33951..79245714f0a777430d459eb2a3c09aa7746410b4 100644 (file)
@@ -1032,6 +1032,10 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
        check_disk_change(ip->i_bdev);
        return 0;
 err_release:
+       if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
+               cdi->ops->lock_door(cdi, 0);
+               cdinfo(CD_OPEN, "door unlocked.\n");
+       }
        cdi->ops->release(cdi);
 err:
        cdi->use_count--;
index d68ddbe70f737414a876c9f52cf1417223cbe8b7..c78ff26647ee2ba0642017e15e1d6f9805b9de37 100644 (file)
@@ -129,7 +129,7 @@ $(obj)/defkeymap.o:  $(obj)/defkeymap.c
 
 ifdef GENERATE_KEYMAP
 
-$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map
+$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map
        loadkeys --mktable $< > $@.tmp
        sed -e 's/^static *//' $@.tmp > $@
        rm $@.tmp
index 35ab1a9f8e8b42269ea1e7a7e9d13f9c86f16d0b..8955e7ff759a7c9b9269fee1e2398a81622cccdd 100644 (file)
@@ -176,7 +176,7 @@ struct agp_bridge_data {
 #define I830_GMCH_MEM_MASK             0x1
 #define I830_GMCH_MEM_64M              0x1
 #define I830_GMCH_MEM_128M             0
-#define I830_GMCH_GMS_MASK             0xF0
+#define I830_GMCH_GMS_MASK             0x70
 #define I830_GMCH_GMS_DISABLED         0x00
 #define I830_GMCH_GMS_LOCAL            0x10
 #define I830_GMCH_GMS_STOLEN_512       0x20
@@ -190,6 +190,7 @@ struct agp_bridge_data {
 #define INTEL_I830_ERRSTS      0x92
 
 /* Intel 855GM/852GM registers */
+#define I855_GMCH_GMS_MASK             0xF0
 #define I855_GMCH_GMS_STOLEN_0M                0x0
 #define I855_GMCH_GMS_STOLEN_1M                (0x1 << 4)
 #define I855_GMCH_GMS_STOLEN_4M                (0x2 << 4)
index 7c69bf259caa7ca3258dfd5d0441dc71d1f6bf21..141ca176c3974719fae122745aaee82ef2c4b276 100644 (file)
@@ -506,12 +506,7 @@ static void intel_i830_init_gtt_entries(void)
                        break;
                }
        } else {
-               /* G33's GTT stolen memory is separate from gfx data
-                * stolen memory.
-                */
-               if (IS_G33)
-                       size = 0;
-               switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+               switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
                case I855_GMCH_GMS_STOLEN_1M:
                        gtt_entries = MB(1) - KB(size);
                        break;
index 737088bd07807a9d875b9c035e509f446b039139..28b98733beb8ffc7b6522e64fcbf1f2282fa36ce 100644 (file)
@@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define I915REG_INT_MASK_R     0x020a8
 #define I915REG_INT_ENABLE_R   0x020a0
 
+#define I915REG_PIPEASTAT      0x70024
+#define I915REG_PIPEBSTAT      0x71024
+
+#define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
+#define I915_VBLANK_CLEAR              (1UL<<1)
+
 #define SRX_INDEX              0x3c4
 #define SRX_DATA               0x3c5
 #define SR01                   1
index 4b4b2ce8986345a5f2d1eedb179756ba0e99d382..bb8e9e9c820156e849cbd6ece7485de88767baff 100644 (file)
@@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u16 temp;
+       u32 pipea_stats, pipeb_stats;
+
+       pipea_stats = I915_READ(I915REG_PIPEASTAT);
+       pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
 
        temp = I915_READ16(I915REG_INT_IDENTITY_R);
 
@@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                return IRQ_NONE;
 
        I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+       (void) I915_READ16(I915REG_INT_IDENTITY_R);
+       DRM_READMEMORYBARRIER();
 
        dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
@@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 
                if (dev_priv->swaps_pending > 0)
                        drm_locked_tasklet(dev, i915_vblank_tasklet);
+               I915_WRITE(I915REG_PIPEASTAT,
+                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+                       I915_VBLANK_CLEAR);
+               I915_WRITE(I915REG_PIPEBSTAT,
+                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+                       I915_VBLANK_CLEAR);
        }
 
        return IRQ_HANDLED;
index 7ecffc9c738f98b56693f61aa4150bfeb655f712..4c16778e3f846dd97937a79e2c4b38bd30f5accc 100644 (file)
@@ -62,6 +62,8 @@
 
 static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
+/* This clocksource driver currently only works on ia64 */
+#ifdef CONFIG_IA64
 static void __iomem *hpet_mctr;
 
 static cycle_t read_hpet(void)
@@ -79,6 +81,7 @@ static struct clocksource clocksource_hpet = {
         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 static struct clocksource *hpet_clocksource;
+#endif
 
 /* A lock for concurrent access by app and isr hpet activity. */
 static DEFINE_SPINLOCK(hpet_lock);
@@ -943,14 +946,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                        printk(KERN_DEBUG "%s: 0x%lx is busy\n",
                                __FUNCTION__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
-                       return -EBUSY;
+                       return AE_ALREADY_EXISTS;
                }
        } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
                struct acpi_resource_fixed_memory32 *fixmem32;
 
                fixmem32 = &res->data.fixed_memory32;
                if (!fixmem32)
-                       return -EINVAL;
+                       return AE_NO_MEMORY;
 
                hdp->hd_phys_address = fixmem32->address;
                hdp->hd_address = ioremap(fixmem32->address,
@@ -960,7 +963,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                        printk(KERN_DEBUG "%s: 0x%lx is busy\n",
                                __FUNCTION__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
-                       return -EBUSY;
+                       return AE_ALREADY_EXISTS;
                }
        } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
                struct acpi_resource_extended_irq *irqp;
index 9b07f78510611197c86fac1d76febf997d1200f1..dd441ff4af56662da423fbd5fc88f1ae8819ac42 100644 (file)
@@ -2215,7 +2215,8 @@ static int ipmi_pci_resume(struct pci_dev *pdev)
 
 static struct pci_device_id ipmi_pci_devices[] = {
        { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
-       { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }
+       { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
+       { 0, }
 };
 MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
 
index c08a4152ee8fc2f5df6032221d519beafb4837f0..04ac155d3a0794cf3d7958722e1532e198aa2c52 100644 (file)
@@ -67,7 +67,7 @@
 /*
  * Page types allocated by the device.
  */
-enum {
+enum mspec_page_type {
        MSPEC_FETCHOP = 1,
        MSPEC_CACHED,
        MSPEC_UNCACHED
@@ -83,15 +83,25 @@ static int is_sn2;
  * One of these structures is allocated when an mspec region is mmaped. The
  * structure is pointed to by the vma->vm_private_data field in the vma struct.
  * This structure is used to record the addresses of the mspec pages.
+ * This structure is shared by all vma's that are split off from the
+ * original vma when split_vma()'s are done.
+ *
+ * The refcnt is incremented atomically because mm->mmap_sem does not
+ * protect in fork case where multiple tasks share the vma_data.
  */
 struct vma_data {
        atomic_t refcnt;        /* Number of vmas sharing the data. */
-       spinlock_t lock;        /* Serialize access to the vma. */
+       spinlock_t lock;        /* Serialize access to this structure. */
        int count;              /* Number of pages allocated. */
-       int type;               /* Type of pages allocated. */
+       enum mspec_page_type type; /* Type of pages allocated. */
+       int flags;              /* See VMD_xxx below. */
+       unsigned long vm_start; /* Original (unsplit) base. */
+       unsigned long vm_end;   /* Original (unsplit) end. */
        unsigned long maddr[0]; /* Array of MSPEC addresses. */
 };
 
+#define VMD_VMALLOCED 0x1      /* vmalloc'd rather than kmalloc'd */
+
 /* used on shub2 to clear FOP cache in the HUB */
 static unsigned long scratch_page[MAX_NUMNODES];
 #define SH2_AMO_CACHE_ENTRIES  4
@@ -129,8 +139,8 @@ mspec_zero_block(unsigned long addr, int len)
  * mspec_open
  *
  * Called when a device mapping is created by a means other than mmap
- * (via fork, etc.).  Increments the reference count on the underlying
- * mspec data so it is not freed prematurely.
+ * (via fork, munmap, etc.).  Increments the reference count on the
+ * underlying mspec data so it is not freed prematurely.
  */
 static void
 mspec_open(struct vm_area_struct *vma)
@@ -145,43 +155,43 @@ mspec_open(struct vm_area_struct *vma)
  * mspec_close
  *
  * Called when unmapping a device mapping. Frees all mspec pages
- * belonging to the vma.
+ * belonging to all the vma's sharing this vma_data structure.
  */
 static void
 mspec_close(struct vm_area_struct *vma)
 {
        struct vma_data *vdata;
-       int i, pages, result, vdata_size;
+       int index, last_index;
+       unsigned long my_page;
 
        vdata = vma->vm_private_data;
+
        if (!atomic_dec_and_test(&vdata->refcnt))
                return;
 
-       pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-       vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
-       for (i = 0; i < pages; i++) {
-               if (vdata->maddr[i] == 0)
+       last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT;
+       for (index = 0; index < last_index; index++) {
+               if (vdata->maddr[index] == 0)
                        continue;
                /*
                 * Clear the page before sticking it back
                 * into the pool.
                 */
-               result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
-               if (!result)
-                       uncached_free_page(vdata->maddr[i]);
+               my_page = vdata->maddr[index];
+               vdata->maddr[index] = 0;
+               if (!mspec_zero_block(my_page, PAGE_SIZE))
+                       uncached_free_page(my_page);
                else
                        printk(KERN_WARNING "mspec_close(): "
-                              "failed to zero page %i\n",
-                              result);
+                              "failed to zero page %ld\n", my_page);
        }
 
-       if (vdata_size <= PAGE_SIZE)
-               kfree(vdata);
-       else
+       if (vdata->flags & VMD_VMALLOCED)
                vfree(vdata);
+       else
+               kfree(vdata);
 }
 
-
 /*
  * mspec_nopfn
  *
@@ -195,7 +205,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
        int index;
        struct vma_data *vdata = vma->vm_private_data;
 
-       index = (address - vma->vm_start) >> PAGE_SHIFT;
+       BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
+       index = (address - vdata->vm_start) >> PAGE_SHIFT;
        maddr = (volatile unsigned long) vdata->maddr[index];
        if (maddr == 0) {
                maddr = uncached_alloc_page(numa_node_id());
@@ -237,10 +248,11 @@ static struct vm_operations_struct mspec_vm_ops = {
  * underlying pages.
  */
 static int
-mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
+mspec_mmap(struct file *file, struct vm_area_struct *vma,
+                                       enum mspec_page_type type)
 {
        struct vma_data *vdata;
-       int pages, vdata_size;
+       int pages, vdata_size, flags = 0;
 
        if (vma->vm_pgoff != 0)
                return -EINVAL;
@@ -255,12 +267,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
        vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
        if (vdata_size <= PAGE_SIZE)
                vdata = kmalloc(vdata_size, GFP_KERNEL);
-       else
+       else {
                vdata = vmalloc(vdata_size);
+               flags = VMD_VMALLOCED;
+       }
        if (!vdata)
                return -ENOMEM;
        memset(vdata, 0, vdata_size);
 
+       vdata->vm_start = vma->vm_start;
+       vdata->vm_end = vma->vm_end;
+       vdata->flags = flags;
        vdata->type = type;
        spin_lock_init(&vdata->lock);
        vdata->refcnt = ATOMIC_INIT(1);
index 397c714cf2ba78b517a363f0bef2eb674309cb13..af274e5a25ee5ec57533eff3a4e869feac831924 100644 (file)
@@ -1550,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
         *      As close as possible to RFC 793, which
         *      suggests using a 250 kHz clock.
         *      Further reading shows this assumes 2 Mb/s networks.
-        *      For 10 Gb/s Ethernet, a 1 GHz clock is appropriate.
-        *      That's funny, Linux has one built in!  Use it!
-        *      (Networks are faster now - should this be increased?)
+        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
+        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
+        *      we also need to limit the resolution so that the u32 seq
+        *      overlaps less than one time per MSL (2 minutes).
+        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
         */
-       seq += ktime_get_real().tv64;
+       seq += ktime_get_real().tv64 >> 6;
 #if 0
        printk("init_seq(%lx, %lx, %d, %d) = %d\n",
               saddr, daddr, sport, dport, seq);
index c6f6f42097391b20f434a669ae6b0f263fda63ee..7a61a2a9aafe3879dc8a0e443fd7d1379e7e493e 100644 (file)
@@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                /*
                 * Switching-from response
                 */
+               acquire_console_sem();
                if (vc->vt_newvt >= 0) {
                        if (arg == 0)
                                /*
@@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                 * complete the switch.
                                 */
                                int newvt;
-                               acquire_console_sem();
                                newvt = vc->vt_newvt;
                                vc->vt_newvt = -1;
                                i = vc_allocate(newvt);
@@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                 * other console switches..
                                 */
                                complete_change_console(vc_cons[newvt].d);
-                               release_console_sem();
                        }
                }
 
@@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        /*
                         * If it's just an ACK, ignore it
                         */
-                       if (arg != VT_ACKACQ)
+                       if (arg != VT_ACKACQ) {
+                               release_console_sem();
                                return -EINVAL;
+                       }
                }
+               release_console_sem();
 
                return 0;
 
@@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
 
 /*
  * Sleeps until a vt is activated, or the task is interrupted. Returns
- * 0 if activation, -EINTR if interrupted.
+ * 0 if activation, -EINTR if interrupted by a signal handler.
  */
 int vt_waitactive(int vt)
 {
@@ -1055,7 +1057,7 @@ int vt_waitactive(int vt)
                        break;
                }
                release_console_sem();
-               retval = -EINTR;
+               retval = -ERESTARTNOHAND;
                if (signal_pending(current))
                        break;
                schedule();
@@ -1208,15 +1210,18 @@ void change_console(struct vc_data *new_vc)
                /*
                 * Send the signal as privileged - kill_pid() will
                 * tell us if the process has gone or something else
-                * is awry
+                * is awry.
+                *
+                * We need to set vt_newvt *before* sending the signal or we
+                * have a race.
                 */
+               vc->vt_newvt = new_vc->vc_num;
                if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
                        /*
                         * It worked. Mark the vt to switch to and
                         * return. The process needs to send us a
                         * VT_RELDISP ioctl to complete the switch.
                         */
-                       vc->vt_newvt = new_vc->vc_num;
                        return;
                }
 
index d011a76f8e7a4d032820ffbaafd7d0c544e1a259..fe9e768cfbc4d28aa462d73fb60d79b689d160e9 100644 (file)
@@ -11,7 +11,8 @@ config FIREWIRE
          This is the "Juju" FireWire stack, a new alternative implementation
          designed for robustness and simplicity.  You can build either this
          stack, or the classic stack (the ieee1394 driver, ohci1394 etc.)
-         or both.
+         or both.  Please read http://wiki.linux1394.org/JujuMigration before
+         you enable the new stack.
 
          To compile this driver as a module, say M here: the module will be
          called firewire-core.  It functionally replaces ieee1394, raw1394,
index eba1adbc1b6a0733137085f67a6933ccb4ebba13..4754769eda9781ee2531b46f8bcbf42167e41685 100644 (file)
@@ -487,6 +487,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
  */
 static const struct drive_list_entry hpa_list[] = {
        { "ST340823A",  NULL },
+       { "ST320413A",  NULL },
        { NULL,         NULL }
 };
 
index 4b13cd9a027d5f9dc1d2ffc22dec940d7387c2ce..2fb047b898aa7d94279fa326327131b7b26d5bfe 100644 (file)
@@ -1546,6 +1546,7 @@ static struct pci_device_id pmac_ide_pci_match[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {},
 };
 
 static struct pci_driver pmac_ide_pci_driver = {
@@ -1802,9 +1803,7 @@ pmac_ide_dma_check(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
        ide_hwif_t *hwif = HWIF(drive);
-       pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
        int enable = 1;
-       int map;
        drive->using_dma = 0;
        
        if (drive->media == ide_floppy)
index ee45259573c8b3c9450637e07047bb5f58ab9d2b..98fd985a32ffb003affce760342a42a0d54709e6 100644 (file)
@@ -1273,7 +1273,7 @@ static void __exit ieee1394_cleanup(void)
        unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-fs_initcall(ieee1394_init); /* same as ohci1394 */
+module_init(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
index 5667c8102efc0dcc56d14a786e602a7437ab4596..372c5c16eb3180df3940d13d8f602acf4c1d97aa 100644 (file)
@@ -3537,7 +3537,5 @@ static int __init ohci1394_init(void)
        return pci_register_driver(&ohci1394_pci_driver);
 }
 
-/* Register before most other device drivers.
- * Useful for remote debugging via physical DMA, e.g. using firescope. */
-fs_initcall(ohci1394_init);
+module_init(ohci1394_init);
 module_exit(ohci1394_cleanup);
index ba0428d872aa4bc0a6cc2993049c6f60f2eba25e..85c51bdc36f1d403130fdf81655c51c7eca6e817 100644 (file)
@@ -1211,12 +1211,42 @@ static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
        dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
 }
 
-static void set_data_seg(struct mlx4_wqe_data_seg *dseg,
-                        struct ib_sge *sg)
+static void set_mlx_icrc_seg(void *dseg)
+{
+       u32 *t = dseg;
+       struct mlx4_wqe_inline_seg *iseg = dseg;
+
+       t[1] = 0;
+
+       /*
+        * Need a barrier here before writing the byte_count field to
+        * make sure that all the data is visible before the
+        * byte_count field is set.  Otherwise, if the segment begins
+        * a new cacheline, the HCA prefetcher could grab the 64-byte
+        * chunk and get a valid (!= * 0xffffffff) byte count but
+        * stale data, and end up sending the wrong data.
+        */
+       wmb();
+
+       iseg->byte_count = cpu_to_be32((1 << 31) | 4);
+}
+
+static void set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
 {
-       dseg->byte_count = cpu_to_be32(sg->length);
        dseg->lkey       = cpu_to_be32(sg->lkey);
        dseg->addr       = cpu_to_be64(sg->addr);
+
+       /*
+        * Need a barrier here before writing the byte_count field to
+        * make sure that all the data is visible before the
+        * byte_count field is set.  Otherwise, if the segment begins
+        * a new cacheline, the HCA prefetcher could grab the 64-byte
+        * chunk and get a valid (!= * 0xffffffff) byte count but
+        * stale data, and end up sending the wrong data.
+        */
+       wmb();
+
+       dseg->byte_count = cpu_to_be32(sg->length);
 }
 
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
@@ -1225,6 +1255,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
        struct mlx4_ib_qp *qp = to_mqp(ibqp);
        void *wqe;
        struct mlx4_wqe_ctrl_seg *ctrl;
+       struct mlx4_wqe_data_seg *dseg;
        unsigned long flags;
        int nreq;
        int err = 0;
@@ -1324,22 +1355,27 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        break;
                }
 
-               for (i = 0; i < wr->num_sge; ++i) {
-                       set_data_seg(wqe, wr->sg_list + i);
+               /*
+                * Write data segments in reverse order, so as to
+                * overwrite cacheline stamp last within each
+                * cacheline.  This avoids issues with WQE
+                * prefetching.
+                */
 
-                       wqe  += sizeof (struct mlx4_wqe_data_seg);
-                       size += sizeof (struct mlx4_wqe_data_seg) / 16;
-               }
+               dseg = wqe;
+               dseg += wr->num_sge - 1;
+               size += wr->num_sge * (sizeof (struct mlx4_wqe_data_seg) / 16);
 
                /* Add one more inline data segment for ICRC for MLX sends */
-               if (qp->ibqp.qp_type == IB_QPT_SMI || qp->ibqp.qp_type == IB_QPT_GSI) {
-                       ((struct mlx4_wqe_inline_seg *) wqe)->byte_count =
-                               cpu_to_be32((1 << 31) | 4);
-                       ((u32 *) wqe)[1] = 0;
-                       wqe  += sizeof (struct mlx4_wqe_data_seg);
+               if (unlikely(qp->ibqp.qp_type == IB_QPT_SMI ||
+                            qp->ibqp.qp_type == IB_QPT_GSI)) {
+                       set_mlx_icrc_seg(dseg + 1);
                        size += sizeof (struct mlx4_wqe_data_seg) / 16;
                }
 
+               for (i = wr->num_sge - 1; i >= 0; --i, --dseg)
+                       set_data_seg(dseg, wr->sg_list + i);
+
                ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
                                    MLX4_WQE_CTRL_FENCE : 0) | size;
 
index e2abe18e575df2d89e2de4189124f2fbb4abb35f..7c662ee594a3e9fdf85761765ae6776ddecf05d9 100644 (file)
@@ -277,7 +277,7 @@ config JOYSTICK_XPAD_FF
 
 config JOYSTICK_XPAD_LEDS
        bool "LED Support for Xbox360 controller 'BigX' LED"
-       depends on LEDS_CLASS && JOYSTICK_XPAD
+       depends on JOYSTICK_XPAD && (LEDS_CLASS=y || LEDS_CLASS=JOYSTICK_XPAD)
        ---help---
          This option enables support for the LED which surrounds the Big X on
          XBox 360 controller.
index 2bea1b2c631c81274b80304f3e4be11216013068..a1804bfdbb8ce38510f783c233682e12e5dabac8 100644 (file)
@@ -328,6 +328,7 @@ static void atp_complete(struct urb* urb)
 {
        int x, y, x_z, y_z, x_f, y_f;
        int retval, i, j;
+       int key;
        struct atp *dev = urb->context;
 
        switch (urb->status) {
@@ -468,6 +469,7 @@ static void atp_complete(struct urb* urb)
                              ATP_XFACT, &x_z, &x_f);
        y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
                              ATP_YFACT, &y_z, &y_f);
+       key = dev->data[dev->datalen - 1] & 1;
 
        if (x && y) {
                if (dev->x_old != -1) {
@@ -505,7 +507,7 @@ static void atp_complete(struct urb* urb)
                   the first touch unless reinitialised. Do so if it's been
                   idle for a while in order to avoid waking the kernel up
                   several hundred times a second */
-               if (atp_is_geyser_3(dev)) {
+               if (!key && atp_is_geyser_3(dev)) {
                        dev->idlecount++;
                        if (dev->idlecount == 10) {
                                dev->valid = 0;
@@ -514,7 +516,7 @@ static void atp_complete(struct urb* urb)
                }
        }
 
-       input_report_key(dev->input, BTN_LEFT, dev->data[dev->datalen - 1] & 1);
+       input_report_key(dev->input, BTN_LEFT, key);
        input_sync(dev->input);
 
 exit:
index ec5f4046412fa564644619175c59373ab4ca39e3..4910bca52640ed0bf67d9833a9595f23c41f44fa 100644 (file)
@@ -1135,7 +1135,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
                        if (count > dev->drv[drvidx]->stavail)
                                count = dev->drv[drvidx]->stavail;
                        len = dev->drv[drvidx]->interface->readstat(buf, count,
-                                               drvidx, isdn_minor2chan(minor));
+                               drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL));
                        if (len < 0) {
                                retval = len;
                                goto out;
@@ -1207,7 +1207,8 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off
                 */
                if (dev->drv[drvidx]->interface->writecmd)
                        retval = dev->drv[drvidx]->interface->
-                               writecmd(buf, count, drvidx, isdn_minor2chan(minor));
+                               writecmd(buf, count, drvidx,
+                               isdn_minor2chan(minor - ISDN_MINOR_CTRL));
                else
                        retval = count;
                goto out;
index 7b64fd4aa2f3d4c99e6f4ffef4c3cdcb48ab9a90..0a419a0de603a352cb2411cfacbb005f17590d9c 100644 (file)
@@ -6,7 +6,8 @@ menuconfig VIRTUALIZATION
        depends on X86
        default y
        ---help---
-         Say Y here to get to see options for virtualization guest drivers.
+         Say Y here to get to see options for using your Linux host to run other
+         operating systems inside virtual machines (guests).
          This option alone does not add any kernel code.
 
          If you say N, all options in this submenu will be skipped and disabled.
index f182c6a36209c4c35b5f0c1b5bba3e5bf1b57f0c..1ddcd5cd20f6070b72428622b80f531f3ac9fe08 100644 (file)
@@ -22,8 +22,9 @@
        jmp lguest_init
 
 /*G:055 We create a macro which puts the assembler code between lgstart_ and
- * lgend_ markers.  These templates end up in the .init.text section, so they
- * are discarded after boot. */
+ * lgend_ markers.  These templates are put in the .text section: they can't be
+ * discarded after boot as we may need to patch modules, too. */
+.text
 #define LGUEST_PATCH(name, insns...)                   \
        lgstart_##name: insns; lgend_##name:;           \
        .globl lgstart_##name; .globl lgend_##name
@@ -34,7 +35,6 @@ LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled)
 LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax)
 /*:*/
 
-.text
 /* These demark the EIP range where host should never deliver interrupts. */
 .global lguest_noirq_start
 .global lguest_noirq_end
index 4d63773ee73a634fe31d72eb04edad4d8942f8e2..f96dea975fa50d94e805c40c46be82df7cfe80bc 100644 (file)
@@ -514,7 +514,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
        struct stripe_head *sh = stripe_head_ref;
        struct bio *return_bi = NULL;
        raid5_conf_t *conf = sh->raid_conf;
-       int i, more_to_read = 0;
+       int i;
 
        pr_debug("%s: stripe %llu\n", __FUNCTION__,
                (unsigned long long)sh->sector);
@@ -522,16 +522,14 @@ static void ops_complete_biofill(void *stripe_head_ref)
        /* clear completed biofills */
        for (i = sh->disks; i--; ) {
                struct r5dev *dev = &sh->dev[i];
-               /* check if this stripe has new incoming reads */
-               if (dev->toread)
-                       more_to_read++;
 
                /* acknowledge completion of a biofill operation */
-               /* and check if we need to reply to a read request
-               */
-               if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
+               /* and check if we need to reply to a read request,
+                * new R5_Wantfill requests are held off until
+                * !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending)
+                */
+               if (test_and_clear_bit(R5_Wantfill, &dev->flags)) {
                        struct bio *rbi, *rbi2;
-                       clear_bit(R5_Wantfill, &dev->flags);
 
                        /* The access to dev->read is outside of the
                         * spin_lock_irq(&conf->device_lock), but is protected
@@ -558,8 +556,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
 
        return_io(return_bi);
 
-       if (more_to_read)
-               set_bit(STRIPE_HANDLE, &sh->state);
+       set_bit(STRIPE_HANDLE, &sh->state);
        release_stripe(sh);
 }
 
index 0285c4a830eb61938d044adc965bf0bef4c49784..66ea3cbc369c209f2ae4cc52d03253479f16052b 100644 (file)
@@ -754,9 +754,11 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
                ivtv_yuv_close(itv);
        }
        if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV)
-           itv->output_mode = OUT_NONE;
+               itv->output_mode = OUT_NONE;
+       else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV)
+               itv->output_mode = OUT_NONE;
        else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG)
-           itv->output_mode = OUT_NONE;
+               itv->output_mode = OUT_NONE;
 
        itv->speed = 0;
        clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
index 380564cd3317d222ea2908c7e6e6d8ef1a12e43b..f09eb102731b25693e818eb83700120ad16f68ff 100644 (file)
@@ -1081,6 +1081,7 @@ struct usb_device_id usbvision_table [] = {
        { USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL },
        { USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM },
        { USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV },
+       { },    /* terminate list */
 };
 
 MODULE_DEVICE_TABLE (usb, usbvision_table);
index e3371f972240a896b930fd03107f12882aedf064..0cb006f2943da5abfb08bc604a25097f18b4665b 100644 (file)
@@ -1387,7 +1387,6 @@ static const struct file_operations usbvision_fops = {
        .ioctl          = video_ioctl2,
        .llseek         = no_llseek,
 /*     .poll          = video_poll, */
-       .mmap          = usbvision_v4l2_mmap,
        .compat_ioctl  = v4l_compat_ioctl32,
 };
 static struct video_device usbvision_video_template = {
@@ -1413,7 +1412,7 @@ static struct video_device usbvision_video_template = {
        .vidioc_s_input       = vidioc_s_input,
        .vidioc_queryctrl     = vidioc_queryctrl,
        .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_g_audio       = vidioc_s_audio,
+       .vidioc_s_audio       = vidioc_s_audio,
        .vidioc_g_ctrl        = vidioc_g_ctrl,
        .vidioc_s_ctrl        = vidioc_s_ctrl,
        .vidioc_streamon      = vidioc_streamon,
@@ -1459,7 +1458,7 @@ static struct video_device usbvision_radio_template=
        .vidioc_s_input       = vidioc_s_input,
        .vidioc_queryctrl     = vidioc_queryctrl,
        .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_g_audio       = vidioc_s_audio,
+       .vidioc_s_audio       = vidioc_s_audio,
        .vidioc_g_ctrl        = vidioc_g_ctrl,
        .vidioc_s_ctrl        = vidioc_s_ctrl,
        .vidioc_g_tuner       = vidioc_g_tuner,
index cff969d05d4a1824cb18fda1808f89a9f9700000..6f32a35eb1069142ade478b2860d2c0297568827 100644 (file)
@@ -816,7 +816,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
 }
 
 static struct pci_device_id cafe_nand_tbl[] = {
-       { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
+       { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
+       { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
index 854d80c330ec8ab4449bddb23a1af1bf43927f0c..66eed22cbd21963e70b7edddc9929ef192dae186 100644 (file)
@@ -54,8 +54,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.6.4"
-#define DRV_MODULE_RELDATE     "August 3, 2007"
+#define DRV_MODULE_VERSION     "1.6.5"
+#define DRV_MODULE_RELDATE     "September 20, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -6727,7 +6727,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        } else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
                   CHIP_NUM(bp) == CHIP_NUM_5708)
                bp->phy_flags |= PHY_CRC_FIX_FLAG;
-       else if (CHIP_ID(bp) == CHIP_ID_5709_A0)
+       else if (CHIP_ID(bp) == CHIP_ID_5709_A0 ||
+                CHIP_ID(bp) == CHIP_ID_5709_A1)
                bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG;
 
        if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
index 4c3785c9d4b811067b5af3dafd0de33224591bae..9ecc3adcf6c189117e038426e0fc0550f08f60bd 100644 (file)
@@ -1726,6 +1726,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
        case E1000_DEV_ID_82571EB_QUAD_COPPER:
        case E1000_DEV_ID_82571EB_QUAD_FIBER:
        case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
+       case E1000_DEV_ID_82571PT_QUAD_COPPER:
        case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
                /* quad port adapters only support WoL on port A */
                if (!adapter->quad_port_a) {
index ba120f7fb0bef2c619475fcd5742170f02b44124..8604adbe351cc07dc2b004896af8c4cd338d9331 100644 (file)
@@ -387,6 +387,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
        case E1000_DEV_ID_82571EB_SERDES_DUAL:
        case E1000_DEV_ID_82571EB_SERDES_QUAD:
        case E1000_DEV_ID_82571EB_QUAD_COPPER:
+       case E1000_DEV_ID_82571PT_QUAD_COPPER:
        case E1000_DEV_ID_82571EB_QUAD_FIBER:
        case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
                hw->mac_type = e1000_82571;
index fe8714655c90445808000870543f5539d70e1dfa..07f0ea73676e90e4ad00555447108c03b2f4ef60 100644 (file)
@@ -475,6 +475,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
 #define E1000_DEV_ID_82571EB_FIBER       0x105F
 #define E1000_DEV_ID_82571EB_SERDES      0x1060
 #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
 #define E1000_DEV_ID_82571EB_QUAD_FIBER  0x10A5
 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE  0x10BC
 #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
index 4a225950fb43f6cbe30feff14945857305825dbe..e7c8951f47fa94d3e0fae7551f5e6d84ef16676a 100644 (file)
@@ -108,6 +108,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
        INTEL_E1000_ETHERNET_DEVICE(0x10BC),
        INTEL_E1000_ETHERNET_DEVICE(0x10C4),
        INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+       INTEL_E1000_ETHERNET_DEVICE(0x10D5),
        INTEL_E1000_ETHERNET_DEVICE(0x10D9),
        INTEL_E1000_ETHERNET_DEVICE(0x10DA),
        /* required last entry */
@@ -1101,6 +1102,7 @@ e1000_probe(struct pci_dev *pdev,
        case E1000_DEV_ID_82571EB_QUAD_COPPER:
        case E1000_DEV_ID_82571EB_QUAD_FIBER:
        case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
+       case E1000_DEV_ID_82571PT_QUAD_COPPER:
                /* if quad port adapter, disable WoL on all but port A */
                if (global_quad_port_a != 0)
                        adapter->eeprom_wol = 0;
index 6a117e9968cb5dd09e91ae4425b3cd3b27e9d35c..315335671f0f06f2a2f9357d17c7ca8a9c4f8296 100644 (file)
@@ -534,7 +534,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
        }
 
        /* PHY status changed */
-       if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) {
+       if (eth_int_cause_ext & (ETH_INT_CAUSE_PHY | ETH_INT_CAUSE_STATE)) {
                struct ethtool_cmd cmd;
 
                if (mii_link_ok(&mp->mii)) {
@@ -1357,7 +1357,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 #endif
 
        dev->watchdog_timeo = 2 * HZ;
-       dev->tx_queue_len = mp->tx_ring_size;
        dev->base_addr = 0;
        dev->change_mtu = mv643xx_eth_change_mtu;
        dev->do_ioctl = mv643xx_eth_do_ioctl;
@@ -2768,8 +2767,6 @@ static const struct ethtool_ops mv643xx_ethtool_ops = {
        .get_stats_count        = mv643xx_get_stats_count,
        .get_ethtool_stats      = mv643xx_get_ethtool_stats,
        .get_strings            = mv643xx_get_strings,
-       .get_stats_count        = mv643xx_get_stats_count,
-       .get_ethtool_stats      = mv643xx_get_ethtool_stats,
        .nway_reset             = mv643xx_eth_nway_restart,
 };
 
index 82f8c0cbfb640fafd0e90b8a429e0283ed6622f3..565b96696acab9e131fb275dca99430e3b88b824 100644 (file)
@@ -64,7 +64,9 @@
 #define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
 #define ETH_INT_CAUSE_TX       (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
 #define ETH_INT_CAUSE_PHY      0x00010000
-#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY)
+#define ETH_INT_CAUSE_STATE    0x00100000
+#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \
+                                       ETH_INT_CAUSE_STATE)
 
 #define ETH_INT_MASK_ALL       0x00000000
 #define ETH_INT_MASK_ALL_EXT   0x00000000
index 1c42266bf88965139244818f49fcca958d1611ad..556962f9612d45ea3f6cfbf90868d0f069fe4e5f 100644 (file)
@@ -3094,9 +3094,12 @@ static void myri10ge_remove(struct pci_dev *pdev)
 }
 
 #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E     0x0008
+#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9   0x0009
 
 static struct pci_device_id myri10ge_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
+       {PCI_DEVICE
+        (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)},
        {0},
 };
 
index c06cae3f0b564c3240058f4a97c3656d47e9bf27..503f2685fb73c434ae4a2d6d98be4f03a3d4b7d9 100644 (file)
@@ -116,7 +116,7 @@ struct el3_private {
     spinlock_t         lock;
 };
 
-static const char *if_names[] = { "auto", "10base2", "10baseT", "AUI" };
+static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
 
 /*====================================================================*/
 
index 0cc4369cacba77778a9e4a7a92a1338041f94cfb..cb230f44d6fc3418cd899c42a76552a0091e9ee4 100644 (file)
@@ -409,6 +409,7 @@ int phy_mii_ioctl(struct phy_device *phydev,
 
        return 0;
 }
+EXPORT_SYMBOL(phy_mii_ioctl);
 
 /**
  * phy_start_aneg - start auto-negotiation for this PHY device
index f79cf87a2bff555aef80eba31da6c17eb340d65c..c0b6d19d1457598ba7a83738a194400344725197 100644 (file)
@@ -136,7 +136,7 @@ struct ppp_mppe_state {
  * Key Derivation, from RFC 3078, RFC 3079.
  * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
  */
-static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey)
+static void get_new_key_from_sha(struct ppp_mppe_state * state)
 {
        struct hash_desc desc;
        struct scatterlist sg[4];
@@ -153,8 +153,6 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I
        desc.flags = 0;
 
        crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest);
-
-       memcpy(InterimKey, state->sha1_digest, state->keylen);
 }
 
 /*
@@ -163,21 +161,21 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I
  */
 static void mppe_rekey(struct ppp_mppe_state * state, int initial_key)
 {
-       unsigned char InterimKey[MPPE_MAX_KEY_LEN];
        struct scatterlist sg_in[1], sg_out[1];
        struct blkcipher_desc desc = { .tfm = state->arc4 };
 
-       get_new_key_from_sha(state, InterimKey);
+       get_new_key_from_sha(state);
        if (!initial_key) {
-               crypto_blkcipher_setkey(state->arc4, InterimKey, state->keylen);
-               setup_sg(sg_in, InterimKey, state->keylen);
+               crypto_blkcipher_setkey(state->arc4, state->sha1_digest,
+                                       state->keylen);
+               setup_sg(sg_in, state->sha1_digest, state->keylen);
                setup_sg(sg_out, state->session_key, state->keylen);
                if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
                                             state->keylen) != 0) {
                    printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n");
                }
        } else {
-               memcpy(state->session_key, InterimKey, state->keylen);
+               memcpy(state->session_key, state->sha1_digest, state->keylen);
        }
        if (state->keylen == 8) {
                /* See RFC 3078 */
index 0d7f570b9a545eca66557ff3e903617a9f5b54f2..9b30cd600a643af5ba54f6c47c9be9e15f6c8dbe 100644 (file)
@@ -879,8 +879,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
        dev->hard_header(skb, dev, ETH_P_PPP_SES,
                         po->pppoe_pa.remote, NULL, data_len);
 
-       if (dev_queue_xmit(skb) < 0)
-               goto abort;
+       dev_queue_xmit(skb);
 
        return 1;
 
index 266e8b38fe10004366e78f3bce482add5037b407..abe91cb595f4fe723a561282f90ed4a1090ec495 100644 (file)
@@ -491,44 +491,46 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
        u16 hdrflags;
        u16 tunnel_id, session_id;
        int length;
-       struct udphdr *uh;
+       int offset;
 
        tunnel = pppol2tp_sock_to_tunnel(sock);
        if (tunnel == NULL)
                goto error;
 
+       /* UDP always verifies the packet length. */
+       __skb_pull(skb, sizeof(struct udphdr));
+
        /* Short packet? */
-       if (skb->len < sizeof(struct udphdr)) {
+       if (!pskb_may_pull(skb, 12)) {
                PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
                       "%s: recv short packet (len=%d)\n", tunnel->name, skb->len);
                goto error;
        }
 
        /* Point to L2TP header */
-       ptr = skb->data + sizeof(struct udphdr);
+       ptr = skb->data;
 
        /* Get L2TP header flags */
        hdrflags = ntohs(*(__be16*)ptr);
 
        /* Trace packet contents, if enabled */
        if (tunnel->debug & PPPOL2TP_MSG_DATA) {
+               length = min(16u, skb->len);
+               if (!pskb_may_pull(skb, length))
+                       goto error;
+
                printk(KERN_DEBUG "%s: recv: ", tunnel->name);
 
-               for (length = 0; length < 16; length++)
-                       printk(" %02X", ptr[length]);
+               offset = 0;
+               do {
+                       printk(" %02X", ptr[offset]);
+               } while (++offset < length);
+
                printk("\n");
        }
 
        /* Get length of L2TP packet */
-       uh = (struct udphdr *) skb_transport_header(skb);
-       length = ntohs(uh->len) - sizeof(struct udphdr);
-
-       /* Too short? */
-       if (length < 12) {
-               PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
-                      "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length);
-               goto error;
-       }
+       length = skb->len;
 
        /* If type is control packet, it is handled by userspace. */
        if (hdrflags & L2TP_HDRFLAG_T) {
@@ -606,7 +608,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
                               "%s: recv data has no seq numbers when required. "
                               "Discarding\n", session->name);
                        session->stats.rx_seq_discards++;
-                       session->stats.rx_errors++;
                        goto discard;
                }
 
@@ -625,7 +626,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
                               "%s: recv data has no seq numbers when required. "
                               "Discarding\n", session->name);
                        session->stats.rx_seq_discards++;
-                       session->stats.rx_errors++;
                        goto discard;
                }
 
@@ -634,10 +634,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
        }
 
        /* If offset bit set, skip it. */
-       if (hdrflags & L2TP_HDRFLAG_O)
-               ptr += 2 + ntohs(*(__be16 *) ptr);
+       if (hdrflags & L2TP_HDRFLAG_O) {
+               offset = ntohs(*(__be16 *)ptr);
+               skb->transport_header += 2 + offset;
+               if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2))
+                       goto discard;
+       }
 
-       skb_pull(skb, ptr - skb->data);
+       __skb_pull(skb, skb_transport_offset(skb));
 
        /* Skip PPP header, if present.  In testing, Microsoft L2TP clients
         * don't send the PPP header (PPP header compression enabled), but
@@ -673,7 +677,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
                         */
                        if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
                                session->stats.rx_seq_discards++;
-                               session->stats.rx_errors++;
                                PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
                                       "%s: oos pkt %hu len %d discarded, "
                                       "waiting for %hu, reorder_q_len=%d\n",
@@ -698,6 +701,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
        return 0;
 
 discard:
+       session->stats.rx_errors++;
        kfree_skb(skb);
        sock_put(session->sock);
 
@@ -958,7 +962,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        int data_len = skb->len;
        struct inet_sock *inet;
        __wsum csum = 0;
-       struct sk_buff *skb2 = NULL;
        struct udphdr *uh;
        unsigned int len;
 
@@ -989,41 +992,30 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
         */
        headroom = NET_SKB_PAD + sizeof(struct iphdr) +
                sizeof(struct udphdr) + hdr_len + sizeof(ppph);
-       if (skb_headroom(skb) < headroom) {
-               skb2 = skb_realloc_headroom(skb, headroom);
-               if (skb2 == NULL)
-                       goto abort;
-       } else
-               skb2 = skb;
-
-       /* Check that the socket has room */
-       if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf)
-               skb_set_owner_w(skb2, sk_tun);
-       else
-               goto discard;
+       if (skb_cow_head(skb, headroom))
+               goto abort;
 
        /* Setup PPP header */
-       skb_push(skb2, sizeof(ppph));
-       skb2->data[0] = ppph[0];
-       skb2->data[1] = ppph[1];
+       __skb_push(skb, sizeof(ppph));
+       skb->data[0] = ppph[0];
+       skb->data[1] = ppph[1];
 
        /* Setup L2TP header */
-       skb_push(skb2, hdr_len);
-       pppol2tp_build_l2tp_header(session, skb2->data);
+       pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len));
 
        /* Setup UDP header */
        inet = inet_sk(sk_tun);
-       skb_push(skb2, sizeof(struct udphdr));
-       skb_reset_transport_header(skb2);
-       uh = (struct udphdr *) skb2->data;
+       __skb_push(skb, sizeof(*uh));
+       skb_reset_transport_header(skb);
+       uh = udp_hdr(skb);
        uh->source = inet->sport;
        uh->dest = inet->dport;
        uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
        uh->check = 0;
 
-       /* Calculate UDP checksum if configured to do so */
+       /* *BROKEN* Calculate UDP checksum if configured to do so */
        if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
-               csum = udp_csum_outgoing(sk_tun, skb2);
+               csum = udp_csum_outgoing(sk_tun, skb);
 
        /* Debug */
        if (session->send_seq)
@@ -1036,7 +1028,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 
        if (session->debug & PPPOL2TP_MSG_DATA) {
                int i;
-               unsigned char *datap = skb2->data;
+               unsigned char *datap = skb->data;
 
                printk(KERN_DEBUG "%s: xmit:", session->name);
                for (i = 0; i < data_len; i++) {
@@ -1049,18 +1041,18 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
                printk("\n");
        }
 
-       memset(&(IPCB(skb2)->opt), 0, sizeof(IPCB(skb2)->opt));
-       IPCB(skb2)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
-                              IPSKB_REROUTED);
-       nf_reset(skb2);
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
+                             IPSKB_REROUTED);
+       nf_reset(skb);
 
        /* Get routing info from the tunnel socket */
-       dst_release(skb2->dst);
-       skb2->dst = sk_dst_get(sk_tun);
+       dst_release(skb->dst);
+       skb->dst = sk_dst_get(sk_tun);
 
        /* Queue the packet to IP for output */
-       len = skb2->len;
-       rc = ip_queue_xmit(skb2, 1);
+       len = skb->len;
+       rc = ip_queue_xmit(skb, 1);
 
        /* Update stats */
        if (rc >= 0) {
@@ -1073,17 +1065,12 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
                session->stats.tx_errors++;
        }
 
-       /* Free the original skb */
-       kfree_skb(skb);
-
        return 1;
 
-discard:
-       /* Free the new skb. Caller will free original skb. */
-       if (skb2 != skb)
-               kfree_skb(skb2);
 abort:
-       return 0;
+       /* Free the original skb */
+       kfree_skb(skb);
+       return 1;
 }
 
 /*****************************************************************************
@@ -1326,12 +1313,14 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
                goto err;
        }
 
+       sk = sock->sk;
+
        /* Quick sanity checks */
-       err = -ESOCKTNOSUPPORT;
-       if (sock->type != SOCK_DGRAM) {
+       err = -EPROTONOSUPPORT;
+       if (sk->sk_protocol != IPPROTO_UDP) {
                PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
-                      "tunl %hu: fd %d wrong type, got %d, expected %d\n",
-                      tunnel_id, fd, sock->type, SOCK_DGRAM);
+                      "tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
+                      tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP);
                goto err;
        }
        err = -EAFNOSUPPORT;
@@ -1343,7 +1332,6 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
        }
 
        err = -ENOTCONN;
-       sk = sock->sk;
 
        /* Check if this socket has already been prepped */
        tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data;
index 69da95b5ad0c3ca51aac4ca58d1729681a8a9923..ea151315050c382ff096696d7ae2a3abd2a54949 100755 (executable)
@@ -2248,6 +2248,13 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
                qdev->rsp_consumer_index) && (work_done < work_to_do)) {
 
                net_rsp = qdev->rsp_current;
+               rmb();
+               /*
+                * Fix 4032 chipe undocumented "feature" where bit-8 is set if the
+                * inbound completion is for a VLAN.
+                */
+               if (qdev->device_id == QL3032_DEVICE_ID)
+                       net_rsp->opcode &= 0x7f;
                switch (net_rsp->opcode) {
 
                case OPCODE_OB_MAC_IOCB_FN0:
index b85ab4a8f2a3377354bf357940334be642f4a6ef..c76dd29c8e9a1ef8f17d60067c08a2c970d788e8 100644 (file)
@@ -1228,7 +1228,10 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
                return;
        }
 
-       /* phy config for RTL8169s mac_version C chip */
+       if ((tp->mac_version != RTL_GIGA_MAC_VER_02) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_03))
+               return;
+
        mdio_write(ioaddr, 31, 0x0001);                 //w 31 2 0 1
        mdio_write(ioaddr, 21, 0x1000);                 //w 21 15 0 1000
        mdio_write(ioaddr, 24, 0x65c7);                 //w 24 15 0 65c7
@@ -1915,7 +1918,11 @@ static void rtl_hw_start_8169(struct net_device *dev)
 
        rtl_set_rx_max_size(ioaddr);
 
-       rtl_set_rx_tx_config_registers(tp);
+       if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
+           (tp->mac_version == RTL_GIGA_MAC_VER_04))
+               rtl_set_rx_tx_config_registers(tp);
 
        tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
 
@@ -1938,6 +1945,14 @@ static void rtl_hw_start_8169(struct net_device *dev)
 
        rtl_set_rx_tx_desc_registers(tp, ioaddr);
 
+       if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
+           (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
+               RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+               rtl_set_rx_tx_config_registers(tp);
+       }
+
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
        /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
@@ -1952,8 +1967,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
 
        /* Enable all known interrupts by setting the interrupt mask. */
        RTL_W16(IntrMask, tp->intr_event);
-
-       RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
 }
 
 static void rtl_hw_start_8168(struct net_device *dev)
@@ -2567,6 +2580,15 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
                    (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
                        netif_wake_queue(dev);
                }
+               /*
+                * 8168 hack: TxPoll requests are lost when the Tx packets are
+                * too close. Let's kick an extra TxPoll request when a burst
+                * of start_xmit activity is detected (if it is not detected,
+                * it is slow enough). -- FR
+                */
+               smp_rmb();
+               if (tp->cur_tx != dirty_tx)
+                       RTL_W8(TxPoll, NPQ);
        }
 }
 
index 5d812de65d90a4d4467327ec675daf5d669d824c..ea117fc3d5e390c6da6b763a61f6d94a071c3c86 100644 (file)
@@ -51,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.17"
+#define DRV_VERSION            "1.18"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -118,12 +118,15 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
@@ -147,6 +150,7 @@ static const char *yukon2_name[] = {
        "Extreme",      /* 0xb5 */
        "EC",           /* 0xb6 */
        "FE",           /* 0xb7 */
+       "FE+",          /* 0xb8 */
 };
 
 static void sky2_set_multicast(struct net_device *dev);
@@ -217,8 +221,7 @@ static void sky2_power_on(struct sky2_hw *hw)
        else
                sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
-           hw->chip_id == CHIP_ID_YUKON_EX) {
+       if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
                u32 reg;
 
                sky2_pci_write32(hw, PCI_DEV_REG3, 0);
@@ -311,10 +314,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
        struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
        u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
 
-       if (sky2->autoneg == AUTONEG_ENABLE
-           && !(hw->chip_id == CHIP_ID_YUKON_XL
-                || hw->chip_id == CHIP_ID_YUKON_EC_U
-                || hw->chip_id == CHIP_ID_YUKON_EX)) {
+       if (sky2->autoneg == AUTONEG_ENABLE &&
+           !(hw->flags & SKY2_HW_NEWER_PHY)) {
                u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 
                ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -334,9 +335,19 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
        ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
        if (sky2_is_copper(hw)) {
-               if (hw->chip_id == CHIP_ID_YUKON_FE) {
+               if (!(hw->flags & SKY2_HW_GIGABIT)) {
                        /* enable automatic crossover */
                        ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
+
+                       if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+                           hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+                               u16 spec;
+
+                               /* Enable Class A driver for FE+ A0 */
+                               spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2);
+                               spec |= PHY_M_FESC_SEL_CL_A;
+                               gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
+                       }
                } else {
                        /* disable energy detect */
                        ctrl &= ~PHY_M_PC_EN_DET_MSK;
@@ -346,9 +357,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
                        /* downshift on PHY 88E1112 and 88E1149 is changed */
                        if (sky2->autoneg == AUTONEG_ENABLE
-                           && (hw->chip_id == CHIP_ID_YUKON_XL
-                               || hw->chip_id == CHIP_ID_YUKON_EC_U
-                               || hw->chip_id == CHIP_ID_YUKON_EX)) {
+                           && (hw->flags & SKY2_HW_NEWER_PHY)) {
                                /* set downshift counter to 3x and enable downshift */
                                ctrl &= ~PHY_M_PC_DSC_MSK;
                                ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
@@ -364,7 +373,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
        gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
 
        /* special setup for PHY 88E1112 Fiber */
-       if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) {
+       if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
                pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
 
                /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
@@ -455,7 +464,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
        gma_write16(hw, port, GM_GP_CTRL, reg);
 
-       if (hw->chip_id != CHIP_ID_YUKON_FE)
+       if (hw->flags & SKY2_HW_GIGABIT)
                gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
 
        gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
@@ -479,6 +488,23 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
                break;
 
+       case CHIP_ID_YUKON_FE_P:
+               /* Enable Link Partner Next Page */
+               ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+               ctrl |= PHY_M_PC_ENA_LIP_NP;
+
+               /* disable Energy Detect and enable scrambler */
+               ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
+               gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+               /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
+               ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
+                       PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
+                       PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
+
+               gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+               break;
+
        case CHIP_ID_YUKON_XL:
                pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
 
@@ -548,7 +574,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
                /* set page register to 0 */
                gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+       } else if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+                  hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+               /* apply workaround for integrated resistors calibration */
+               gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
+               gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
        } else if (hw->chip_id != CHIP_ID_YUKON_EX) {
+               /* no effect on Yukon-XL */
                gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
 
                if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
@@ -669,25 +701,25 @@ static void sky2_wol_init(struct sky2_port *sky2)
 
 static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
 {
-       if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+       struct net_device *dev = hw->dev[port];
+
+       if (dev->mtu <= ETH_DATA_LEN)
                sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                            TX_STFW_ENA |
-                            (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
-       } else {
-               if (hw->dev[port]->mtu > ETH_DATA_LEN) {
-                       /* set Tx GMAC FIFO Almost Empty Threshold */
-                       sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
-                                    (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+                            TX_JUMBO_DIS | TX_STFW_ENA);
 
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                                    TX_JUMBO_ENA | TX_STFW_DIS);
+       else if (hw->chip_id != CHIP_ID_YUKON_EC_U)
+               sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+                            TX_STFW_ENA | TX_JUMBO_ENA);
+       else {
+               /* set Tx GMAC FIFO Almost Empty Threshold */
+               sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+                            (ECU_JUMBO_WM << 16) | ECU_AE_THR);
 
-                       /* Can't do offload because of lack of store/forward */
-                       hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
-                                                    | NETIF_F_ALL_CSUM);
-               } else
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                                    TX_JUMBO_DIS | TX_STFW_ENA);
+               sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+                            TX_JUMBO_ENA | TX_STFW_DIS);
+
+               /* Can't do offload because of lack of store/forward */
+               dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
        }
 }
 
@@ -773,7 +805,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
        /* Configure Rx MAC FIFO */
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
        rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
-       if (hw->chip_id == CHIP_ID_YUKON_EX)
+       if (hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                rx_reg |= GMF_RX_OVER_ON;
 
        sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
@@ -782,13 +815,19 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
        sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
 
        /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug  */
-       sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
+       reg = RX_GMF_FL_THR_DEF + 1;
+       /* Another magic mystery workaround from sk98lin */
+       if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+           hw->chip_rev == CHIP_REV_YU_FE2_A0)
+               reg = 0x178;
+       sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
 
        /* Configure Tx MAC FIFO */
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
        sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+       /* On chips without ram buffer, pause is controled by MAC level */
+       if (sky2_read8(hw, B2_E_0) == 0) {
                sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
                sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 
@@ -871,6 +910,20 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
        return le;
 }
 
+static void tx_init(struct sky2_port *sky2)
+{
+       struct sky2_tx_le *le;
+
+       sky2->tx_prod = sky2->tx_cons = 0;
+       sky2->tx_tcpsum = 0;
+       sky2->tx_last_mss = 0;
+
+       le = get_tx_le(sky2);
+       le->addr = 0;
+       le->opcode = OP_ADDR64 | HW_OWNER;
+       sky2->tx_addr64 = 0;
+}
+
 static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2,
                                            struct sky2_tx_le *le)
 {
@@ -967,19 +1020,15 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re)
  */
 static void rx_set_checksum(struct sky2_port *sky2)
 {
-       struct sky2_rx_le *le;
-
-       if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
-               le = sky2_next_rx(sky2);
-               le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
-               le->ctrl = 0;
-               le->opcode = OP_TCPSTART | HW_OWNER;
+       struct sky2_rx_le *le = sky2_next_rx(sky2);
 
-               sky2_write32(sky2->hw,
-                            Q_ADDR(rxqaddr[sky2->port], Q_CSR),
-                            sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
-       }
+       le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+       le->ctrl = 0;
+       le->opcode = OP_TCPSTART | HW_OWNER;
 
+       sky2_write32(sky2->hw,
+                    Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+                    sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 }
 
 /*
@@ -1175,7 +1224,8 @@ static int sky2_rx_start(struct sky2_port *sky2)
 
        sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
 
-       rx_set_checksum(sky2);
+       if (!(hw->flags & SKY2_HW_NEW_LE))
+               rx_set_checksum(sky2);
 
        /* Space needed for frame data + headers rounded up */
        size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
@@ -1246,7 +1296,7 @@ static int sky2_up(struct net_device *dev)
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u32 ramsize, imask;
+       u32 imask, ramsize;
        int cap, err = -ENOMEM;
        struct net_device *otherdev = hw->dev[sky2->port^1];
 
@@ -1284,7 +1334,8 @@ static int sky2_up(struct net_device *dev)
                                GFP_KERNEL);
        if (!sky2->tx_ring)
                goto err_out;
-       sky2->tx_prod = sky2->tx_cons = 0;
+
+       tx_init(sky2);
 
        sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
                                           &sky2->rx_le_map);
@@ -1303,11 +1354,10 @@ static int sky2_up(struct net_device *dev)
 
        /* Register is number of 4K blocks on internal RAM buffer. */
        ramsize = sky2_read8(hw, B2_E_0) * 4;
-       printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize);
-
        if (ramsize > 0) {
                u32 rxspace;
 
+               pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
                if (ramsize < 16)
                        rxspace = ramsize / 2;
                else
@@ -1436,13 +1486,15 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        /* Check for TCP Segmentation Offload */
        mss = skb_shinfo(skb)->gso_size;
        if (mss != 0) {
-               if (hw->chip_id != CHIP_ID_YUKON_EX)
+
+               if (!(hw->flags & SKY2_HW_NEW_LE))
                        mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
 
                if (mss != sky2->tx_last_mss) {
                        le = get_tx_le(sky2);
                        le->addr = cpu_to_le32(mss);
-                       if (hw->chip_id == CHIP_ID_YUKON_EX)
+
+                       if (hw->flags & SKY2_HW_NEW_LE)
                                le->opcode = OP_MSS | HW_OWNER;
                        else
                                le->opcode = OP_LRGLEN | HW_OWNER;
@@ -1468,8 +1520,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        /* Handle TCP checksum offload */
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                /* On Yukon EX (some versions) encoding change. */
-               if (hw->chip_id == CHIP_ID_YUKON_EX
-                   && hw->chip_rev != CHIP_REV_YU_EX_B0)
+               if (hw->flags & SKY2_HW_AUTO_TX_SUM)
                        ctrl |= CALSUM; /* auto checksum */
                else {
                        const unsigned offset = skb_transport_offset(skb);
@@ -1622,9 +1673,6 @@ static int sky2_down(struct net_device *dev)
        if (netif_msg_ifdown(sky2))
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
-       if (netif_carrier_ok(dev) && --hw->active == 0)
-               del_timer(&hw->watchdog_timer);
-
        /* Stop more packets from being queued */
        netif_stop_queue(dev);
 
@@ -1708,11 +1756,15 @@ static int sky2_down(struct net_device *dev)
 
 static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
 {
-       if (!sky2_is_copper(hw))
+       if (hw->flags & SKY2_HW_FIBRE_PHY)
                return SPEED_1000;
 
-       if (hw->chip_id == CHIP_ID_YUKON_FE)
-               return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+       if (!(hw->flags & SKY2_HW_GIGABIT)) {
+               if (aux & PHY_M_PS_SPEED_100)
+                       return SPEED_100;
+               else
+                       return SPEED_10;
+       }
 
        switch (aux & PHY_M_PS_SPEED_MSK) {
        case PHY_M_PS_SPEED_1000:
@@ -1745,17 +1797,13 @@ static void sky2_link_up(struct sky2_port *sky2)
 
        netif_carrier_on(sky2->netdev);
 
-       if (hw->active++ == 0)
-               mod_timer(&hw->watchdog_timer, jiffies + 1);
-
+       mod_timer(&hw->watchdog_timer, jiffies + 1);
 
        /* Turn on link LED */
        sky2_write8(hw, SK_REG(port, LNK_LED_REG),
                    LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
 
-       if (hw->chip_id == CHIP_ID_YUKON_XL
-           || hw->chip_id == CHIP_ID_YUKON_EC_U
-           || hw->chip_id == CHIP_ID_YUKON_EX) {
+       if (hw->flags & SKY2_HW_NEWER_PHY) {
                u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
                u16 led = PHY_M_LEDC_LOS_CTRL(1);       /* link active */
 
@@ -1800,11 +1848,6 @@ static void sky2_link_down(struct sky2_port *sky2)
 
        netif_carrier_off(sky2->netdev);
 
-       /* Stop watchdog if both ports are not active */
-       if (--hw->active == 0)
-               del_timer(&hw->watchdog_timer);
-
-
        /* Turn on link LED */
        sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
 
@@ -1847,7 +1890,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
        /* Since the pause result bits seem to in different positions on
         * different chips. look at registers.
         */
-       if (!sky2_is_copper(hw)) {
+       if (hw->flags & SKY2_HW_FIBRE_PHY) {
                /* Shift for bits in fiber PHY */
                advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
                lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
@@ -1958,7 +2001,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
        if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
                return -EINVAL;
 
-       if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE)
+       if (new_mtu > ETH_DATA_LEN &&
+           (hw->chip_id == CHIP_ID_YUKON_FE ||
+            hw->chip_id == CHIP_ID_YUKON_FE_P))
                return -EINVAL;
 
        if (!netif_running(dev)) {
@@ -1975,7 +2020,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
 
        synchronize_irq(hw->pdev->irq);
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+       if (sky2_read8(hw, B2_E_0) == 0)
                sky2_set_tx_stfwd(hw, port);
 
        ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2103,6 +2148,13 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        struct sky2_port *sky2 = netdev_priv(dev);
        struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
        struct sk_buff *skb = NULL;
+       u16 count = (status & GMR_FS_LEN) >> 16;
+
+#ifdef SKY2_VLAN_TAG_USED
+       /* Account for vlan tag */
+       if (sky2->vlgrp && (status & GMR_FS_VLAN))
+               count -= VLAN_HLEN;
+#endif
 
        if (unlikely(netif_msg_rx_status(sky2)))
                printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
@@ -2111,15 +2163,26 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
        prefetch(sky2->rx_ring + sky2->rx_next);
 
+       /* This chip has hardware problems that generates bogus status.
+        * So do only marginal checking and expect higher level protocols
+        * to handle crap frames.
+        */
+       if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
+           sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 &&
+           length != count)
+               goto okay;
+
        if (status & GMR_FS_ANY_ERR)
                goto error;
 
        if (!(status & GMR_FS_RX_OK))
                goto resubmit;
 
-       if (status >> 16 != length)
-               goto len_mismatch;
+       /* if length reported by DMA does not match PHY, packet was truncated */
+       if (length != count)
+               goto len_error;
 
+okay:
        if (length < copybreak)
                skb = receive_copy(sky2, re, length);
        else
@@ -2129,10 +2192,14 @@ resubmit:
 
        return skb;
 
-len_mismatch:
+len_error:
        /* Truncation of overlength packets
           causes PHY length to not match MAC length */
        ++sky2->net_stats.rx_length_errors;
+       if (netif_msg_rx_err(sky2) && net_ratelimit())
+               pr_info(PFX "%s: rx length error: status %#x length %d\n",
+                       dev->name, status, length);
+       goto resubmit;
 
 error:
        ++sky2->net_stats.rx_errors;
@@ -2202,7 +2269,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                        }
 
                        /* This chip reports checksum status differently */
-                       if (hw->chip_id == CHIP_ID_YUKON_EX) {
+                       if (hw->flags & SKY2_HW_NEW_LE) {
                                if (sky2->rx_csum &&
                                    (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
                                    (le->css & CSS_TCPUDPCSOK))
@@ -2243,8 +2310,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                        if (!sky2->rx_csum)
                                break;
 
-                       if (hw->chip_id == CHIP_ID_YUKON_EX)
+                       /* If this happens then driver assuming wrong format */
+                       if (unlikely(hw->flags & SKY2_HW_NEW_LE)) {
+                               if (net_ratelimit())
+                                       printk(KERN_NOTICE "%s: unexpected"
+                                              " checksum status\n",
+                                              dev->name);
                                break;
+                       }
 
                        /* Both checksum counters are programmed to start at
                         * the same offset, so unless there is a problem they
@@ -2436,20 +2509,72 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port,
        sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
 }
 
-/* Check for lost IRQ once a second */
+static int sky2_rx_hung(struct net_device *dev)
+{
+       struct sky2_port *sky2 = netdev_priv(dev);
+       struct sky2_hw *hw = sky2->hw;
+       unsigned port = sky2->port;
+       unsigned rxq = rxqaddr[port];
+       u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP));
+       u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV));
+       u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP));
+       u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL));
+
+       /* If idle and MAC or PCI is stuck */
+       if (sky2->check.last == dev->last_rx &&
+           ((mac_rp == sky2->check.mac_rp &&
+             mac_lev != 0 && mac_lev >= sky2->check.mac_lev) ||
+            /* Check if the PCI RX hang */
+            (fifo_rp == sky2->check.fifo_rp &&
+             fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) {
+               printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n",
+                      dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp,
+                      sky2_read8(hw, Q_ADDR(rxq, Q_WP)));
+               return 1;
+       } else {
+               sky2->check.last = dev->last_rx;
+               sky2->check.mac_rp = mac_rp;
+               sky2->check.mac_lev = mac_lev;
+               sky2->check.fifo_rp = fifo_rp;
+               sky2->check.fifo_lev = fifo_lev;
+               return 0;
+       }
+}
+
 static void sky2_watchdog(unsigned long arg)
 {
        struct sky2_hw *hw = (struct sky2_hw *) arg;
+       struct net_device *dev;
 
+       /* Check for lost IRQ once a second */
        if (sky2_read32(hw, B0_ISRC)) {
-               struct net_device *dev = hw->dev[0];
-
+               dev = hw->dev[0];
                if (__netif_rx_schedule_prep(dev))
                        __netif_rx_schedule(dev);
+       } else {
+               int i, active = 0;
+
+               for (i = 0; i < hw->ports; i++) {
+                       dev = hw->dev[i];
+                       if (!netif_running(dev))
+                               continue;
+                       ++active;
+
+                       /* For chips with Rx FIFO, check if stuck */
+                       if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) &&
+                            sky2_rx_hung(dev)) {
+                               pr_info(PFX "%s: receiver hang detected\n",
+                                       dev->name);
+                               schedule_work(&hw->restart_work);
+                               return;
+                       }
+               }
+
+               if (active == 0)
+                       return;
        }
 
-       if (hw->active > 0)
-               mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
+       mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
 }
 
 /* Hardware/software error handling */
@@ -2546,17 +2671,25 @@ static void sky2_netpoll(struct net_device *dev)
 #endif
 
 /* Chip internal frequency for clock calculations */
-static inline u32 sky2_mhz(const struct sky2_hw *hw)
+static u32 sky2_mhz(const struct sky2_hw *hw)
 {
        switch (hw->chip_id) {
        case CHIP_ID_YUKON_EC:
        case CHIP_ID_YUKON_EC_U:
        case CHIP_ID_YUKON_EX:
-               return 125;     /* 125 Mhz */
+               return 125;
+
        case CHIP_ID_YUKON_FE:
-               return 100;     /* 100 Mhz */
-       default:                /* YUKON_XL */
-               return 156;     /* 156 Mhz */
+               return 100;
+
+       case CHIP_ID_YUKON_FE_P:
+               return 50;
+
+       case CHIP_ID_YUKON_XL:
+               return 156;
+
+       default:
+               BUG();
        }
 }
 
@@ -2581,23 +2714,63 @@ static int __devinit sky2_init(struct sky2_hw *hw)
        sky2_write8(hw, B0_CTST, CS_RST_CLR);
 
        hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
-       if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+       hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+       switch(hw->chip_id) {
+       case CHIP_ID_YUKON_XL:
+               hw->flags = SKY2_HW_GIGABIT
+                       | SKY2_HW_NEWER_PHY;
+               if (hw->chip_rev < 3)
+                       hw->flags |= SKY2_HW_FIFO_HANG_CHECK;
+
+               break;
+
+       case CHIP_ID_YUKON_EC_U:
+               hw->flags = SKY2_HW_GIGABIT
+                       | SKY2_HW_NEWER_PHY
+                       | SKY2_HW_ADV_POWER_CTL;
+               break;
+
+       case CHIP_ID_YUKON_EX:
+               hw->flags = SKY2_HW_GIGABIT
+                       | SKY2_HW_NEWER_PHY
+                       | SKY2_HW_NEW_LE
+                       | SKY2_HW_ADV_POWER_CTL;
+
+               /* New transmit checksum */
+               if (hw->chip_rev != CHIP_REV_YU_EX_B0)
+                       hw->flags |= SKY2_HW_AUTO_TX_SUM;
+               break;
+
+       case CHIP_ID_YUKON_EC:
+               /* This rev is really old, and requires untested workarounds */
+               if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+                       dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
+                       return -EOPNOTSUPP;
+               }
+               hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK;
+               break;
+
+       case CHIP_ID_YUKON_FE:
+               break;
+
+       case CHIP_ID_YUKON_FE_P:
+               hw->flags = SKY2_HW_NEWER_PHY
+                       | SKY2_HW_NEW_LE
+                       | SKY2_HW_AUTO_TX_SUM
+                       | SKY2_HW_ADV_POWER_CTL;
+               break;
+       default:
                dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
                        hw->chip_id);
                return -EOPNOTSUPP;
        }
 
-       hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+       hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+       if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+               hw->flags |= SKY2_HW_FIBRE_PHY;
 
-       /* This rev is really old, and requires untested workarounds */
-       if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) {
-               dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n",
-                       yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
-                       hw->chip_id, hw->chip_rev);
-               return -EOPNOTSUPP;
-       }
 
-       hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
        hw->ports = 1;
        t8 = sky2_read8(hw, B2_Y2_HW_RES);
        if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
@@ -2791,7 +2964,9 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 
        sky2->wol = wol->wolopts;
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+           hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                sky2_write32(hw, B0_CTST, sky2->wol
                             ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
 
@@ -2809,7 +2984,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw)
                        | SUPPORTED_100baseT_Full
                        | SUPPORTED_Autoneg | SUPPORTED_TP;
 
-               if (hw->chip_id != CHIP_ID_YUKON_FE)
+               if (hw->flags & SKY2_HW_GIGABIT)
                        modes |= SUPPORTED_1000baseT_Half
                                | SUPPORTED_1000baseT_Full;
                return modes;
@@ -2829,13 +3004,6 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        ecmd->supported = sky2_supported_modes(hw);
        ecmd->phy_address = PHY_ADDR_MARV;
        if (sky2_is_copper(hw)) {
-               ecmd->supported = SUPPORTED_10baseT_Half
-                   | SUPPORTED_10baseT_Full
-                   | SUPPORTED_100baseT_Half
-                   | SUPPORTED_100baseT_Full
-                   | SUPPORTED_1000baseT_Half
-                   | SUPPORTED_1000baseT_Full
-                   | SUPPORTED_Autoneg | SUPPORTED_TP;
                ecmd->port = PORT_TP;
                ecmd->speed = sky2->speed;
        } else {
@@ -3814,8 +3982,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
                dev->features |= NETIF_F_HIGHDMA;
 
 #ifdef SKY2_VLAN_TAG_USED
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-       dev->vlan_rx_register = sky2_vlan_rx_register;
+       /* The workaround for FE+ status conflicts with VLAN tag detection. */
+       if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
+             sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) {
+               dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+               dev->vlan_rx_register = sky2_vlan_rx_register;
+       }
 #endif
 
        /* read the mac address */
@@ -3846,7 +4018,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
                return IRQ_NONE;
 
        if (status & Y2_IS_IRQ_SW) {
-               hw->msi = 1;
+               hw->flags |= SKY2_HW_USE_MSI;
                wake_up(&hw->msi_wait);
                sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
        }
@@ -3874,9 +4046,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
        sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
        sky2_read8(hw, B0_CTST);
 
-       wait_event_timeout(hw->msi_wait, hw->msi, HZ/10);
+       wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
 
-       if (!hw->msi) {
+       if (!(hw->flags & SKY2_HW_USE_MSI)) {
                /* MSI test failed, go back to INTx mode */
                dev_info(&pdev->dev, "No interrupt generated using MSI, "
                         "switching to INTx mode.\n");
@@ -4009,7 +4181,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out_free_netdev;
        }
 
-       err = request_irq(pdev->irq,  sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+       err = request_irq(pdev->irq, sky2_intr,
+                         (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
                          dev->name, hw);
        if (err) {
                dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
@@ -4042,7 +4215,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        return 0;
 
 err_out_unregister:
-       if (hw->msi)
+       if (hw->flags & SKY2_HW_USE_MSI)
                pci_disable_msi(pdev);
        unregister_netdev(dev);
 err_out_free_netdev:
@@ -4091,7 +4264,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
        sky2_read8(hw, B0_CTST);
 
        free_irq(pdev->irq, hw);
-       if (hw->msi)
+       if (hw->flags & SKY2_HW_USE_MSI)
                pci_disable_msi(pdev);
        pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
        pci_release_regions(pdev);
@@ -4159,7 +4332,9 @@ static int sky2_resume(struct pci_dev *pdev)
        pci_enable_wake(pdev, PCI_D0, 0);
 
        /* Re-enable all clocks */
-       if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
+       if (hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_EC_U ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                sky2_pci_write32(hw, PCI_DEV_REG3, 0);
 
        sky2_reset(hw);
index 72e12b7cfa40e27dd5af5e25e9294b416feef325..8bc5c54e3efacd2cdc63e12aabd31a5ce37b0051 100644 (file)
@@ -470,18 +470,24 @@ enum {
        CHIP_ID_YUKON_EX   = 0xb5, /* Chip ID for YUKON-2 Extreme */
        CHIP_ID_YUKON_EC   = 0xb6, /* Chip ID for YUKON-2 EC */
        CHIP_ID_YUKON_FE   = 0xb7, /* Chip ID for YUKON-2 FE */
-
+       CHIP_ID_YUKON_FE_P = 0xb8, /* Chip ID for YUKON-2 FE+ */
+};
+enum yukon_ec_rev {
        CHIP_REV_YU_EC_A1    = 0,  /* Chip Rev. for Yukon-EC A1/A0 */
        CHIP_REV_YU_EC_A2    = 1,  /* Chip Rev. for Yukon-EC A2 */
        CHIP_REV_YU_EC_A3    = 2,  /* Chip Rev. for Yukon-EC A3 */
-
+};
+enum yukon_ec_u_rev {
        CHIP_REV_YU_EC_U_A0  = 1,
        CHIP_REV_YU_EC_U_A1  = 2,
        CHIP_REV_YU_EC_U_B0  = 3,
-
+};
+enum yukon_fe_rev {
        CHIP_REV_YU_FE_A1    = 1,
        CHIP_REV_YU_FE_A2    = 2,
-
+};
+enum yukon_fe_p_rev {
+       CHIP_REV_YU_FE2_A0   = 0,
 };
 enum yukon_ex_rev {
        CHIP_REV_YU_EX_A0    = 1,
@@ -1668,7 +1674,7 @@ enum {
 
 /* Receive Frame Status Encoding */
 enum {
-       GMR_FS_LEN      = 0xffff<<16, /* Bit 31..16:    Rx Frame Length */
+       GMR_FS_LEN      = 0x7fff<<16, /* Bit 30..16:    Rx Frame Length */
        GMR_FS_VLAN     = 1<<13, /* VLAN Packet */
        GMR_FS_JABBER   = 1<<12, /* Jabber Packet */
        GMR_FS_UN_SIZE  = 1<<11, /* Undersize Packet */
@@ -1729,6 +1735,10 @@ enum {
        GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON,
 };
 
+/*     TX_GMF_EA               32 bit  Tx GMAC FIFO End Address */
+enum {
+       TX_DYN_WM_ENA   = 3,    /* Yukon-FE+ specific */
+};
 
 /*     TX_GMF_CTRL_T   32 bit  Tx GMAC FIFO Control/Test */
 enum {
@@ -2017,6 +2027,14 @@ struct sky2_port {
        u16                  rx_tag;
        struct vlan_group    *vlgrp;
 #endif
+       struct {
+               unsigned long last;
+               u32     mac_rp;
+               u8      mac_lev;
+               u8      fifo_rp;
+               u8      fifo_lev;
+       } check;
+
 
        dma_addr_t           rx_le_map;
        dma_addr_t           tx_le_map;
@@ -2040,12 +2058,20 @@ struct sky2_hw {
        void __iomem         *regs;
        struct pci_dev       *pdev;
        struct net_device    *dev[2];
+       unsigned long        flags;
+#define SKY2_HW_USE_MSI                0x00000001
+#define SKY2_HW_FIBRE_PHY      0x00000002
+#define SKY2_HW_GIGABIT                0x00000004
+#define SKY2_HW_NEWER_PHY      0x00000008
+#define SKY2_HW_FIFO_HANG_CHECK        0x00000010
+#define SKY2_HW_NEW_LE         0x00000020      /* new LSOv2 format */
+#define SKY2_HW_AUTO_TX_SUM    0x00000040      /* new IP decode for Tx */
+#define SKY2_HW_ADV_POWER_CTL  0x00000080      /* additional PHY power regs */
 
        u8                   chip_id;
        u8                   chip_rev;
        u8                   pmd_type;
        u8                   ports;
-       u8                   active;
 
        struct sky2_status_le *st_le;
        u32                  st_idx;
@@ -2053,13 +2079,12 @@ struct sky2_hw {
 
        struct timer_list    watchdog_timer;
        struct work_struct   restart_work;
-       int                  msi;
        wait_queue_head_t    msi_wait;
 };
 
 static inline int sky2_is_copper(const struct sky2_hw *hw)
 {
-       return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P');
+       return !(hw->flags & SKY2_HW_FIBRE_PHY);
 }
 
 /* Register accessor for memory mapped device */
index 16c7a0e878505a7b229817012de9e3f2b3eab50c..a2de32fabc170a9a688750ce7f427f67f4e7a5e6 100644 (file)
@@ -405,7 +405,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD;
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
index ef35bc6c4a228491723bd6c4efc9d5816dd8009b..4eb6d9752881e7459a4bb0be66d959903c394e2d 100644 (file)
@@ -43,7 +43,7 @@ obj-$(CONFIG_PCMCIA_RAYCS)    += ray_cs.o
 obj-$(CONFIG_PCMCIA_WL3501)    += wl3501_cs.o
 
 obj-$(CONFIG_USB_ZD1201)       += zd1201.o
-obj-$(CONFIG_LIBERTAS_USB)     += libertas/
+obj-$(CONFIG_LIBERTAS)         += libertas/
 
 rtl8187-objs           := rtl8187_dev.o rtl8187_rtl8225.o
 obj-$(CONFIG_RTL8187)  += rtl8187.o
index d6d9413d7f23cdd662eadf09cc675dd667b2fda1..6acfdc49dccd30507f4b8b9521f4e75a2a237fbd 100644 (file)
@@ -444,7 +444,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
        u16 maxpower;
 
        if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
-               printk(PFX KERN_ERR "TX power not in dBm.\n");
+               printk(KERN_ERR PFX "TX power not in dBm.\n");
                return -EOPNOTSUPP;
        }
 
index 7dcaa09b3c200591cfb49412c331b19ccb3e8999..50f2dd9e1bb2cac61a58d132c52046ac88fc5d66 100644 (file)
@@ -1444,7 +1444,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
 static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
 {
        u16 command;
-       u32 bar;
        u8 __iomem *csr;
        u8 cmd_hi;
 
@@ -1476,12 +1475,12 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
         * re-enable them when it's ready.
         */
        pci_read_config_word(dev, PCI_COMMAND, &command);
-       pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar);
 
-       if (!(command & PCI_COMMAND_MEMORY) || !bar)
+       if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0))
                return;
 
-       csr = ioremap(bar, 8);
+       /* Convert from PCI bus to resource space.  */
+       csr = ioremap(pci_resource_start(dev, 0), 8);
        if (!csr) {
                printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
                        pci_name(dev));
index c7c4574729b190c6358e57e7f02d04427be3c029..de3155b21285df91c29def0571409e28973bdbdc 100644 (file)
@@ -289,6 +289,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
                if (ret)
                        goto out;
        }
+       envp[i] = NULL;
 
 out:
        free_page((unsigned long)prop_buf);
index 46da5714932c3e15f9607058a4855aeba02f6e3d..5ab3492817d16b0574202380b9ddb2a394042ba5 100644 (file)
@@ -61,7 +61,7 @@
 struct rtc_plat_data {
        struct rtc_device *rtc;
        void __iomem *ioaddr;
-       unsigned long baseaddr;
+       resource_size_t baseaddr;
        unsigned long last_jiffies;
        int irq;
        unsigned int irqen;
index b2e5481ba3b610766eee9936170c6e3455d03d21..67291b0f82838a6e7214827b0706fdbf07096ae3 100644 (file)
@@ -55,7 +55,7 @@ struct rtc_plat_data {
        void __iomem *ioaddr_rtc;
        size_t size_nvram;
        size_t size;
-       unsigned long baseaddr;
+       resource_size_t baseaddr;
        unsigned long last_jiffies;
 };
 
index d5d8caba35605f3643b165211d84aa583f29bbd4..ab13824df856594ec140ce9c23bb9888b71b4523 100644 (file)
@@ -451,7 +451,7 @@ static int asd_build_smp_ascb(struct asd_ascb *ascb, struct sas_task *task,
        struct scb *scb;
 
        pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1,
-                  PCI_DMA_FROMDEVICE);
+                  PCI_DMA_TODEVICE);
        pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1,
                   PCI_DMA_FROMDEVICE);
 
@@ -486,7 +486,7 @@ static void asd_unbuild_smp_ascb(struct asd_ascb *a)
 
        BUG_ON(!task);
        pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1,
-                    PCI_DMA_FROMDEVICE);
+                    PCI_DMA_TODEVICE);
        pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1,
                     PCI_DMA_FROMDEVICE);
 }
index 77b06a983fa763023f245c010fb738616c7d18bc..95cf7b6cd6225043f7a13ef33939b118303cba1c 100644 (file)
@@ -2314,6 +2314,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev)
        esp->host->transportt = esp_transport_template;
        esp->host->max_lun = ESP_MAX_LUN;
        esp->host->cmd_per_lun = 2;
+       esp->host->unique_id = instance;
 
        esp_set_clock_params(esp);
 
@@ -2337,7 +2338,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev)
        if (err)
                return err;
 
-       esp->host->unique_id = instance++;
+       instance++;
 
        scsi_scan_host(esp->host);
 
index 3907f6718ede11272e797bc7b6f7d7a1bfc34210..da56163c30a8f6404b02c16743595561a7b2a692 100644 (file)
@@ -1753,6 +1753,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
 
        *len = 0;
 
+       if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) {
+               sg = scsi_sglist(cmd);
+               scb->dma_h_bulkdata = sg_dma_address(sg);
+               *buf = (u32)scb->dma_h_bulkdata;
+               *len = sg_dma_len(sg);
+               return 0;
+       }
+
        scsi_for_each_sg(cmd, sg, sgcnt, idx) {
                if (adapter->has_64bit_addr) {
                        scb->sgl64[idx].address = sg_dma_address(sg);
index 6f56f8750635eca0e44ec6af2914a40f54b7c123..4df21c92ff1ede9931772f36ec7aa3ac77255bb9 100644 (file)
@@ -787,10 +787,12 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
        struct scsi_target *starget = sdev->sdev_target;
        struct Scsi_Host *shost = sdev->host;
        int len = sdev->inquiry_len;
+       int min_period = spi_min_period(starget);
+       int max_width = spi_max_width(starget);
        /* first set us up for narrow async */
        DV_SET(offset, 0);
        DV_SET(width, 0);
-       
+
        if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
            != SPI_COMPARE_SUCCESS) {
                starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n");
@@ -798,9 +800,13 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
                return;
        }
 
+       if (!scsi_device_wide(sdev)) {
+               spi_max_width(starget) = 0;
+               max_width = 0;
+       }
+
        /* test width */
-       if (i->f->set_width && spi_max_width(starget) &&
-           scsi_device_wide(sdev)) {
+       if (i->f->set_width && max_width) {
                i->f->set_width(starget, 1);
 
                if (spi_dv_device_compare_inquiry(sdev, buffer,
@@ -809,6 +815,11 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
                    != SPI_COMPARE_SUCCESS) {
                        starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n");
                        i->f->set_width(starget, 0);
+                       /* Make sure we don't force wide back on by asking
+                        * for a transfer period that requires it */
+                       max_width = 0;
+                       if (min_period < 10)
+                               min_period = 10;
                }
        }
 
@@ -828,7 +839,8 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
 
        /* now set up to the maximum */
        DV_SET(offset, spi_max_offset(starget));
-       DV_SET(period, spi_min_period(starget));
+       DV_SET(period, min_period);
+
        /* try QAS requests; this should be harmless to set if the
         * target supports it */
        if (scsi_device_qas(sdev)) {
@@ -837,14 +849,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
                DV_SET(qas, 0);
        }
 
-       if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) {
+       if (scsi_device_ius(sdev) && min_period < 9) {
                /* This u320 (or u640). Set IU transfers */
                DV_SET(iu, 1);
                /* Then set the optional parameters */
                DV_SET(rd_strm, 1);
                DV_SET(wr_flow, 1);
                DV_SET(rti, 1);
-               if (spi_min_period(starget) == 8)
+               if (min_period == 8)
                        DV_SET(pcomp_en, 1);
        } else {
                DV_SET(iu, 0);
@@ -862,6 +874,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
        } else {
                DV_SET(dt, 1);
        }
+       /* set width last because it will pull all the other
+        * parameters down to required values */
+       DV_SET(width, max_width);
+
        /* Do the read only INQUIRY tests */
        spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len,
                       spi_dv_device_compare_inquiry);
index a99e45e2b6d8d114db340681805297b99f431292..2a6477834c3e0e8e63c17b7c62fc8735855d1db1 100644 (file)
@@ -37,6 +37,6 @@ static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
        up->smc_tfcr = SMC_EB;
 }
 
-#define DPRAM_BASE     ((unsigned char *)&cpmp->cp_dpmem[0])
+#define DPRAM_BASE     ((unsigned char *)cpm_dpram_addr(0))
 
 #endif
index a0ea43598515b360115108d319d4ce25aeb3071e..7c8d78fbbbfb80965e31100a91d9a93faf47174e 100644 (file)
@@ -943,6 +943,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
        PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
        PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
+       PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
        /* too generic */
        /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
        /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
index bca57bb949393275c902f5f31e35e1abe9527d1a..ff610c23314bd74e5b9fa9d3f103334c1c957581 100644 (file)
@@ -38,7 +38,7 @@
 #include <asm/prom.h>
 #include <asm/of_device.h>
 
-#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
 
@@ -58,6 +58,7 @@ struct uart_sunsab_port {
        unsigned char                   interrupt_mask1;/* ISR1 masking         */
        unsigned char                   pvr_dtr_bit;    /* Which PVR bit is DTR */
        unsigned char                   pvr_dsr_bit;    /* Which PVR bit is DSR */
+       unsigned int                    gis_shift;
        int                             type;           /* SAB82532 version     */
 
        /* Setting configuration bits while the transmitter is active
@@ -305,13 +306,15 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
        struct tty_struct *tty;
        union sab82532_irq_status status;
        unsigned long flags;
+       unsigned char gis;
 
        spin_lock_irqsave(&up->port.lock, flags);
 
        status.stat = 0;
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA0)
+       gis = readb(&up->regs->r.gis) >> up->gis_shift;
+       if (gis & 1)
                status.sreg.isr0 = readb(&up->regs->r.isr0);
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA1)
+       if (gis & 2)
                status.sreg.isr1 = readb(&up->regs->r.isr1);
 
        tty = NULL;
@@ -327,35 +330,6 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
                        transmit_chars(up, &status);
        }
 
-       spin_unlock(&up->port.lock);
-
-       if (tty)
-               tty_flip_buffer_push(tty);
-
-       up++;
-
-       spin_lock(&up->port.lock);
-
-       status.stat = 0;
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB0)
-               status.sreg.isr0 = readb(&up->regs->r.isr0);
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB1)
-               status.sreg.isr1 = readb(&up->regs->r.isr1);
-
-       tty = NULL;
-       if (status.stat) {
-               if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
-                                        SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
-                   (status.sreg.isr1 & SAB82532_ISR1_BRK))
-
-                       tty = receive_chars(up, &status);
-               if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
-                   (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
-                       check_status(up, &status);
-               if (status.sreg.isr1 & (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR))
-                       transmit_chars(up, &status);
-       }
-
        spin_unlock_irqrestore(&up->port.lock, flags);
 
        if (tty)
@@ -539,6 +513,10 @@ static int sunsab_startup(struct uart_port *port)
        struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
        unsigned long flags;
        unsigned char tmp;
+       int err = request_irq(up->port.irq, sunsab_interrupt,
+                             IRQF_SHARED, "sab", up);
+       if (err)
+               return err;
 
        spin_lock_irqsave(&up->port.lock, flags);
 
@@ -641,6 +619,7 @@ static void sunsab_shutdown(struct uart_port *port)
 #endif
 
        spin_unlock_irqrestore(&up->port.lock, flags);
+       free_irq(up->port.irq, up);
 }
 
 /*
@@ -1008,9 +987,11 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
        if ((up->port.line & 0x1) == 0) {
                up->pvr_dsr_bit = (1 << 0);
                up->pvr_dtr_bit = (1 << 1);
+               up->gis_shift = 2;
        } else {
                up->pvr_dsr_bit = (1 << 3);
                up->pvr_dtr_bit = (1 << 2);
+               up->gis_shift = 0;
        }
        up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
        writeb(up->cached_pvr, &up->regs->w.pvr);
@@ -1023,19 +1004,6 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
        up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
        up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
 
-       if (!(up->port.line & 0x01)) {
-               int err;
-
-               err = request_irq(up->port.irq, sunsab_interrupt,
-                                 IRQF_SHARED, "sab", up);
-               if (err) {
-                       of_iounmap(&op->resource[0],
-                                  up->port.membase,
-                                  sizeof(union sab82532_async_regs));
-                       return err;
-               }
-       }
-
        return 0;
 }
 
@@ -1051,52 +1019,60 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
                              0,
                              (inst * 2) + 0);
        if (err)
-               return err;
+               goto out;
 
        err = sunsab_init_one(&up[1], op,
                              sizeof(union sab82532_async_regs),
                              (inst * 2) + 1);
-       if (err) {
-               of_iounmap(&op->resource[0],
-                          up[0].port.membase,
-                          sizeof(union sab82532_async_regs));
-               free_irq(up[0].port.irq, &up[0]);
-               return err;
-       }
+       if (err)
+               goto out1;
 
        sunserial_console_match(SUNSAB_CONSOLE(), op->node,
                                &sunsab_reg, up[0].port.line);
-       uart_add_one_port(&sunsab_reg, &up[0].port);
 
        sunserial_console_match(SUNSAB_CONSOLE(), op->node,
                                &sunsab_reg, up[1].port.line);
-       uart_add_one_port(&sunsab_reg, &up[1].port);
+
+       err = uart_add_one_port(&sunsab_reg, &up[0].port);
+       if (err)
+               goto out2;
+
+       err = uart_add_one_port(&sunsab_reg, &up[1].port);
+       if (err)
+               goto out3;
 
        dev_set_drvdata(&op->dev, &up[0]);
 
        inst++;
 
        return 0;
-}
-
-static void __devexit sab_remove_one(struct uart_sunsab_port *up)
-{
-       struct of_device *op = to_of_device(up->port.dev);
 
-       uart_remove_one_port(&sunsab_reg, &up->port);
-       if (!(up->port.line & 1))
-               free_irq(up->port.irq, up);
+out3:
+       uart_remove_one_port(&sunsab_reg, &up[0].port);
+out2:
        of_iounmap(&op->resource[0],
-                  up->port.membase,
+                  up[1].port.membase,
                   sizeof(union sab82532_async_regs));
+out1:
+       of_iounmap(&op->resource[0],
+                  up[0].port.membase,
+                  sizeof(union sab82532_async_regs));
+out:
+       return err;
 }
 
 static int __devexit sab_remove(struct of_device *op)
 {
        struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
 
-       sab_remove_one(&up[0]);
-       sab_remove_one(&up[1]);
+       uart_remove_one_port(&sunsab_reg, &up[1].port);
+       uart_remove_one_port(&sunsab_reg, &up[0].port);
+       of_iounmap(&op->resource[0],
+                  up[1].port.membase,
+                  sizeof(union sab82532_async_regs));
+       of_iounmap(&op->resource[0],
+                  up[0].port.membase,
+                  sizeof(union sab82532_async_regs));
 
        dev_set_drvdata(&op->dev, NULL);
 
@@ -1143,6 +1119,7 @@ static int __init sunsab_init(void)
 
                sunsab_reg.minor = sunserial_current_minor;
                sunsab_reg.nr = num_channels;
+               sunsab_reg.cons = SUNSAB_CONSOLE();
 
                err = uart_register_driver(&sunsab_reg);
                if (err) {
index b21d0dec92836d1481b7a33e4325e91f2a355a1b..6a47682d861446639c5c81bd0db1cc26af3b6036 100644 (file)
@@ -1352,7 +1352,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
 
        /* turn off PLL */
        tmp = INREG(dpll_reg);
-       dpll_reg &= ~DPLL_VCO_ENABLE;
+       tmp &= ~DPLL_VCO_ENABLE;
        OUTREG(dpll_reg, tmp);
 
        /* Set PLL parameters */
index 8d7ab74170d57944b2f1c68fb94f74bcd21c3519..a593f900eff4ff1936f9e9504747592ab27e9b4d 100644 (file)
@@ -431,6 +431,7 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp,
        err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size,
                        &cur_len, "W1_SLAVE_ID=%024LX",
                        (unsigned long long)sl->reg_num.id);
+       envp[cur_index] = NULL;
        if (err)
                return err;
 
index dbe699e9828c3ac840529876d4daf2dda56abb47..ea2e198203818a4703f8dc56a6d8473cf6ada21a 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1562,6 +1562,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                fput(file);
                return -EAGAIN;
        }
+       req->ki_filp = file;
        if (iocb->aio_flags & IOCB_FLAG_RESFD) {
                /*
                 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
@@ -1576,7 +1577,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                }
        }
 
-       req->ki_filp = file;
        ret = put_user(req->ki_key, &user_iocb->aio_key);
        if (unlikely(ret)) {
                dprintk("EFAULT: aio_key\n");
index 861141b4f6d6f4cbbfcd96366074db8e4adbeaf3..fcb3405bb14e99b64aa322f7e3856ee3fa2ddbb1 100644 (file)
@@ -742,6 +742,7 @@ static int load_flat_file(struct linux_binprm * bprm,
         * __start to address 4 so that is okay).
         */
        if (rev > OLD_FLAT_VERSION) {
+               unsigned long persistent = 0;
                for (i=0; i < relocs; i++) {
                        unsigned long addr, relval;
 
@@ -749,6 +750,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                           relocated (of course, the address has to be
                           relocated first).  */
                        relval = ntohl(reloc[i]);
+                       if (flat_set_persistent (relval, &persistent))
+                               continue;
                        addr = flat_get_relocate_addr(relval);
                        rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
                        if (rp == (unsigned long *)RELOC_FAILED) {
@@ -757,7 +760,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                        }
 
                        /* Get the pointer's value.  */
-                       addr = flat_get_addr_from_rp(rp, relval, flags);
+                       addr = flat_get_addr_from_rp(rp, relval, flags,
+                                                       &persistent);
                        if (addr != 0) {
                                /*
                                 * Do the relocation.  PIC relocs in the data section are
index 5a5b7116cefb28cc5b56a85f089985796c7b6423..37310b0e81076caf3d5e5970530c3b1325e9e7aa 100644 (file)
@@ -3190,6 +3190,8 @@ COMPATIBLE_IOCTL(SIOCSIWRETRY)
 COMPATIBLE_IOCTL(SIOCGIWRETRY)
 COMPATIBLE_IOCTL(SIOCSIWPOWER)
 COMPATIBLE_IOCTL(SIOCGIWPOWER)
+COMPATIBLE_IOCTL(SIOCSIWAUTH)
+COMPATIBLE_IOCTL(SIOCGIWAUTH)
 /* hiddev */
 COMPATIBLE_IOCTL(HIDIOCGVERSION)
 COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
index c21a8cc0627709db512597ff2af82ab7c094e67d..073b0b8c6d055a3fd947f16fbdbe5552a6bc34c8 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -50,7 +50,6 @@
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
-#include <linux/signalfd.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -784,7 +783,6 @@ static int de_thread(struct task_struct *tsk)
         * and we can just re-use it all.
         */
        if (atomic_read(&oldsighand->count) <= 1) {
-               signalfd_detach(tsk);
                exit_itimers(sig);
                return 0;
        }
@@ -923,7 +921,6 @@ static int de_thread(struct task_struct *tsk)
        sig->flags = 0;
 
 no_thread_group:
-       signalfd_detach(tsk);
        exit_itimers(sig);
        if (leader)
                release_task(leader);
index 1586807b81779ef9c02008e6828c9df50d4f000c..c1fa1908dba05137158d0e9f40b991a983a4c9d8 100644 (file)
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT3_INDEX
@@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     root->info.info_length));
+
+       if (dx_get_limit(entries) != dx_root_limit(dir,
+                                                  root->info.info_length)) {
+               ext3_warning(dir->i_sb, __FUNCTION__,
+                            "dx entry: limit != root limit");
+               brelse(bh);
+               *err = ERR_BAD_DX_DIR;
+               goto fail;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(entries));
+               if (!count || count > dx_get_limit(entries)) {
+                       ext3_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: no count or count > limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -423,8 +439,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               if (dx_get_limit(entries) != dx_node_limit (dir)) {
+                       ext3_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: limit != node limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -432,6 +455,10 @@ fail2:
                frame--;
        }
 fail:
+       if (*err == ERR_BAD_DX_DIR)
+               ext3_warning(dir->i_sb, __FUNCTION__,
+                            "Corrupt dir inode %ld, running e2fsck is "
+                            "recommended.", dir->i_ino);
        return NULL;
 }
 
@@ -671,6 +698,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -684,7 +715,8 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        ext3fs_dirhash(de->name, de->name_len, &h);
                        map_tail--;
                        map_tail->hash = h.hash;
-                       map_tail->offs = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -694,6 +726,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
        return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
         struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1091,6 +1124,10 @@ static inline void ext3_set_de_type(struct super_block *sb,
 }
 
 #ifdef CONFIG_EXT3_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext3_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1109,6 +1146,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
        return (struct ext3_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
        struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
@@ -1131,6 +1172,11 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
        return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
                        struct dx_hash_info *hinfo, int *error)
@@ -1142,7 +1188,7 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        u32 hash2;
        struct dx_map_entry *map;
        char *data1 = (*bh)->b_data, *data2;
-       unsigned split;
+       unsigned split, move, size, i;
        struct ext3_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1170,8 +1216,19 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        count = dx_make_map ((struct ext3_dir_entry_2 *) data1,
                             blocksize, hinfo, map);
        map -= count;
-       split = count/2; // need to adjust to actual middle
        dx_sort_map (map, count);
+       /* Split the existing block in the middle, size-wise */
+       size = 0;
+       move = 0;
+       for (i = count-1; i >= 0; i--) {
+               /* is more than half of this entry in 2nd half of the block? */
+               if (size + map[i].size/2 > blocksize/2)
+                       break;
+               size += map[i].size;
+               move++;
+       }
+       /* map index at which we will split */
+       split = count - move;
        hash2 = map[split].hash;
        continued = hash2 == map[split - 1].hash;
        dxtrace(printk("Split block %i at %x, %i/%i\n",
index da224974af7861efeab66cdd0de475e0679f9432..5fdb862e71c47fb8df885e87e93090141227154a 100644 (file)
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT4_INDEX
@@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     root->info.info_length));
+
+       if (dx_get_limit(entries) != dx_root_limit(dir,
+                                                  root->info.info_length)) {
+               ext4_warning(dir->i_sb, __FUNCTION__,
+                            "dx entry: limit != root limit");
+               brelse(bh);
+               *err = ERR_BAD_DX_DIR;
+               goto fail;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(entries));
+               if (!count || count > dx_get_limit(entries)) {
+                       ext4_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: no count or count > limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -423,8 +439,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               if (dx_get_limit(entries) != dx_node_limit (dir)) {
+                       ext4_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: limit != node limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -432,6 +455,10 @@ fail2:
                frame--;
        }
 fail:
+       if (*err == ERR_BAD_DX_DIR)
+               ext4_warning(dir->i_sb, __FUNCTION__,
+                            "Corrupt dir inode %ld, running e2fsck is "
+                            "recommended.", dir->i_ino);
        return NULL;
 }
 
@@ -671,6 +698,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
                        struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -684,7 +715,8 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
                        ext4fs_dirhash(de->name, de->name_len, &h);
                        map_tail--;
                        map_tail->hash = h.hash;
-                       map_tail->offs = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -694,6 +726,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
        return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
        struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1089,6 +1122,10 @@ static inline void ext4_set_de_type(struct super_block *sb,
 }
 
 #ifdef CONFIG_EXT4_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext4_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1107,6 +1144,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
        return (struct ext4_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
        struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
@@ -1129,6 +1170,11 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
        return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
                        struct dx_hash_info *hinfo, int *error)
@@ -1140,7 +1186,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        u32 hash2;
        struct dx_map_entry *map;
        char *data1 = (*bh)->b_data, *data2;
-       unsigned split;
+       unsigned split, move, size, i;
        struct ext4_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1168,8 +1214,19 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        count = dx_make_map ((struct ext4_dir_entry_2 *) data1,
                             blocksize, hinfo, map);
        map -= count;
-       split = count/2; // need to adjust to actual middle
        dx_sort_map (map, count);
+       /* Split the existing block in the middle, size-wise */
+       size = 0;
+       move = 0;
+       for (i = count-1; i >= 0; i--) {
+               /* is more than half of this entry in 2nd half of the block? */
+               if (size + map[i].size/2 > blocksize/2)
+                       break;
+               size += map[i].size;
+               move++;
+       }
+       /* map index at which we will split */
+       split = count - move;
        hash2 = map[split].hash;
        continued = hash2 == map[split - 1].hash;
        dxtrace(printk("Split block %i at %x, %i/%i\n",
index a21e4bc5444b49058537d810131234771cdfa17f..d120ec39bcb0ea5c472fc7c1f3ba277b9308709d 100644 (file)
@@ -171,19 +171,14 @@ found:
  * GRANTED_RES message by cookie, without having to rely on the client's IP
  * address. --okir
  */
-static inline struct nlm_block *
-nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
-               struct nlm_lock *lock, struct nlm_cookie *cookie)
+static struct nlm_block *
+nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
+                   struct nlm_file *file, struct nlm_lock *lock,
+                   struct nlm_cookie *cookie)
 {
        struct nlm_block        *block;
-       struct nlm_host         *host;
        struct nlm_rqst         *call = NULL;
 
-       /* Create host handle for callback */
-       host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
-       if (host == NULL)
-               return NULL;
-
        call = nlm_alloc_call(host);
        if (call == NULL)
                return NULL;
@@ -366,6 +361,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                        struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
        struct nlm_block        *block = NULL;
+       struct nlm_host         *host;
        int                     error;
        __be32                  ret;
 
@@ -377,6 +373,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                                (long long)lock->fl.fl_end,
                                wait);
 
+       /* Create host handle for callback */
+       host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
+       if (host == NULL)
+               return nlm_lck_denied_nolocks;
 
        /* Lock file against concurrent access */
        mutex_lock(&file->f_mutex);
@@ -385,7 +385,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
         */
        block = nlmsvc_lookup_block(file, lock);
        if (block == NULL) {
-               block = nlmsvc_create_block(rqstp, file, lock, cookie);
+               block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
+                               lock, cookie);
                ret = nlm_lck_denied_nolocks;
                if (block == NULL)
                        goto out;
@@ -449,6 +450,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 out:
        mutex_unlock(&file->f_mutex);
        nlmsvc_release_block(block);
+       nlm_release_host(host);
        dprintk("lockd: nlmsvc_lock returned %u\n", ret);
        return ret;
 }
@@ -477,10 +479,17 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
 
        if (block == NULL) {
                struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+               struct nlm_host *host;
 
                if (conf == NULL)
                        return nlm_granted;
-               block = nlmsvc_create_block(rqstp, file, lock, cookie);
+               /* Create host handle for callback */
+               host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
+               if (host == NULL) {
+                       kfree(conf);
+                       return nlm_lck_denied_nolocks;
+               }
+               block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
                if (block == NULL) {
                        kfree(conf);
                        return nlm_granted;
index a49f9feff776253f99ffd167246a5fc2b77d79d5..a204484072f34ca37320f310eeee2b8bdbb35cca 100644 (file)
@@ -588,16 +588,6 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
        server->namelen  = data->namlen;
        /* Create a client RPC handle for the NFSv3 ACL management interface */
        nfs_init_server_aclclient(server);
-       if (clp->cl_nfsversion == 3) {
-               if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
-                       server->namelen = NFS3_MAXNAMLEN;
-               if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
-                       server->caps |= NFS_CAP_READDIRPLUS;
-       } else {
-               if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
-                       server->namelen = NFS2_MAXNAMLEN;
-       }
-
        dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
        return 0;
 
@@ -794,6 +784,16 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
        error = nfs_probe_fsinfo(server, mntfh, &fattr);
        if (error < 0)
                goto error;
+       if (server->nfs_client->rpc_ops->version == 3) {
+               if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
+                       server->namelen = NFS3_MAXNAMLEN;
+               if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+                       server->caps |= NFS_CAP_READDIRPLUS;
+       } else {
+               if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
+                       server->namelen = NFS2_MAXNAMLEN;
+       }
+
        if (!(fattr.valid & NFS_ATTR_FATTR)) {
                error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
                if (error < 0) {
@@ -984,6 +984,9 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
        if (error < 0)
                goto error;
 
+       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+               server->namelen = NFS4_MAXNAMLEN;
+
        BUG_ON(!server->nfs_client);
        BUG_ON(!server->nfs_client->rpc_ops);
        BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
@@ -1056,6 +1059,9 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        if (error < 0)
                goto error;
 
+       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+               server->namelen = NFS4_MAXNAMLEN;
+
        dprintk("Referral FSID: %llx:%llx\n",
                (unsigned long long) server->fsid.major,
                (unsigned long long) server->fsid.minor);
@@ -1115,6 +1121,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
        if (error < 0)
                goto out_free_server;
 
+       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+               server->namelen = NFS4_MAXNAMLEN;
+
        dprintk("Cloned FSID: %llx:%llx\n",
                (unsigned long long) server->fsid.major,
                (unsigned long long) server->fsid.minor);
index ea97408e423e916bf77ef5b303541a23551d2cb3..e4a04d16b8b06fd4faf22b7ba238f404403a8c7f 100644 (file)
@@ -1162,6 +1162,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
        }
        if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
                return NULL;
+       if (name.len > NFS_SERVER(dir)->namelen)
+               return NULL;
        /* Note: caller is already holding the dir->i_mutex! */
        dentry = d_alloc(parent, &name);
        if (dentry == NULL)
index d1cbf0a0fbb2d457c92c964958e96dc2d9f56839..522e5ad4d8ad9b3946e201926c7f799ddf0f2e36 100644 (file)
@@ -175,6 +175,9 @@ next_component:
                path++;
        name.len = path - (const char *) name.name;
 
+       if (name.len > NFS4_MAXNAMLEN)
+               return -ENAMETOOLONG;
+
 eat_dot_dir:
        while (*path == '/')
                path++;
index 8ed593766f160260c972df87d93fc1ecb8634305..b878528b64c1a9d0aed22fd19b20339bc1644b22 100644 (file)
@@ -345,8 +345,8 @@ void __exit unregister_nfs_fs(void)
        unregister_shrinker(&acl_shrinker);
 #ifdef CONFIG_NFS_V4
        unregister_filesystem(&nfs4_fs_type);
-       nfs_unregister_sysctl();
 #endif
+       nfs_unregister_sysctl();
        unregister_filesystem(&nfs_fs_type);
 }
 
index 50cd8a209012ed0cd216c651483416c71baa0d28..f37f25c931f59f7e8b6b5c27ab502529f8621834 100644 (file)
@@ -930,18 +930,11 @@ static void ocfs2_write_failure(struct inode *inode,
                                loff_t user_pos, unsigned user_len)
 {
        int i;
-       unsigned from, to;
+       unsigned from = user_pos & (PAGE_CACHE_SIZE - 1),
+               to = user_pos + user_len;
        struct page *tmppage;
 
-       ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
-
-       if (wc->w_large_pages) {
-               from = wc->w_target_from;
-               to = wc->w_target_to;
-       } else {
-               from = 0;
-               to = PAGE_CACHE_SIZE;
-       }
+       ocfs2_zero_new_buffers(wc->w_target_page, from, to);
 
        for(i = 0; i < wc->w_num_pages; i++) {
                tmppage = wc->w_pages[i];
@@ -991,9 +984,6 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
                        map_from = cluster_start;
                        map_to = cluster_end;
                }
-
-               wc->w_target_from = map_from;
-               wc->w_target_to = map_to;
        } else {
                /*
                 * If we haven't allocated the new page yet, we
@@ -1211,18 +1201,33 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
                                       loff_t pos, unsigned len)
 {
        int ret, i;
+       loff_t cluster_off;
+       unsigned int local_len = len;
        struct ocfs2_write_cluster_desc *desc;
+       struct ocfs2_super *osb = OCFS2_SB(mapping->host->i_sb);
 
        for (i = 0; i < wc->w_clen; i++) {
                desc = &wc->w_desc[i];
 
+               /*
+                * We have to make sure that the total write passed in
+                * doesn't extend past a single cluster.
+                */
+               local_len = len;
+               cluster_off = pos & (osb->s_clustersize - 1);
+               if ((cluster_off + local_len) > osb->s_clustersize)
+                       local_len = osb->s_clustersize - cluster_off;
+
                ret = ocfs2_write_cluster(mapping, desc->c_phys,
                                          desc->c_unwritten, data_ac, meta_ac,
-                                         wc, desc->c_cpos, pos, len);
+                                         wc, desc->c_cpos, pos, local_len);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
+
+               len -= local_len;
+               pos += local_len;
        }
 
        ret = 0;
index 7e34e66159c690cb13beb43abaebe58b8f285333..f3bc3658e7a5ef69ee677c2822b541c557da84b7 100644 (file)
@@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_claim_clusters(osb, handle, data_ac, 1,
-                                     &bit_off, &num_bits);
+       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+                                       clusters_to_add, &bit_off, &num_bits);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
index 545f7892cdf39b645888e12fa8614598dbb86bfb..d272847d5a070491d22cda6b1f0b482423b33a39 100644 (file)
@@ -514,8 +514,10 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
        ac->ac_bh = osb->local_alloc_bh;
        status = 0;
 bail:
-       if (status < 0 && local_alloc_inode)
+       if (status < 0 && local_alloc_inode) {
+               mutex_unlock(&local_alloc_inode->i_mutex);
                iput(local_alloc_inode);
+       }
 
        mlog_exit(status);
        return status;
@@ -524,13 +526,12 @@ bail:
 int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 handle_t *handle,
                                 struct ocfs2_alloc_context *ac,
-                                u32 min_bits,
+                                u32 bits_wanted,
                                 u32 *bit_off,
                                 u32 *num_bits)
 {
        int status, start;
        struct inode *local_alloc_inode;
-       u32 bits_wanted;
        void *bitmap;
        struct ocfs2_dinode *alloc;
        struct ocfs2_local_alloc *la;
@@ -538,7 +539,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
        mlog_entry_void();
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
 
-       bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
        local_alloc_inode = ac->ac_inode;
        alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
        la = OCFS2_LOCAL_ALLOC(alloc);
index 385a10152f9c8a7fd72cad76ec2a0bc6a90eff09..3f76631e110c5a6284963cfe186b2c9a0917dabd 100644 (file)
@@ -48,7 +48,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 handle_t *handle,
                                 struct ocfs2_alloc_context *ac,
-                                u32 min_bits,
+                                u32 bits_wanted,
                                 u32 *bit_off,
                                 u32 *num_bits);
 
index d9c5c9fcb30fc300bb9132f54f0526156f5847b8..8f09f5235e3a68651ca279ab34598f2f22270cc8 100644 (file)
@@ -1486,21 +1486,21 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
  * contig. allocation, set to '1' to indicate we can deal with extents
  * of any size.
  */
-int ocfs2_claim_clusters(struct ocfs2_super *osb,
-                        handle_t *handle,
-                        struct ocfs2_alloc_context *ac,
-                        u32 min_clusters,
-                        u32 *cluster_start,
-                        u32 *num_clusters)
+int __ocfs2_claim_clusters(struct ocfs2_super *osb,
+                          handle_t *handle,
+                          struct ocfs2_alloc_context *ac,
+                          u32 min_clusters,
+                          u32 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters)
 {
        int status;
-       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+       unsigned int bits_wanted = max_clusters;
        u64 bg_blkno = 0;
        u16 bg_bit_off;
 
        mlog_entry_void();
 
-       BUG_ON(!ac);
        BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
 
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
@@ -1557,6 +1557,19 @@ bail:
        return status;
 }
 
+int ocfs2_claim_clusters(struct ocfs2_super *osb,
+                        handle_t *handle,
+                        struct ocfs2_alloc_context *ac,
+                        u32 min_clusters,
+                        u32 *cluster_start,
+                        u32 *num_clusters)
+{
+       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+
+       return __ocfs2_claim_clusters(osb, handle, ac, min_clusters,
+                                     bits_wanted, cluster_start, num_clusters);
+}
+
 static inline int ocfs2_block_group_clear_bits(handle_t *handle,
                                               struct inode *alloc_inode,
                                               struct ocfs2_group_desc *bg,
index f212dc01a84bd83088f5f7a70460a44efddc1b4a..cafe93703095f187a5fadf825a6415c9d1837bad 100644 (file)
@@ -85,6 +85,17 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
                         u32 min_clusters,
                         u32 *cluster_start,
                         u32 *num_clusters);
+/*
+ * Use this variant of ocfs2_claim_clusters to specify a maxiumum
+ * number of clusters smaller than the allocation reserved.
+ */
+int __ocfs2_claim_clusters(struct ocfs2_super *osb,
+                          handle_t *handle,
+                          struct ocfs2_alloc_context *ac,
+                          u32 min_clusters,
+                          u32 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters);
 
 int ocfs2_free_suballoc_bits(handle_t *handle,
                             struct inode *alloc_inode,
index 66a13ee63d4c7cd2ee496214cd7ea6a2c6b31b65..c05358538f2bfa96ddab90b7ddd1c01d1faa3efb 100644 (file)
@@ -66,7 +66,7 @@ struct ocfs2_vote_msg
 {
        struct ocfs2_msg_hdr v_hdr;
        __be32 v_reserved1;
-};
+} __attribute__ ((packed));
 
 /* Responses are given these values to maintain backwards
  * compatibility with older ocfs2 versions */
@@ -78,7 +78,7 @@ struct ocfs2_response_msg
 {
        struct ocfs2_msg_hdr r_hdr;
        __be32 r_response;
-};
+} __attribute__ ((packed));
 
 struct ocfs2_vote_work {
        struct list_head   w_list;
index a8e293d3003432ff493eff7069f32305fa35006a..aefb0be07942d735de747ad8697834368f8a907a 100644 (file)
  *      Now using anonymous inode source.
  *      Thanks to Oleg Nesterov for useful code review and suggestions.
  *      More comments and suggestions from Arnd Bergmann.
- * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
+ *  Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
  *      Retrieve multiple signals with one read() call
+ *  Sun Jul 15, 2007: Davide Libenzi <davidel@xmailserver.org>
+ *      Attach to the sighand only during read() and poll().
  */
 
 #include <linux/file.h>
 #include <linux/signalfd.h>
 
 struct signalfd_ctx {
-       struct list_head lnk;
-       wait_queue_head_t wqh;
        sigset_t sigmask;
-       struct task_struct *tsk;
 };
 
-struct signalfd_lockctx {
-       struct task_struct *tsk;
-       unsigned long flags;
-};
-
-/*
- * Tries to acquire the sighand lock. We do not increment the sighand
- * use count, and we do not even pin the task struct, so we need to
- * do it inside an RCU read lock, and we must be prepared for the
- * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand
- * being detached. We return 0 if the sighand has been detached, or
- * 1 if we were able to pin the sighand lock.
- */
-static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk)
-{
-       struct sighand_struct *sighand = NULL;
-
-       rcu_read_lock();
-       lk->tsk = rcu_dereference(ctx->tsk);
-       if (likely(lk->tsk != NULL))
-               sighand = lock_task_sighand(lk->tsk, &lk->flags);
-       rcu_read_unlock();
-
-       if (!sighand)
-               return 0;
-
-       if (!ctx->tsk) {
-               unlock_task_sighand(lk->tsk, &lk->flags);
-               return 0;
-       }
-
-       if (lk->tsk->tgid == current->tgid)
-               lk->tsk = current;
-
-       return 1;
-}
-
-static void signalfd_unlock(struct signalfd_lockctx *lk)
-{
-       unlock_task_sighand(lk->tsk, &lk->flags);
-}
-
-/*
- * This must be called with the sighand lock held.
- */
-void signalfd_deliver(struct task_struct *tsk, int sig)
-{
-       struct sighand_struct *sighand = tsk->sighand;
-       struct signalfd_ctx *ctx, *tmp;
-
-       BUG_ON(!sig);
-       list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) {
-               /*
-                * We use a negative signal value as a way to broadcast that the
-                * sighand has been orphaned, so that we can notify all the
-                * listeners about this. Remember the ctx->sigmask is inverted,
-                * so if the user is interested in a signal, that corresponding
-                * bit will be zero.
-                */
-               if (sig < 0) {
-                       if (ctx->tsk == tsk) {
-                               ctx->tsk = NULL;
-                               list_del_init(&ctx->lnk);
-                               wake_up(&ctx->wqh);
-                       }
-               } else {
-                       if (!sigismember(&ctx->sigmask, sig))
-                               wake_up(&ctx->wqh);
-               }
-       }
-}
-
-static void signalfd_cleanup(struct signalfd_ctx *ctx)
-{
-       struct signalfd_lockctx lk;
-
-       /*
-        * This is tricky. If the sighand is gone, we do not need to remove
-        * context from the list, the list itself won't be there anymore.
-        */
-       if (signalfd_lock(ctx, &lk)) {
-               list_del(&ctx->lnk);
-               signalfd_unlock(&lk);
-       }
-       kfree(ctx);
-}
-
 static int signalfd_release(struct inode *inode, struct file *file)
 {
-       signalfd_cleanup(file->private_data);
+       kfree(file->private_data);
        return 0;
 }
 
@@ -130,23 +42,15 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait)
 {
        struct signalfd_ctx *ctx = file->private_data;
        unsigned int events = 0;
-       struct signalfd_lockctx lk;
 
-       poll_wait(file, &ctx->wqh, wait);
+       poll_wait(file, &current->sighand->signalfd_wqh, wait);
 
-       /*
-        * Let the caller get a POLLIN in this case, ala socket recv() when
-        * the peer disconnects.
-        */
-       if (signalfd_lock(ctx, &lk)) {
-               if ((lk.tsk == current &&
-                    next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) ||
-                   next_signal(&lk.tsk->signal->shared_pending,
-                               &ctx->sigmask) > 0)
-                       events |= POLLIN;
-               signalfd_unlock(&lk);
-       } else
+       spin_lock_irq(&current->sighand->siglock);
+       if (next_signal(&current->pending, &ctx->sigmask) ||
+           next_signal(&current->signal->shared_pending,
+                       &ctx->sigmask))
                events |= POLLIN;
+       spin_unlock_irq(&current->sighand->siglock);
 
        return events;
 }
@@ -219,59 +123,46 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
                                int nonblock)
 {
        ssize_t ret;
-       struct signalfd_lockctx lk;
        DECLARE_WAITQUEUE(wait, current);
 
-       if (!signalfd_lock(ctx, &lk))
-               return 0;
-
-       ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+       spin_lock_irq(&current->sighand->siglock);
+       ret = dequeue_signal(current, &ctx->sigmask, info);
        switch (ret) {
        case 0:
                if (!nonblock)
                        break;
                ret = -EAGAIN;
        default:
-               signalfd_unlock(&lk);
+               spin_unlock_irq(&current->sighand->siglock);
                return ret;
        }
 
-       add_wait_queue(&ctx->wqh, &wait);
+       add_wait_queue(&current->sighand->signalfd_wqh, &wait);
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
-               ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
-               signalfd_unlock(&lk);
+               ret = dequeue_signal(current, &ctx->sigmask, info);
                if (ret != 0)
                        break;
                if (signal_pending(current)) {
                        ret = -ERESTARTSYS;
                        break;
                }
+               spin_unlock_irq(&current->sighand->siglock);
                schedule();
-               ret = signalfd_lock(ctx, &lk);
-               if (unlikely(!ret)) {
-                       /*
-                        * Let the caller read zero byte, ala socket
-                        * recv() when the peer disconnect. This test
-                        * must be done before doing a dequeue_signal(),
-                        * because if the sighand has been orphaned,
-                        * the dequeue_signal() call is going to crash
-                        * because ->sighand will be long gone.
-                        */
-                        break;
-               }
+               spin_lock_irq(&current->sighand->siglock);
        }
+       spin_unlock_irq(&current->sighand->siglock);
 
-       remove_wait_queue(&ctx->wqh, &wait);
+       remove_wait_queue(&current->sighand->signalfd_wqh, &wait);
        __set_current_state(TASK_RUNNING);
 
        return ret;
 }
 
 /*
- * Returns either the size of a "struct signalfd_siginfo", or zero if the
- * sighand we are attached to, has been orphaned. The "count" parameter
- * must be at least the size of a "struct signalfd_siginfo".
+ * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative
+ * error code. The "count" parameter must be at least the size of a
+ * "struct signalfd_siginfo".
  */
 static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
                             loff_t *ppos)
@@ -287,7 +178,6 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
                return -EINVAL;
 
        siginfo = (struct signalfd_siginfo __user *) buf;
-
        do {
                ret = signalfd_dequeue(ctx, &info, nonblock);
                if (unlikely(ret <= 0))
@@ -300,7 +190,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
                nonblock = 1;
        } while (--count);
 
-       return total ? total : ret;
+       return total ? total: ret;
 }
 
 static const struct file_operations signalfd_fops = {
@@ -309,20 +199,13 @@ static const struct file_operations signalfd_fops = {
        .read           = signalfd_read,
 };
 
-/*
- * Create a file descriptor that is associated with our signal
- * state. We can pass it around to others if we want to, but
- * it will always be _our_ signal state.
- */
 asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
 {
        int error;
        sigset_t sigmask;
        struct signalfd_ctx *ctx;
-       struct sighand_struct *sighand;
        struct file *file;
        struct inode *inode;
-       struct signalfd_lockctx lk;
 
        if (sizemask != sizeof(sigset_t) ||
            copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
@@ -335,17 +218,7 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
                if (!ctx)
                        return -ENOMEM;
 
-               init_waitqueue_head(&ctx->wqh);
                ctx->sigmask = sigmask;
-               ctx->tsk = current->group_leader;
-
-               sighand = current->sighand;
-               /*
-                * Add this fd to the list of signal listeners.
-                */
-               spin_lock_irq(&sighand->siglock);
-               list_add_tail(&ctx->lnk, &sighand->signalfd_list);
-               spin_unlock_irq(&sighand->siglock);
 
                /*
                 * When we call this, the initialization must be complete, since
@@ -364,23 +237,18 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
                        fput(file);
                        return -EINVAL;
                }
-               /*
-                * We need to be prepared of the fact that the sighand this fd
-                * is attached to, has been detched. In that case signalfd_lock()
-                * will return 0, and we'll just skip setting the new mask.
-                */
-               if (signalfd_lock(ctx, &lk)) {
-                       ctx->sigmask = sigmask;
-                       signalfd_unlock(&lk);
-               }
-               wake_up(&ctx->wqh);
+               spin_lock_irq(&current->sighand->siglock);
+               ctx->sigmask = sigmask;
+               spin_unlock_irq(&current->sighand->siglock);
+
+               wake_up(&current->sighand->signalfd_wqh);
                fput(file);
        }
 
        return ufd;
 
 err_fdalloc:
-       signalfd_cleanup(ctx);
+       kfree(ctx);
        return error;
 }
 
index c010a72ca2d2a3543fb2a7365b2e8c5b4c73b652..e95a36228863affa3d6c19a37ac4766f8e147412 100644 (file)
@@ -1223,6 +1223,33 @@ static long do_splice(struct file *in, loff_t __user *off_in,
        return -EINVAL;
 }
 
+/*
+ * Do a copy-from-user while holding the mmap_semaphore for reading, in a
+ * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem
+ * for writing) and page faulting on the user memory pointed to by src.
+ * This assumes that we will very rarely hit the partial != 0 path, or this
+ * will not be a win.
+ */
+static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n)
+{
+       int partial;
+
+       pagefault_disable();
+       partial = __copy_from_user_inatomic(dst, src, n);
+       pagefault_enable();
+
+       /*
+        * Didn't copy everything, drop the mmap_sem and do a faulting copy
+        */
+       if (unlikely(partial)) {
+               up_read(&current->mm->mmap_sem);
+               partial = copy_from_user(dst, src, n);
+               down_read(&current->mm->mmap_sem);
+       }
+
+       return partial;
+}
+
 /*
  * Map an iov into an array of pages and offset/length tupples. With the
  * partial_page structure, we can map several non-contiguous ranges into
@@ -1236,31 +1263,26 @@ static int get_iovec_page_array(const struct iovec __user *iov,
 {
        int buffers = 0, error = 0;
 
-       /*
-        * It's ok to take the mmap_sem for reading, even
-        * across a "get_user()".
-        */
        down_read(&current->mm->mmap_sem);
 
        while (nr_vecs) {
                unsigned long off, npages;
+               struct iovec entry;
                void __user *base;
                size_t len;
                int i;
 
-               /*
-                * Get user address base and length for this iovec.
-                */
-               error = get_user(base, &iov->iov_base);
-               if (unlikely(error))
-                       break;
-               error = get_user(len, &iov->iov_len);
-               if (unlikely(error))
+               error = -EFAULT;
+               if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry)))
                        break;
 
+               base = entry.iov_base;
+               len = entry.iov_len;
+
                /*
                 * Sanity check this iovec. 0 read succeeds.
                 */
+               error = 0;
                if (unlikely(!len))
                        break;
                error = -EFAULT;
index 73402c5eeb8afc90452768b57f0cbdb13fcc3469..38eb0b7a1f3d3111c0e4a1b604d7ac40e110cc46 100644 (file)
@@ -894,7 +894,7 @@ magic_found:
                goto again;
        }
 
-
+       sbi->s_flags = flags;/*after that line some functions use s_flags*/
        ufs_print_super_stuff(sb, usb1, usb2, usb3);
 
        /*
@@ -1025,8 +1025,6 @@ magic_found:
            UFS_MOUNT_UFSTYPE_44BSD)
                uspi->s_maxsymlinklen =
                    fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen);
-       
-       sbi->s_flags = flags;
 
        inode = iget(sb, UFS_ROOTINO);
        if (!inode || is_bad_inode(inode))
index d9c40fe641953a20b9b5fc8059f65b481382f9b7..5f152f60d74d83ce8878fcba2ee16780ee767513 100644 (file)
@@ -181,6 +181,7 @@ xfs_setfilesize(
                ip->i_d.di_size = isize;
                ip->i_update_core = 1;
                ip->i_update_size = 1;
+               mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
        }
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
index 4528f9a3f304d5e923fa09458bd6aacfd04161c2..491d1f4f202d8d5919ade355c0a212825e8c8a54 100644 (file)
@@ -415,8 +415,10 @@ xfs_fs_write_inode(
 
        if (vp) {
                vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-               if (sync)
+               if (sync) {
+                       filemap_fdatawait(inode->i_mapping);
                        flags |= FLUSH_SYNC;
+               }
                error = bhv_vop_iflush(vp, flags);
                if (error == EAGAIN)
                        error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
index ce2278611bb74232269f2adad55a7e619141988f..36d8f6aa11afeed014b3223c1a00334a502c9e38 100644 (file)
@@ -350,9 +350,10 @@ _xfs_filestream_update_ag(
 /* xfs_fstrm_free_func(): callback for freeing cached stream items. */
 void
 xfs_fstrm_free_func(
-       xfs_ino_t       ino,
-       fstrm_item_t    *item)
+       unsigned long   ino,
+       void            *data)
 {
+       fstrm_item_t    *item  = (fstrm_item_t *)data;
        xfs_inode_t     *ip = item->ip;
        int ref;
 
@@ -438,7 +439,7 @@ xfs_filestream_mount(
        grp_count = 10;
 
        err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count,
-                            (xfs_mru_cache_free_func_t)xfs_fstrm_free_func);
+                            xfs_fstrm_free_func);
 
        return err;
 }
@@ -467,8 +468,7 @@ void
 xfs_filestream_flush(
        xfs_mount_t     *mp)
 {
-       /* point in time flush, so keep the reaper running */
-       xfs_mru_cache_flush(mp->m_filestream, 1);
+       xfs_mru_cache_flush(mp->m_filestream);
 }
 
 /*
index 7deb9e3cbbd3dcb2669186605f8cb9fc91d084e3..e0b358c1c533cc66220d47140dbd5df4b0341a96 100644 (file)
@@ -206,8 +206,11 @@ _xfs_mru_cache_list_insert(
         */
        if (!_xfs_mru_cache_migrate(mru, now)) {
                mru->time_zero = now;
-               if (!mru->next_reap)
-                       mru->next_reap = mru->grp_count * mru->grp_time;
+               if (!mru->queued) {
+                       mru->queued = 1;
+                       queue_delayed_work(xfs_mru_reap_wq, &mru->work,
+                                          mru->grp_count * mru->grp_time);
+               }
        } else {
                grp = (now - mru->time_zero) / mru->grp_time;
                grp = (mru->lru_grp + grp) % mru->grp_count;
@@ -271,29 +274,26 @@ _xfs_mru_cache_reap(
        struct work_struct      *work)
 {
        xfs_mru_cache_t         *mru = container_of(work, xfs_mru_cache_t, work.work);
-       unsigned long           now;
+       unsigned long           now, next;
 
        ASSERT(mru && mru->lists);
        if (!mru || !mru->lists)
                return;
 
        mutex_spinlock(&mru->lock);
-       now = jiffies;
-       if (mru->reap_all ||
-           (mru->next_reap && time_after(now, mru->next_reap))) {
-               if (mru->reap_all)
-                       now += mru->grp_count * mru->grp_time * 2;
-               mru->next_reap = _xfs_mru_cache_migrate(mru, now);
-               _xfs_mru_cache_clear_reap_list(mru);
+       next = _xfs_mru_cache_migrate(mru, jiffies);
+       _xfs_mru_cache_clear_reap_list(mru);
+
+       mru->queued = next;
+       if ((mru->queued > 0)) {
+               now = jiffies;
+               if (next <= now)
+                       next = 0;
+               else
+                       next -= now;
+               queue_delayed_work(xfs_mru_reap_wq, &mru->work, next);
        }
 
-       /*
-        * the process that triggered the reap_all is responsible
-        * for restating the periodic reap if it is required.
-        */
-       if (!mru->reap_all)
-               queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
-       mru->reap_all = 0;
        mutex_spinunlock(&mru->lock, 0);
 }
 
@@ -352,7 +352,7 @@ xfs_mru_cache_create(
 
        /* An extra list is needed to avoid reaping up to a grp_time early. */
        mru->grp_count = grp_count + 1;
-       mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
+       mru->lists = kmem_zalloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
 
        if (!mru->lists) {
                err = ENOMEM;
@@ -374,11 +374,6 @@ xfs_mru_cache_create(
        mru->grp_time  = grp_time;
        mru->free_func = free_func;
 
-       /* start up the reaper event */
-       mru->next_reap = 0;
-       mru->reap_all = 0;
-       queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
-
        *mrup = mru;
 
 exit:
@@ -394,35 +389,25 @@ exit:
  * Call xfs_mru_cache_flush() to flush out all cached entries, calling their
  * free functions as they're deleted.  When this function returns, the caller is
  * guaranteed that all the free functions for all the elements have finished
- * executing.
- *
- * While we are flushing, we stop the periodic reaper event from triggering.
- * Normally, we want to restart this periodic event, but if we are shutting
- * down the cache we do not want it restarted. hence the restart parameter
- * where 0 = do not restart reaper and 1 = restart reaper.
+ * executing and the reaper is not running.
  */
 void
 xfs_mru_cache_flush(
-       xfs_mru_cache_t         *mru,
-       int                     restart)
+       xfs_mru_cache_t         *mru)
 {
        if (!mru || !mru->lists)
                return;
 
-       cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
-
        mutex_spinlock(&mru->lock);
-       mru->reap_all = 1;
-       mutex_spinunlock(&mru->lock, 0);
+       if (mru->queued) {
+               mutex_spinunlock(&mru->lock, 0);
+               cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
+               mutex_spinlock(&mru->lock);
+       }
 
-       queue_work(xfs_mru_reap_wq, &mru->work.work);
-       flush_workqueue(xfs_mru_reap_wq);
+       _xfs_mru_cache_migrate(mru, jiffies + mru->grp_count * mru->grp_time);
+       _xfs_mru_cache_clear_reap_list(mru);
 
-       mutex_spinlock(&mru->lock);
-       WARN_ON_ONCE(mru->reap_all != 0);
-       mru->reap_all = 0;
-       if (restart)
-               queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
        mutex_spinunlock(&mru->lock, 0);
 }
 
@@ -433,8 +418,7 @@ xfs_mru_cache_destroy(
        if (!mru || !mru->lists)
                return;
 
-       /* we don't want the reaper to restart here */
-       xfs_mru_cache_flush(mru, 0);
+       xfs_mru_cache_flush(mru);
 
        kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
        kmem_free(mru, sizeof(*mru));
index 624fd10ee8e5ed21be6be354bb999e147989b915..dd58ea1bbebefeb0a49116c1f52be41e4dc60e44 100644 (file)
@@ -32,11 +32,9 @@ typedef struct xfs_mru_cache
        unsigned int            grp_time;  /* Time period spanned by grps.  */
        unsigned int            lru_grp;   /* Group containing time zero.   */
        unsigned long           time_zero; /* Time first element was added. */
-       unsigned long           next_reap; /* Time that the reaper should
-                                             next do something. */
-       unsigned int            reap_all;  /* if set, reap all lists */
        xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
        struct delayed_work     work;      /* Workqueue data for reaping.   */
+       unsigned int            queued;    /* work has been queued */
 } xfs_mru_cache_t;
 
 int xfs_mru_cache_init(void);
@@ -44,7 +42,7 @@ void xfs_mru_cache_uninit(void);
 int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
                             unsigned int grp_count,
                             xfs_mru_cache_free_func_t free_func);
-void xfs_mru_cache_flush(xfs_mru_cache_t *mru, int restart);
+void xfs_mru_cache_flush(xfs_mru_cache_t *mru);
 void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
 int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
                                void *value);
index 1a5ad8cd97b00d3d8cd24c04961ea075cb5e1635..603459229904e0b6701b4a883b262041967e9a0a 100644 (file)
@@ -1082,6 +1082,9 @@ xfs_fsync(
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return XFS_ERROR(EIO);
 
+       if (flag & FSYNC_DATA)
+               filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping);
+
        /*
         * We always need to make sure that the required inode state
         * is safe on disk.  The vnode might be clean but because
@@ -3769,12 +3772,16 @@ xfs_inode_flush(
                        sync_lsn = log->l_last_sync_lsn;
                        GRANT_UNLOCK(log, s);
 
-                       if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) <= 0))
-                               return 0;
+                       if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) {
+                               if (flags & FLUSH_SYNC)
+                                       log_flags |= XFS_LOG_SYNC;
+                               error = xfs_log_force(mp, iip->ili_last_lsn, log_flags);
+                               if (error)
+                                       return error;
+                       }
 
-                       if (flags & FLUSH_SYNC)
-                               log_flags |= XFS_LOG_SYNC;
-                       return xfs_log_force(mp, iip->ili_last_lsn, log_flags);
+                       if (ip->i_update_core == 0)
+                               return 0;
                }
        }
 
@@ -3788,9 +3795,6 @@ xfs_inode_flush(
        if (flags & FLUSH_INODE) {
                int     flush_flags;
 
-               if (xfs_ipincount(ip))
-                       return EAGAIN;
-
                if (flags & FLUSH_SYNC) {
                        xfs_ilock(ip, XFS_ILOCK_SHARED);
                        xfs_iflock(ip);
index 202acb9ff4d071299cb0926c8887cc5d3b57bd53..f85f77a538aa67afb418b4b35ba8c3ccd945516f 100644 (file)
@@ -147,10 +147,6 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle)
 /*--------------------------------------------------------------------------
                                   Suspend/Resume
   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_SLEEP
 extern int acpi_sleep_init(void);
-#else
-static inline int acpi_sleep_init(void) { return 0; }
-#endif
 
 #endif /*__ACPI_DRIVERS_H__*/
index ec3ffdadb4d257c452d091b30e8322c01c049e3f..99934a999e6651e904bc23310d7c36a17153f05f 100644 (file)
@@ -320,6 +320,8 @@ int acpi_processor_power_init(struct acpi_processor *pr,
 int acpi_processor_cst_has_changed(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr,
                              struct acpi_device *device);
+int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
+int acpi_processor_resume(struct acpi_device * device);
 
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
index e043cafa3c429795c3eb7e473e04da4eac58c50f..69b9f8e120e93402b5cae571f2e8dfdd26084e49 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/serial.h>
 #include <asm/dma.h>
+#include <asm/portmux.h>
 
 #define NR_PORTS                1
 
@@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = {
        }
 };
 
+#define DRIVER_NAME "bfin-uart"
 
 int nr_ports = NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_CTSRTS
        if (uart->cts_pin >= 0) {
-               gpio_request(uart->cts_pin, NULL);
+               gpio_request(uart->cts_pin, DRIVER_NAME);
                gpio_direction_input(uart->cts_pin);
        }
        if (uart->rts_pin >= 0) {
-               gpio_request(uart->rts_pin, NULL);
+               gpio_request(uart->rts_pin, DRIVER_NAME);
                gpio_direction_input(uart->rts_pin);
        }
 #endif
index 8f5d9c4d8d5b836e51f7ffcb0bfdd396bbd9610c..6fb328f5186a25dd759e35e944576ab434306f55 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/serial.h>
 #include <asm/dma.h>
+#include <asm/portmux.h>
 
 #define NR_PORTS               2
 
@@ -122,25 +123,29 @@ struct bfin_serial_res bfin_serial_resource[] = {
 
 int nr_ports = ARRAY_SIZE(bfin_serial_resource);
 
+#define DRIVER_NAME "bfin-uart"
+
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
-       unsigned short val;
-       val = bfin_read16(BFIN_PORT_MUX);
-       val &= ~(PFDE | PFTE);
-       bfin_write16(BFIN_PORT_MUX, val);
 
-       val = bfin_read16(PORTF_FER);
-       val |= 0xF;
-       bfin_write16(PORTF_FER, val);
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       peripheral_request(P_UART1_TX, DRIVER_NAME);
+       peripheral_request(P_UART1_RX, DRIVER_NAME);
+#endif
 
 #ifdef CONFIG_SERIAL_BFIN_CTSRTS
        if (uart->cts_pin >= 0) {
-               gpio_request(uart->cts_pin, NULL);
+               gpio_request(uart->cts_pin, DRIVER_NAME);
                gpio_direction_input(uart->cts_pin);
        }
 
        if (uart->rts_pin >= 0) {
-               gpio_request(uart->rts_pin, NULL);
+               gpio_request(uart->rts_pin, DRIVER_NAME);
                gpio_direction_output(uart->rts_pin);
        }
 #endif
index 23e13c5abc4d9deb689c2d4c5d69c6d62567045e..ae6c53b28452520919decaa007c3979a2dd2896a 100644 (file)
 #define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
 #define P_SPI0_SSEL7   (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2))
 
-#endif /* _MACH_PORTMUX_H_ */
+#define P_MII0 {\
+       P_MII0_ETxD0, \
+       P_MII0_ETxD1, \
+       P_MII0_ETxD2, \
+       P_MII0_ETxD3, \
+       P_MII0_ETxEN, \
+       P_MII0_TxCLK, \
+       P_MII0_PHYINT, \
+       P_MII0_COL, \
+       P_MII0_ERxD0, \
+       P_MII0_ERxD1, \
+       P_MII0_ERxD2, \
+       P_MII0_ERxD3, \
+       P_MII0_ERxDV, \
+       P_MII0_ERxCLK, \
+       P_MII0_ERxER, \
+       P_MII0_CRS, \
+       P_MDC, \
+       P_MDIO, 0}
+
+
+#define P_RMII0 {\
+       P_MII0_ETxD0, \
+       P_MII0_ETxD1, \
+       P_MII0_ETxEN, \
+       P_MII0_ERxD0, \
+       P_MII0_ERxD1, \
+       P_MII0_ERxER, \
+       P_RMII0_REF_CLK, \
+       P_RMII0_MDINT, \
+       P_RMII0_CRS_DV, \
+       P_MDC, \
+       P_MDIO, 0}
+#endif                                 /* _MACH_PORTMUX_H_ */
index e043cafa3c429795c3eb7e473e04da4eac58c50f..69b9f8e120e93402b5cae571f2e8dfdd26084e49 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/serial.h>
 #include <asm/dma.h>
+#include <asm/portmux.h>
 
 #define NR_PORTS                1
 
@@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = {
        }
 };
 
+#define DRIVER_NAME "bfin-uart"
 
 int nr_ports = NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
 #ifdef CONFIG_SERIAL_BFIN_CTSRTS
        if (uart->cts_pin >= 0) {
-               gpio_request(uart->cts_pin, NULL);
+               gpio_request(uart->cts_pin, DRIVER_NAME);
                gpio_direction_input(uart->cts_pin);
        }
        if (uart->rts_pin >= 0) {
-               gpio_request(uart->rts_pin, NULL);
+               gpio_request(uart->rts_pin, DRIVER_NAME);
                gpio_direction_input(uart->rts_pin);
        }
 #endif
index 9d3681e4211107524e66ed1a25a88c97f5567b40..0d3f650d2d99ad50ecc4dc4269d1117581985507 100644 (file)
 #define P_MAYSHARE     0x2000
 #define P_DONTCARE     0x1000
 
+
+int peripheral_request(unsigned short per, const char *label);
+void peripheral_free(unsigned short per);
+int peripheral_request_list(unsigned short per[], const char *label);
+void peripheral_free_list(unsigned short per[]);
+
 #include <asm/gpio.h>
 #include <asm/mach/portmux.h>
 
 #define P_SPI2_SSEL3 P_UNDEF
 #endif
 
+#ifndef P_SPI2_SSEL4
+#define P_SPI2_SSEL4 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL5
+#define P_SPI2_SSEL5 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL6
+#define P_SPI2_SSEL6 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL7
+#define P_SPI2_SSEL7 P_UNDEF
+#endif
+
 #ifndef P_SPI2_SCK
 #define P_SPI2_SCK P_UNDEF
 #endif
 #define P_SPI0_SSEL3 P_UNDEF
 #endif
 
+#ifndef P_SPI0_SSEL4
+#define P_SPI0_SSEL4 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL5
+#define P_SPI0_SSEL5 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL6
+#define P_SPI0_SSEL6 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL7
+#define P_SPI0_SSEL7 P_UNDEF
+#endif
+
 #ifndef P_UART0_TX
 #define P_UART0_TX P_UNDEF
 #endif
 #define P_SPI1_SSEL3 P_UNDEF
 #endif
 
+
+#ifndef P_SPI1_SSEL4
+#define P_SPI1_SSEL4 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL5
+#define P_SPI1_SSEL5 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL6
+#define P_SPI1_SSEL6 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL7
+#define P_SPI1_SSEL7 P_UNDEF
+#endif
+
 #ifndef P_SPI1_SCK
 #define P_SPI1_SCK P_UNDEF
 #endif
index 0df9f2d322a3a473b54ef9bd4c14ad194966b0c9..07ffe8b718c51a0d379ec07d43b5277c20a63eda 100644 (file)
@@ -3,6 +3,7 @@
 /*
  * This file contains the system call numbers.
  */
+#define __NR_restart_syscall     0
 #define __NR_exit                1
 #define __NR_fork                2
 #define __NR_read                3
 #define __NR_sched_get_priority_min    160
 #define __NR_sched_rr_get_interval     161
 #define __NR_nanosleep         162
-                               /* 163 __NR_mremap */
+#define __NR_mremap            163
 #define __NR_setresuid         164
 #define __NR_getresuid         165
                                /* 166 __NR_vm86 */
                                /* 167 __NR_query_module */
                                /* 168 __NR_poll */
-                               /* 169 __NR_nfsservctl */
+#define __NR_nfsservctl                169
 #define __NR_setresgid         170
 #define __NR_getresgid         171
 #define __NR_prctl             172
                                /* 222 reserved for TUX */
                                /* 223 reserved for TUX */
 #define __NR_gettid            224
-                               /* 225 __NR_readahead */
+#define __NR_readahead         225
 #define __NR_setxattr          226
 #define __NR_lsetxattr         227
 #define __NR_fsetxattr         228
 #define __NR_mq_timedreceive   (__NR_mq_open+3)
 #define __NR_mq_notify         (__NR_mq_open+4)
 #define __NR_mq_getsetattr     (__NR_mq_open+5)
-                               /* 284 __NR_sys_kexec_load */
+#define __NR_kexec_load                284
 #define __NR_waitid            285
 #define __NR_add_key           286
 #define __NR_request_key       287
 #define __NR_shmdt             340
 #define __NR_shmget            341
 
-#define __NR_syscall           342
+#define __NR_splice            342
+#define __NR_sync_file_range   343
+#define __NR_tee               344
+#define __NR_vmsplice          345
+
+#define __NR_epoll_pwait       346
+#define __NR_utimensat         347
+#define __NR_signalfd          348
+#define __NR_timerfd           349
+#define __NR_eventfd           350
+#define __NR_pread64           351
+#define __NR_pwrite64          352
+#define __NR_fadvise64         353
+#define __NR_set_robust_list   354
+#define __NR_get_robust_list   355
+#define __NR_fallocate         356
+
+#define __NR_syscall           357
 #define NR_syscalls            __NR_syscall
 
+/* Old optional stuff no one actually uses */
+#define __IGNORE_sysfs
+#define __IGNORE_uselib
+
+/* Implement the newer interfaces */
+#define __IGNORE_mmap
+#define __IGNORE_poll
+#define __IGNORE_select
+#define __IGNORE_utime
+
+/* Not relevant on no-mmu */
+#define __IGNORE_swapon
+#define __IGNORE_swapoff
+#define __IGNORE_msync
+#define __IGNORE_mlock
+#define __IGNORE_munlock
+#define __IGNORE_mlockall
+#define __IGNORE_munlockall
+#define __IGNORE_mincore
+#define __IGNORE_madvise
+#define __IGNORE_remap_file_pages
+#define __IGNORE_mbind
+#define __IGNORE_get_mempolicy
+#define __IGNORE_set_mempolicy
+#define __IGNORE_migrate_pages
+#define __IGNORE_move_pages
+#define __IGNORE_getcpu
+
 #ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
index c20eee767d6f1ebeca20e5933dbd8f71452d199e..2a873508a9a101b359483ebbf086f84aa769f0f0 100644 (file)
@@ -9,6 +9,7 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                1
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
+#define        flat_set_persistent(relval, p)          0
 
 /*
  * on the H8 a couple of the relocations have an instruction in the
@@ -18,7 +19,7 @@
  */
 
 #define        flat_get_relocate_addr(rel)             (rel)
-#define flat_get_addr_from_rp(rp, relval, flags) \
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
         (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff))
 #define flat_put_addr_at_rp(rp, addr, rel) \
        put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp)
index 609756c616769194763fb3b17dbf046ca3c25059..d69ba937e09251769e2f00d54c0c91562a4127e8 100644 (file)
@@ -214,11 +214,6 @@ static inline unsigned long get_limit(unsigned long segment)
  */
  
 
-/* 
- * Actually only lfence would be needed for mb() because all stores done 
- * by the kernel should be already ordered. But keep a full barrier for now. 
- */
-
 #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
 #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
 
index 1b285f65cab631506ed7169d50a6ae94dde311b5..d851cf0c4aa5ecff7902da7a54fdab618eccdad4 100644 (file)
 #define        flat_stack_align(sp)            (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0))
 #define        flat_argvp_envp_on_stack()              0
 #define        flat_old_ram_flag(flags)                (flags)
+#define        flat_set_persistent(relval, p)          0
 #define        flat_reloc_valid(reloc, size)           \
        (((reloc) - textlen_for_m32r_lo16_data) <= (size))
-#define flat_get_addr_from_rp(rp, relval, flags) \
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
        m32r_flat_get_addr_from_rp(rp, relval, (text_len) )
 
 #define flat_put_addr_at_rp(rp, addr, relval) \
index 2d836edc43441e9a005b533147d29cca26180f18..814b5174a8e0ffb623aa96e65f9b2a1b52a4ddad 100644 (file)
@@ -9,8 +9,9 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags)        get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, p)     get_unaligned(rp)
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
+#define        flat_set_persistent(relval, p)          0
 
 #endif /* __M68KNOMMU_FLAT_H__ */
diff --git a/include/asm-mips/cmpxchg.h b/include/asm-mips/cmpxchg.h
new file mode 100644 (file)
index 0000000..c5b4708
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_CMPXCHG_H
+#define __ASM_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define __cmpxchg_asm(ld, st, m, old, new)                             \
+({                                                                     \
+       __typeof(*(m)) __ret;                                           \
+                                                                       \
+       if (cpu_has_llsc && R10000_LLSC_WAR) {                          \
+               __asm__ __volatile__(                                   \
+               "       .set    push                            \n"     \
+               "       .set    noat                            \n"     \
+               "       .set    mips3                           \n"     \
+               "1:     " ld "  %0, %2          # __cmpxchg_asm \n"     \
+               "       bne     %0, %z3, 2f                     \n"     \
+               "       .set    mips0                           \n"     \
+               "       move    $1, %z4                         \n"     \
+               "       .set    mips3                           \n"     \
+               "       " st "  $1, %1                          \n"     \
+               "       beqzl   $1, 1b                          \n"     \
+               "2:                                             \n"     \
+               "       .set    pop                             \n"     \
+               : "=&r" (__ret), "=R" (*m)                              \
+               : "R" (*m), "Jr" (old), "Jr" (new)                      \
+               : "memory");                                            \
+       } else if (cpu_has_llsc) {                                      \
+               __asm__ __volatile__(                                   \
+               "       .set    push                            \n"     \
+               "       .set    noat                            \n"     \
+               "       .set    mips3                           \n"     \
+               "1:     " ld "  %0, %2          # __cmpxchg_asm \n"     \
+               "       bne     %0, %z3, 2f                     \n"     \
+               "       .set    mips0                           \n"     \
+               "       move    $1, %z4                         \n"     \
+               "       .set    mips3                           \n"     \
+               "       " st "  $1, %1                          \n"     \
+               "       beqz    $1, 3f                          \n"     \
+               "2:                                             \n"     \
+               "       .subsection 2                           \n"     \
+               "3:     b       1b                              \n"     \
+               "       .previous                               \n"     \
+               "       .set    pop                             \n"     \
+               : "=&r" (__ret), "=R" (*m)                              \
+               : "R" (*m), "Jr" (old), "Jr" (new)                      \
+               : "memory");                                            \
+       } else {                                                        \
+               unsigned long __flags;                                  \
+                                                                       \
+               raw_local_irq_save(__flags);                            \
+               __ret = *m;                                             \
+               if (__ret == old)                                       \
+                       *m = new;                                       \
+               raw_local_irq_restore(__flags);                         \
+       }                                                               \
+                                                                       \
+       __ret;                                                          \
+})
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg().
+ */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __cmpxchg(ptr,old,new,barrier)                                 \
+({                                                                     \
+       __typeof__(ptr) __ptr = (ptr);                                  \
+       __typeof__(*(ptr)) __old = (old);                               \
+       __typeof__(*(ptr)) __new = (new);                               \
+       __typeof__(*(ptr)) __res = 0;                                   \
+                                                                       \
+       barrier;                                                        \
+                                                                       \
+       switch (sizeof(*(__ptr))) {                                     \
+       case 4:                                                         \
+               __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \
+               break;                                                  \
+       case 8:                                                         \
+               if (sizeof(long) == 8) {                                \
+                       __res = __cmpxchg_asm("lld", "scd", __ptr,      \
+                                          __old, __new);               \
+                       break;                                          \
+               }                                                       \
+       default:                                                        \
+               __cmpxchg_called_with_bad_pointer();                    \
+               break;                                                  \
+       }                                                               \
+                                                                       \
+       barrier;                                                        \
+                                                                       \
+       __res;                                                          \
+})
+
+#define cmpxchg(ptr, old, new)         __cmpxchg(ptr, old, new, smp_llsc_mb())
+#define cmpxchg_local(ptr, old, new)   __cmpxchg(ptr, old, new,)
+
+#endif /* __ASM_CMPXCHG_H */
index 169ae26105e9d8d5f71b41606f5399d9243db170..aa6b876bbd78d153042af014979eea2af04b768a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004  Maciej W. Rozycki
+ * Copyright (C) 2004, 2007  Maciej W. Rozycki
  *
  * 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
@@ -9,8 +9,10 @@
 #define _ASM_COMPILER_H
 
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define GCC_IMM_ASM "n"
 #define GCC_REG_ACCUM "$0"
 #else
+#define GCC_IMM_ASM "rn"
 #define GCC_REG_ACCUM "accum"
 #endif
 
index 00a50ec1c19fd6426bd57732aad5e2bdd64e7807..2a52333a062d1879d6b06cc2ab1bb44fc67d95b4 100644 (file)
@@ -13,6 +13,7 @@
 #define O_SYNC         0x0010
 #define O_NONBLOCK     0x0080
 #define O_CREAT         0x0100 /* not fcntl */
+#define O_TRUNC                0x0200  /* not fcntl */
 #define O_EXCL         0x0400  /* not fcntl */
 #define O_NOCTTY       0x0800  /* not fcntl */
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
index 97102ebc54b19d44137945dcac23833eceec6ada..2cb52cf8bd4ebe378b2e6f37890dc857a330dca1 100644 (file)
@@ -24,7 +24,30 @@ static inline int irq_canonicalize(int irq)
 #define irq_canonicalize(irq) (irq)    /* Sane hardware, sane code ... */
 #endif
 
+#ifdef CONFIG_MIPS_MT_SMTC
+
+struct irqaction;
+
+extern unsigned long irq_hwmask[];
+extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+                          unsigned long hwmask);
+
+static inline void smtc_im_ack_irq(unsigned int irq)
+{
+       if (irq_hwmask[irq] & ST0_IM)
+               set_c0_status(irq_hwmask[irq] & ST0_IM);
+}
+
+#else
+
+static inline void smtc_im_ack_irq(unsigned int irq)
+{
+}
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
+
 /*
  * Clear interrupt mask handling "backstop" if irq_hwmask
  * entry so indicates. This implies that the ack() or end()
@@ -38,6 +61,7 @@ do {                                                                  \
                                   ~(irq_hwmask[irq] & 0x0000ff00));    \
 } while (0)
 #else
+
 #define __DO_IRQ_SMTC_HOOK(irq) do { } while (0)
 #endif
 
@@ -60,14 +84,6 @@ do {                                                                 \
 extern void arch_init_irq(void);
 extern void spurious_interrupt(void);
 
-#ifdef CONFIG_MIPS_MT_SMTC
-struct irqaction;
-
-extern unsigned long irq_hwmask[];
-extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
-                          unsigned long hwmask);
-#endif /* CONFIG_MIPS_MT_SMTC */
-
 extern int allocate_irqno(void);
 extern void alloc_legacy_irqno(void);
 extern void free_irqno(unsigned int irq);
index ed882c88e0caa0e8d9add0be6b7c8ce7576c36cd..f9a5ce5c9af174aae59d3da955f0c351280f4d7f 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/percpu.h>
 #include <linux/bitops.h>
 #include <asm/atomic.h>
+#include <asm/cmpxchg.h>
 #include <asm/war.h>
 
 typedef struct
@@ -114,68 +115,6 @@ static __inline__ long local_sub_return(long i, local_t * l)
        return result;
 }
 
-/*
- * local_sub_if_positive - conditionally subtract integer from atomic variable
- * @i: integer value to subtract
- * @l: pointer of type local_t
- *
- * Atomically test @l and subtract @i if @l is greater or equal than @i.
- * The function returns the old value of @l minus @i.
- */
-static __inline__ long local_sub_if_positive(long i, local_t * l)
-{
-       unsigned long result;
-
-       if (cpu_has_llsc && R10000_LLSC_WAR) {
-               unsigned long temp;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:"    __LL    "%1, %2         # local_sub_if_positive\n"
-               "       dsubu   %0, %1, %3                              \n"
-               "       bltz    %0, 1f                                  \n"
-                       __SC    "%0, %2                                 \n"
-               "       .set    noreorder                               \n"
-               "       beqzl   %0, 1b                                  \n"
-               "        dsubu  %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
-               "1:                                                     \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
-               : "Ir" (i), "m" (l->a.counter)
-               : "memory");
-       } else if (cpu_has_llsc) {
-               unsigned long temp;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:"    __LL    "%1, %2         # local_sub_if_positive\n"
-               "       dsubu   %0, %1, %3                              \n"
-               "       bltz    %0, 1f                                  \n"
-                       __SC    "%0, %2                                 \n"
-               "       .set    noreorder                               \n"
-               "       beqz    %0, 1b                                  \n"
-               "        dsubu  %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
-               "1:                                                     \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (result), "=&r" (temp), "=m" (l->a.counter)
-               : "Ir" (i), "m" (l->a.counter)
-               : "memory");
-       } else {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               result = l->a.counter;
-               result -= i;
-               if (result >= 0)
-                       l->a.counter = result;
-               local_irq_restore(flags);
-       }
-
-       return result;
-}
-
 #define local_cmpxchg(l, o, n) \
        ((long)cmpxchg_local(&((l)->a.counter), (o), (n)))
 #define local_xchg(l, n) (xchg_local(&((l)->a.counter),(n)))
@@ -233,12 +172,6 @@ static __inline__ long local_sub_if_positive(long i, local_t * l)
  */
 #define local_dec_and_test(l) (local_sub_return(1, (l)) == 0)
 
-/*
- * local_dec_if_positive - decrement by 1 if old value positive
- * @l: pointer of type local_t
- */
-#define local_dec_if_positive(l)       local_sub_if_positive(1, l)
-
 /*
  * local_add_negative - add and test if negative
  * @l: pointer of type local_t
index b92dd8c760da5d8a600f6abb33bd62b9bc6c1146..e3301e54d559c9586bf47c31b0486af12d9e2ab6 100644 (file)
@@ -142,7 +142,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 /*
  * __pa()/__va() should be used only during mem init.
  */
-#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
+#ifdef CONFIG_64BIT
 #define __pa(x)                                                                \
 ({                                                                     \
     unsigned long __x = (unsigned long)(x);                            \
index 357251f42518bdb51e7c402ae720140880425007..480b574e2483a6a22581280e8091d23ba9afaa5d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/barrier.h>
+#include <asm/cmpxchg.h>
 #include <asm/cpu-features.h>
 #include <asm/dsp.h>
 #include <asm/war.h>
@@ -194,266 +195,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
-       unsigned long new)
-{
-       __u32 retval;
-
-       if (cpu_has_llsc && R10000_LLSC_WAR) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       .set    mips0                                   \n"
-               "       move    $1, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      $1, %1                                  \n"
-               "       beqzl   $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else if (cpu_has_llsc) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       .set    mips0                                   \n"
-               "       move    $1, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      $1, %1                                  \n"
-               "       beqz    $1, 3f                                  \n"
-               "2:                                                     \n"
-               "       .subsection 2                                   \n"
-               "3:     b       1b                                      \n"
-               "       .previous                                       \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               if (retval == old)
-                       *m = new;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-
-static inline unsigned long __cmpxchg_u32_local(volatile int * m,
-       unsigned long old, unsigned long new)
-{
-       __u32 retval;
-
-       if (cpu_has_llsc && R10000_LLSC_WAR) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       .set    mips0                                   \n"
-               "       move    $1, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      $1, %1                                  \n"
-               "       beqzl   $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else if (cpu_has_llsc) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       .set    mips0                                   \n"
-               "       move    $1, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      $1, %1                                  \n"
-               "       beqz    $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               retval = *m;
-               if (retval == old)
-                       *m = new;
-               local_irq_restore(flags);       /* implies memory barrier  */
-       }
-
-       return retval;
-}
-
-#ifdef CONFIG_64BIT
-static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
-       unsigned long new)
-{
-       __u64 retval;
-
-       if (cpu_has_llsc && R10000_LLSC_WAR) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       move    $1, %z4                                 \n"
-               "       scd     $1, %1                                  \n"
-               "       beqzl   $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else if (cpu_has_llsc) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       move    $1, %z4                                 \n"
-               "       scd     $1, %1                                  \n"
-               "       beqz    $1, 3f                                  \n"
-               "2:                                                     \n"
-               "       .subsection 2                                   \n"
-               "3:     b       1b                                      \n"
-               "       .previous                                       \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               if (retval == old)
-                       *m = new;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-
-static inline unsigned long __cmpxchg_u64_local(volatile int * m,
-       unsigned long old, unsigned long new)
-{
-       __u64 retval;
-
-       if (cpu_has_llsc && R10000_LLSC_WAR) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       move    $1, %z4                                 \n"
-               "       scd     $1, %1                                  \n"
-               "       beqzl   $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else if (cpu_has_llsc) {
-               __asm__ __volatile__(
-               "       .set    push                                    \n"
-               "       .set    noat                                    \n"
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
-               "       bne     %0, %z3, 2f                             \n"
-               "       move    $1, %z4                                 \n"
-               "       scd     $1, %1                                  \n"
-               "       beqz    $1, 1b                                  \n"
-               "2:                                                     \n"
-               "       .set    pop                                     \n"
-               : "=&r" (retval), "=R" (*m)
-               : "R" (*m), "Jr" (old), "Jr" (new)
-               : "memory");
-       } else {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               retval = *m;
-               if (retval == old)
-                       *m = new;
-               local_irq_restore(flags);       /* implies memory barrier  */
-       }
-
-       return retval;
-}
-
-#else
-extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
-       volatile int * m, unsigned long old, unsigned long new);
-#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
-extern unsigned long __cmpxchg_u64_local_unsupported_on_32bit_kernels(
-       volatile int * m, unsigned long old, unsigned long new);
-#define __cmpxchg_u64_local __cmpxchg_u64_local_unsupported_on_32bit_kernels
-#endif
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
-       unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-static inline unsigned long __cmpxchg_local(volatile void * ptr,
-       unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32_local(ptr, old, new);
-       case 8:
-               return __cmpxchg_u64_local(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,old,new) \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), \
-               (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
-
-#define cmpxchg_local(ptr,old,new) \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \
-               (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
-
 extern void set_handler (unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
 
index d7f5ddfbaac77f5f69c32643a6ef1691bb6e7820..c104c15c6625b5d35a06ae22f0a4a96cc20a2131 100644 (file)
@@ -149,6 +149,11 @@ static inline u64 get_tb(void)
 }
 #endif /* !CONFIG_PPC64 */
 
+static inline u64 get_tb_or_rtc(void)
+{
+       return __USE_RTC() ? get_rtc() : get_tb();
+}
+
 static inline void set_tb(unsigned int upper, unsigned int lower)
 {
        mtspr(SPRN_TBWL, 0);
index 0d5cc04ab005db06809770d4b551c4475382569e..dc4f5950dafaab9a074c9845c56b2f4de6f72abc 100644 (file)
@@ -16,8 +16,9 @@
 #define        flat_argvp_envp_on_stack()              0
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags)        get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, p)     get_unaligned(rp)
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
+#define        flat_set_persistent(relval, p)          0
 
 #endif /* __ASM_SH_FLAT_H */
index 3888f59d6881494bcbd7f4d183846d1ba62896c9..17f0ea566611bfffe443462903333b7e49c49901 100644 (file)
@@ -25,6 +25,7 @@
 #define        flat_stack_align(sp)            /* nothing needed */
 #define        flat_argvp_envp_on_stack()      0
 #define        flat_old_ram_flag(flags)        (flags)
+#define        flat_set_persistent(relval, p)  0
 
 /* We store the type of relocation in the top 4 bits of the `relval.' */
 
@@ -46,7 +47,8 @@ flat_get_relocate_addr (unsigned long relval)
    For the v850, RP should always be half-word aligned.  */
 static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
                                                   unsigned long relval,
-                                                  unsigned long flags)
+                                                  unsigned long flags,
+                                                  unsigned long *persistent)
 {
        short *srp = (short *)rp;
 
index b467be6d367f8b3725c1b7449e9d052ea1c3e768..8bb5646878602f3731e345b46a80486f593e1640 100644 (file)
@@ -4,10 +4,6 @@
 #include <asm/pda.h>
 #include <linux/threads.h>
 #include <linux/mm.h>
-#include <linux/quicklist.h>
-
-#define QUICK_PGD 0    /* We preserve special mappings over free */
-#define QUICK_PT 1     /* Other page table pages that are zero on free */
 
 #define pmd_populate_kernel(mm, pmd, pte) \
                set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
@@ -24,23 +20,23 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
 static inline void pmd_free(pmd_t *pmd)
 {
        BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PT, NULL, pmd);
+       free_page((unsigned long)pmd);
 }
 
 static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
 {
-       return (pmd_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pud_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline void pud_free (pud_t *pud)
 {
        BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PT, NULL, pud);
+       free_page((unsigned long)pud);
 }
 
 static inline void pgd_list_add(pgd_t *pgd)
@@ -61,57 +57,41 @@ static inline void pgd_list_del(pgd_t *pgd)
        spin_unlock(&pgd_lock);
 }
 
-static inline void pgd_ctor(void *x)
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        unsigned boundary;
-       pgd_t *pgd = x;
-       struct page *page = virt_to_page(pgd);
-
+       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       if (!pgd)
+               return NULL;
+       pgd_list_add(pgd);
        /*
         * Copy kernel pointers in from init.
+        * Could keep a freelist or slab cache of those because the kernel
+        * part never changes.
         */
        boundary = pgd_index(__PAGE_OFFSET);
+       memset(pgd, 0, boundary * sizeof(pgd_t));
        memcpy(pgd + boundary,
-               init_level4_pgt + boundary,
-               (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
-
-       spin_lock(&pgd_lock);
-       list_add(&page->lru, &pgd_list);
-       spin_unlock(&pgd_lock);
-}
-
-static inline void pgd_dtor(void *x)
-{
-       pgd_t *pgd = x;
-       struct page *page = virt_to_page(pgd);
-
-        spin_lock(&pgd_lock);
-       list_del(&page->lru);
-       spin_unlock(&pgd_lock);
-}
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       pgd_t *pgd = (pgd_t *)quicklist_alloc(QUICK_PGD,
-               GFP_KERNEL|__GFP_REPEAT, pgd_ctor);
+              init_level4_pgt + boundary,
+              (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
        return pgd;
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
        BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PGD, pgd_dtor, pgd);
+       pgd_list_del(pgd);
+       free_page((unsigned long)pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       return (pte_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       void *p = (void *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
-
+       void *p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
        if (!p)
                return NULL;
        return virt_to_page(p);
@@ -123,22 +103,17 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
 static inline void pte_free_kernel(pte_t *pte)
 {
        BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PT, NULL, pte);
+       free_page((unsigned long)pte); 
 }
 
 static inline void pte_free(struct page *pte)
 {
-       quicklist_free_page(QUICK_PT, NULL, pte);
-}
+       __free_page(pte);
+} 
 
-#define __pte_free_tlb(tlb,pte) quicklist_free_page(QUICK_PT, NULL,(pte))
+#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
 
-#define __pmd_free_tlb(tlb,x)   quicklist_free(QUICK_PT, NULL, (x))
-#define __pud_free_tlb(tlb,x)   quicklist_free(QUICK_PT, NULL, (x))
+#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+#define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
 
-static inline void check_pgt_cache(void)
-{
-       quicklist_trim(QUICK_PGD, pgd_dtor, 25, 16);
-       quicklist_trim(QUICK_PT, NULL, 25, 16);
-}
 #endif /* _X86_64_PGALLOC_H */
index c9d8764c89d182920dc1b50b4938f63521292c70..57dd6b3107ead9395f546ccd2ed5e7e1123ad1e8 100644 (file)
@@ -411,6 +411,7 @@ pte_t *lookup_address(unsigned long addr);
 #define HAVE_ARCH_UNMAPPED_AREA
 
 #define pgtable_cache_init()   do { } while (0)
+#define check_pgt_cache()      do { } while (0)
 
 #define PAGE_AGP    PAGE_KERNEL_NOCACHE
 #define HAVE_PAGE_AGP 1
index 19525175b91c2a7793bf463c4e78eba925030d3c..31f579b828f232de4789f515b3aa5c1d633e46a1 100644 (file)
@@ -371,7 +371,7 @@ static inline void sync_core(void)
 #define ARCH_HAS_PREFETCH
 static inline void prefetch(void *x) 
 { 
-       asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x));
+       asm volatile("prefetcht0 (%0)" :: "r" (x));
 } 
 
 #define ARCH_HAS_PREFETCHW 1
index 963051a967d6c22510840473e4913cbe71cf03d0..3ec6e7ff5fbd3514cb332fac4f4ad18cab98a717 100644 (file)
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *********************************************************************/
 
-#ifdef CONFIG_CPU_FREQ
 int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
-#else
-static inline int cpufreq_register_notifier(struct notifier_block *nb,
-                                               unsigned int list)
-{
-       return 0;
-}
-#endif
 int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
 
 #define CPUFREQ_TRANSITION_NOTIFIER    (0)
@@ -268,22 +260,17 @@ struct freq_attr {
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 
+/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
+unsigned int cpufreq_get(unsigned int cpu);
 
-/*
- * query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it
- */
+/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
 #ifdef CONFIG_CPU_FREQ
 unsigned int cpufreq_quick_get(unsigned int cpu);
-unsigned int cpufreq_get(unsigned int cpu);
 #else
 static inline unsigned int cpufreq_quick_get(unsigned int cpu)
 {
        return 0;
 }
-static inline unsigned int cpufreq_get(unsigned int cpu)
-{
-       return 0;
-}
 #endif
 
 
index cab741c2d6033ad937b761852def3fbbf60b763b..f8abfa349ef924344a11b1fd9739e68bd4d72b24 100644 (file)
@@ -86,7 +86,7 @@ extern struct nsproxy init_nsproxy;
        .count          = ATOMIC_INIT(1),                               \
        .action         = { { { .sa_handler = NULL, } }, },             \
        .siglock        = __SPIN_LOCK_UNLOCKED(sighand.siglock),        \
-       .signalfd_list  = LIST_HEAD_INIT(sighand.signalfd_list),        \
+       .signalfd_wqh   = __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh),  \
 }
 
 extern struct group_info init_groups;
index 5bdd656e88cf598a9e41758dc54bf35a644a2e69..a020eb2d4e2a3984fe8807cb833947c42367a232 100644 (file)
@@ -159,7 +159,7 @@ extern void mpol_fix_fork_child_flag(struct task_struct *p);
 
 extern struct mempolicy default_policy;
 extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-               unsigned long addr, gfp_t gfp_flags);
+               unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol);
 extern unsigned slab_node(struct mempolicy *policy);
 
 extern enum zone_type policy_zone;
@@ -256,7 +256,7 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p)
 #define set_cpuset_being_rebound(x) do {} while (0)
 
 static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
-               unsigned long addr, gfp_t gfp_flags)
+               unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol)
 {
        return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
 }
index f4e324ed2e4478e5282ba3b4c0f33339fc581dd8..313c6b6e774f887438c3926c539186ed03e6939e 100644 (file)
@@ -113,7 +113,7 @@ extern unsigned long avenrun[];             /* Load averages */
 
 #define FSHIFT         11              /* nr of bits of precision */
 #define FIXED_1                (1<<FSHIFT)     /* 1.0 as fixed-point */
-#define LOAD_FREQ      (5*HZ)          /* 5 sec intervals */
+#define LOAD_FREQ      (5*HZ+1)        /* 5 sec intervals */
 #define EXP_1          1884            /* 1/exp(5sec/1min) as fixed-point */
 #define EXP_5          2014            /* 1/exp(5sec/5min) */
 #define EXP_15         2037            /* 1/exp(5sec/15min) */
@@ -438,7 +438,7 @@ struct sighand_struct {
        atomic_t                count;
        struct k_sigaction      action[_NSIG];
        spinlock_t              siglock;
-       struct list_head        signalfd_list;
+       wait_queue_head_t       signalfd_wqh;
 };
 
 struct pacct_struct {
@@ -593,7 +593,7 @@ struct user_struct {
 #endif
 
        /* Hash table maintenance information */
-       struct list_head uidhash_list;
+       struct hlist_node uidhash_node;
        uid_t uid;
 };
 
@@ -1406,6 +1406,7 @@ extern unsigned int sysctl_sched_wakeup_granularity;
 extern unsigned int sysctl_sched_batch_wakeup_granularity;
 extern unsigned int sysctl_sched_stat_granularity;
 extern unsigned int sysctl_sched_runtime_limit;
+extern unsigned int sysctl_sched_compat_yield;
 extern unsigned int sysctl_sched_child_runs_first;
 extern unsigned int sysctl_sched_features;
 
@@ -1472,6 +1473,7 @@ static inline struct user_struct *get_uid(struct user_struct *u)
 }
 extern void free_uid(struct user_struct *);
 extern void switch_uid(struct user_struct *);
+extern void release_uids(struct user_namespace *ns);
 
 #include <asm/current.h>
 
index 5104294956906c038e4359ab4e37c35632e2e478..4c9ff0910ae01d39f691a23c9acf5d1db48b06d2 100644 (file)
@@ -45,49 +45,17 @@ struct signalfd_siginfo {
 #ifdef CONFIG_SIGNALFD
 
 /*
- * Deliver the signal to listening signalfd. This must be called
- * with the sighand lock held. Same are the following that end up
- * calling signalfd_deliver().
- */
-void signalfd_deliver(struct task_struct *tsk, int sig);
-
-/*
- * No need to fall inside signalfd_deliver() if no signal listeners
- * are available.
+ * Deliver the signal to listening signalfd.
  */
 static inline void signalfd_notify(struct task_struct *tsk, int sig)
 {
-       if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
-               signalfd_deliver(tsk, sig);
-}
-
-/*
- * The signal -1 is used to notify the signalfd that the sighand
- * is on its way to be detached.
- */
-static inline void signalfd_detach_locked(struct task_struct *tsk)
-{
-       if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
-               signalfd_deliver(tsk, -1);
-}
-
-static inline void signalfd_detach(struct task_struct *tsk)
-{
-       struct sighand_struct *sighand = tsk->sighand;
-
-       if (unlikely(!list_empty(&sighand->signalfd_list))) {
-               spin_lock_irq(&sighand->siglock);
-               signalfd_deliver(tsk, -1);
-               spin_unlock_irq(&sighand->siglock);
-       }
+       if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh)))
+               wake_up(&tsk->sighand->signalfd_wqh);
 }
 
 #else /* CONFIG_SIGNALFD */
 
-#define signalfd_deliver(t, s) do { } while (0)
-#define signalfd_notify(t, s) do { } while (0)
-#define signalfd_detach_locked(t) do { } while (0)
-#define signalfd_detach(t) do { } while (0)
+static inline void signalfd_notify(struct task_struct *tsk, int sig) { }
 
 #endif /* CONFIG_SIGNALFD */
 
index 1101b0ce878f67973d5037f7b651cabf1fb8d28e..b5f41d4c2eec71a3d3c786128f0f980f0b41317d 100644 (file)
@@ -11,7 +11,7 @@
 
 struct user_namespace {
        struct kref             kref;
-       struct list_head        uidhash_table[UIDHASH_SZ];
+       struct hlist_head       uidhash_table[UIDHASH_SZ];
        struct user_struct      *root_user;
 };
 
index 4ef4d22e5e43bb1439183aee44782fb5d46a41a3..b4af6bcb7b7aa26a67b3358598826f166e16e553 100644 (file)
@@ -127,7 +127,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
                        loff_t pos, loff_t count);
 int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
                           loff_t pos, loff_t count);
-void set_page_dirty_balance(struct page *page);
+void set_page_dirty_balance(struct page *page, int page_mkwrite);
 void writeback_set_ratelimit(void);
 
 /* pdflush.c */
index a4047d3cf5ddda9a7511c3b68b6542a3c3e292d3..e5bb084d8754fcf5a57abe18095755e321cedcd6 100644 (file)
@@ -188,7 +188,7 @@ extern void rose_kick(struct sock *);
 extern void rose_enquiry_response(struct sock *);
 
 /* rose_route.c */
-extern struct rose_neigh rose_loopback_neigh;
+extern struct rose_neigh *rose_loopback_neigh;
 extern const struct file_operations rose_neigh_fops;
 extern const struct file_operations rose_nodes_fops;
 extern const struct file_operations rose_routes_fops;
index 991c85bb9e3648e83cf44599d36845aa92bd9fc4..e8e3a64eb32254d50a86d87e7028042aae8578d4 100644 (file)
@@ -114,7 +114,6 @@ sctp_state_fn_t sctp_sf_do_4_C;
 sctp_state_fn_t sctp_sf_eat_data_6_2;
 sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
 sctp_state_fn_t sctp_sf_eat_sack_6_2;
-sctp_state_fn_t sctp_sf_tabort_8_4_8;
 sctp_state_fn_t sctp_sf_operr_notify;
 sctp_state_fn_t sctp_sf_t1_init_timer_expire;
 sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
@@ -247,6 +246,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
                                              int, __be16);
 struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
                                             union sctp_addr *addr);
+int sctp_verify_asconf(const struct sctp_association *asoc,
+                      struct sctp_paramhdr *param_hdr, void *chunk_end,
+                      struct sctp_paramhdr **errp);
 struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
                                       struct sctp_chunk *asconf);
 int sctp_process_asconf_ack(struct sctp_association *asoc,
index c2fe2dcc9afc9b5d1e2b618b82a7a26aa7c19e0c..baff49dfcdbd488ef21c922be48eacf3be17eea2 100644 (file)
@@ -421,6 +421,7 @@ struct sctp_signed_cookie {
  * internally.
  */
 union sctp_addr_param {
+       struct sctp_paramhdr p;
        struct sctp_ipv4addr_param v4;
        struct sctp_ipv6addr_param v6;
 };
@@ -1156,7 +1157,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
 int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
                       __u8 use_as_src, gfp_t gfp);
 int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
-                       void (*rcu_call)(struct rcu_head *,
+                       void fastcall (*rcu_call)(struct rcu_head *,
                                          void (*func)(struct rcu_head *)));
 int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
                         struct sctp_sock *);
index 185c7ecce4cc159e845c3e9afa62a7facc7b8bea..54053de0bdd7c12f2f3a0269f2ddf5b77c33ec47 100644 (file)
@@ -1059,14 +1059,12 @@ struct tcp_md5sig_key {
 };
 
 struct tcp4_md5sig_key {
-       u8                      *key;
-       u16                     keylen;
+       struct tcp_md5sig_key   base;
        __be32                  addr;
 };
 
 struct tcp6_md5sig_key {
-       u8                      *key;
-       u16                     keylen;
+       struct tcp_md5sig_key   base;
 #if 0
        u32                     scope_id;       /* XXX */
 #endif
index 96b54595f1dc16e1809852ca0462184b948b54b4..d54d0cadcc064c284c10cce88beaf9c55ccf0cdd 100644 (file)
@@ -488,6 +488,7 @@ config SIGNALFD
 config TIMERFD
        bool "Enable timerfd() system call" if EMBEDDED
        select ANON_INODES
+       depends on BROKEN
        default y
        help
          Enable the timerfd() system call that allows to receive timer
index a6b4c0c08e13ea4bc1db5ade1cf8eb73d18c7d72..fd4fc12d262464b0b763e2e0fb5dd1781f2a3b70 100644 (file)
@@ -57,8 +57,10 @@ static void __init handle_initrd(void)
 
        pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
        if (pid > 0)
-               while (pid != sys_wait4(-1, NULL, 0, NULL))
+               while (pid != sys_wait4(-1, NULL, 0, NULL)) {
+                       try_to_freeze();
                        yield();
+               }
 
        /* move initrd to rootfs' /old */
        sys_fchdir(old_fd);
index 06b24b3aa370c69577012023b12573d4c7624d19..993369ee94d1ebb8d4c7675a821e90abf8a1737e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
-#include <linux/signalfd.h>
 #include <linux/mount.h>
 #include <linux/proc_fs.h>
 #include <linux/kthread.h>
@@ -86,14 +85,6 @@ static void __exit_signal(struct task_struct *tsk)
        sighand = rcu_dereference(tsk->sighand);
        spin_lock(&sighand->siglock);
 
-       /*
-        * Notify that this sighand has been detached. This must
-        * be called with the tsk->sighand lock held. Also, this
-        * access tsk->sighand internally, so it must be called
-        * before tsk->sighand is reset.
-        */
-       signalfd_detach_locked(tsk);
-
        posix_cpu_timers_exit(tsk);
        if (atomic_dec_and_test(&sig->count))
                posix_cpu_timers_exit_group(tsk);
index 7332e236d3676153dc9f40c1a78848e6e2810632..33f12f48684a0053a82d72506c1d7ec1e7ca6a15 100644 (file)
@@ -1438,7 +1438,7 @@ static void sighand_ctor(void *data, struct kmem_cache *cachep,
        struct sighand_struct *sighand = data;
 
        spin_lock_init(&sighand->siglock);
-       INIT_LIST_HEAD(&sighand->signalfd_list);
+       init_waitqueue_head(&sighand->signalfd_wqh);
 }
 
 void __init proc_caches_init(void)
index e8935b195e8809fa1a23484d5007feb27887fd63..fcc94e7b40864afcb72170f19d832f8117e517fc 100644 (file)
@@ -1943,9 +1943,10 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
 void exit_robust_list(struct task_struct *curr)
 {
        struct robust_list_head __user *head = curr->robust_list;
-       struct robust_list __user *entry, *pending;
-       unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
+       struct robust_list __user *entry, *next_entry, *pending;
+       unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip;
        unsigned long futex_offset;
+       int rc;
 
        /*
         * Fetch the list head (which was registered earlier, via
@@ -1965,11 +1966,13 @@ void exit_robust_list(struct task_struct *curr)
        if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
                return;
 
-       if (pending)
-               handle_futex_death((void __user *)pending + futex_offset,
-                                  curr, pip);
-
+       next_entry = NULL;      /* avoid warning with gcc */
        while (entry != &head->list) {
+               /*
+                * Fetch the next entry in the list before calling
+                * handle_futex_death:
+                */
+               rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi);
                /*
                 * A pending lock might already be on the list, so
                 * don't process it twice:
@@ -1978,11 +1981,10 @@ void exit_robust_list(struct task_struct *curr)
                        if (handle_futex_death((void __user *)entry + futex_offset,
                                                curr, pi))
                                return;
-               /*
-                * Fetch the next entry in the list:
-                */
-               if (fetch_robust_entry(&entry, &entry->next, &pi))
+               if (rc)
                        return;
+               entry = next_entry;
+               pi = next_pi;
                /*
                 * Avoid excessively long or circular lists:
                 */
@@ -1991,6 +1993,10 @@ void exit_robust_list(struct task_struct *curr)
 
                cond_resched();
        }
+
+       if (pending)
+               handle_futex_death((void __user *)pending + futex_offset,
+                                  curr, pip);
 }
 
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
index 7e52eb051f227f557a171e974312d35b9192944a..2c2e2954b713b2681a5bf120c0097cb2c2affc8c 100644 (file)
@@ -38,10 +38,11 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
 void compat_exit_robust_list(struct task_struct *curr)
 {
        struct compat_robust_list_head __user *head = curr->compat_robust_list;
-       struct robust_list __user *entry, *pending;
-       unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
-       compat_uptr_t uentry, upending;
+       struct robust_list __user *entry, *next_entry, *pending;
+       unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip;
+       compat_uptr_t uentry, next_uentry, upending;
        compat_long_t futex_offset;
+       int rc;
 
        /*
         * Fetch the list head (which was registered earlier, via
@@ -61,10 +62,15 @@ void compat_exit_robust_list(struct task_struct *curr)
        if (fetch_robust_entry(&upending, &pending,
                               &head->list_op_pending, &pip))
                return;
-       if (pending)
-               handle_futex_death((void __user *)pending + futex_offset, curr, pip);
 
+       next_entry = NULL;      /* avoid warning with gcc */
        while (entry != (struct robust_list __user *) &head->list) {
+               /*
+                * Fetch the next entry in the list before calling
+                * handle_futex_death:
+                */
+               rc = fetch_robust_entry(&next_uentry, &next_entry,
+                       (compat_uptr_t __user *)&entry->next, &next_pi);
                /*
                 * A pending lock might already be on the list, so
                 * dont process it twice:
@@ -74,12 +80,11 @@ void compat_exit_robust_list(struct task_struct *curr)
                                                curr, pi))
                                return;
 
-               /*
-                * Fetch the next entry in the list:
-                */
-               if (fetch_robust_entry(&uentry, &entry,
-                                      (compat_uptr_t __user *)&entry->next, &pi))
+               if (rc)
                        return;
+               uentry = next_uentry;
+               entry = next_entry;
+               pi = next_pi;
                /*
                 * Avoid excessively long or circular lists:
                 */
@@ -88,6 +93,9 @@ void compat_exit_robust_list(struct task_struct *curr)
 
                cond_resched();
        }
+       if (pending)
+               handle_futex_death((void __user *)pending + futex_offset,
+                                  curr, pip);
 }
 
 asmlinkage long
index c8580a1e68739510088355cc5c37f4c47b571a77..14b0e10dc95c6a8a1b305f212e2300574120f16f 100644 (file)
@@ -110,7 +110,7 @@ config SUSPEND
 
 config HIBERNATION_UP_POSSIBLE
        bool
-       depends on X86 || PPC64_SWSUSP || FRV || PPC32
+       depends on X86 || PPC64_SWSUSP || PPC32
        depends on !SMP
        default y
 
index deeb1f8e0c309b4214d9854f2d67699d54f17caa..6107a0cd6325f9afe219007e1e1e446fda899b78 100644 (file)
@@ -1682,6 +1682,11 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
 
        p->prio = effective_prio(p);
 
+       if (rt_prio(p->prio))
+               p->sched_class = &rt_sched_class;
+       else
+               p->sched_class = &fair_sched_class;
+
        if (!p->sched_class->task_new || !sysctl_sched_child_runs_first ||
                        (clone_flags & CLONE_VM) || task_cpu(p) != this_cpu ||
                        !current->se.on_rq) {
@@ -4550,10 +4555,7 @@ asmlinkage long sys_sched_yield(void)
        struct rq *rq = this_rq_lock();
 
        schedstat_inc(rq, yld_cnt);
-       if (unlikely(rq->nr_running == 1))
-               schedstat_inc(rq, yld_act_empty);
-       else
-               current->sched_class->yield_task(rq, current);
+       current->sched_class->yield_task(rq, current);
 
        /*
         * Since we are going to call schedule() anyway, there's
index 892616bf2c77ab212d28823c6fe1bc76b1cb7825..67c67a87146ebaa64514c4bdf8b0ae5de0d4cf47 100644 (file)
@@ -42,6 +42,14 @@ unsigned int sysctl_sched_latency __read_mostly = 20000000ULL;
  */
 unsigned int sysctl_sched_min_granularity __read_mostly = 2000000ULL;
 
+/*
+ * sys_sched_yield() compat mode
+ *
+ * This option switches the agressive yield implementation of the
+ * old scheduler back on.
+ */
+unsigned int __read_mostly sysctl_sched_compat_yield;
+
 /*
  * SCHED_BATCH wake-up granularity.
  * (default: 25 msec, units: nanoseconds)
@@ -631,6 +639,16 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 
                se->block_start = 0;
                se->sum_sleep_runtime += delta;
+
+               /*
+                * Blocking time is in units of nanosecs, so shift by 20 to
+                * get a milliseconds-range estimation of the amount of
+                * time that the task spent sleeping:
+                */
+               if (unlikely(prof_on == SLEEP_PROFILING)) {
+                       profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk),
+                                    delta >> 20);
+               }
        }
 #endif
 }
@@ -897,19 +915,62 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep)
 }
 
 /*
- * sched_yield() support is very simple - we dequeue and enqueue
+ * sched_yield() support is very simple - we dequeue and enqueue.
+ *
+ * If compat_yield is turned on then we requeue to the end of the tree.
  */
 static void yield_task_fair(struct rq *rq, struct task_struct *p)
 {
        struct cfs_rq *cfs_rq = task_cfs_rq(p);
+       struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+       struct sched_entity *rightmost, *se = &p->se;
+       struct rb_node *parent;
 
-       __update_rq_clock(rq);
        /*
-        * Dequeue and enqueue the task to update its
-        * position within the tree:
+        * Are we the only task in the tree?
+        */
+       if (unlikely(cfs_rq->nr_running == 1))
+               return;
+
+       if (likely(!sysctl_sched_compat_yield)) {
+               __update_rq_clock(rq);
+               /*
+                * Dequeue and enqueue the task to update its
+                * position within the tree:
+                */
+               dequeue_entity(cfs_rq, &p->se, 0);
+               enqueue_entity(cfs_rq, &p->se, 0);
+
+               return;
+       }
+       /*
+        * Find the rightmost entry in the rbtree:
+        */
+       do {
+               parent = *link;
+               link = &parent->rb_right;
+       } while (*link);
+
+       rightmost = rb_entry(parent, struct sched_entity, run_node);
+       /*
+        * Already in the rightmost position?
         */
-       dequeue_entity(cfs_rq, &p->se, 0);
-       enqueue_entity(cfs_rq, &p->se, 0);
+       if (unlikely(rightmost == se))
+               return;
+
+       /*
+        * Minimally necessary key value to be last in the tree:
+        */
+       se->fair_key = rightmost->fair_key + 1;
+
+       if (cfs_rq->rb_leftmost == &se->run_node)
+               cfs_rq->rb_leftmost = rb_next(&se->run_node);
+       /*
+        * Relink the task to the rightmost position:
+        */
+       rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+       rb_link_node(&se->run_node, parent, link);
+       rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
 }
 
 /*
index 3169bed0b4d0e44166b37c48ed663d516a9ccba5..7929523810928d9aa405aa74cb2e390a6083491f 100644 (file)
@@ -378,8 +378,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
         */
-       if (likely(tsk == current))
-               signr = __dequeue_signal(&tsk->pending, mask, info);
+       signr = __dequeue_signal(&tsk->pending, mask, info);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
                                         mask, info);
@@ -407,8 +406,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                        }
                }
        }
-       if (likely(tsk == current))
-               recalc_sigpending();
+       recalc_sigpending();
        if (signr && unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
@@ -425,7 +423,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
                        tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
        }
-       if (signr && likely(tsk == current) &&
+       if (signr &&
             ((info->si_code & __SI_MASK) == __SI_TIMER) &&
             info->si_sys_private){
                /*
@@ -533,18 +531,18 @@ static int check_kill_permission(int sig, struct siginfo *info,
        if (!valid_signal(sig))
                return error;
 
-       error = audit_signal_info(sig, t); /* Let audit system see the signal */
-       if (error)
-               return error;
-
-       error = -EPERM;
-       if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
-           && ((sig != SIGCONT) ||
-               (process_session(current) != process_session(t)))
-           && (current->euid ^ t->suid) && (current->euid ^ t->uid)
-           && (current->uid ^ t->suid) && (current->uid ^ t->uid)
-           && !capable(CAP_KILL))
+       if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) {
+               error = audit_signal_info(sig, t); /* Let audit system see the signal */
+               if (error)
+                       return error;
+               error = -EPERM;
+               if (((sig != SIGCONT) ||
+                       (process_session(current) != process_session(t)))
+                   && (current->euid ^ t->suid) && (current->euid ^ t->uid)
+                   && (current->uid ^ t->suid) && (current->uid ^ t->uid)
+                   && !capable(CAP_KILL))
                return error;
+       }
 
        return security_task_kill(t, info, sig, 0);
 }
index 1b33b05d346bb8958ac235a2aa423b657cdf28ad..8ae2e636eb1ba690f9fd9cf0f363d5f677db80ac 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/getcpu.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/seccomp.h>
+#include <linux/cpu.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -878,6 +879,7 @@ void kernel_power_off(void)
        kernel_shutdown_prepare(SYSTEM_POWER_OFF);
        if (pm_power_off_prepare)
                pm_power_off_prepare();
+       disable_nonboot_cpus();
        sysdev_shutdown();
        printk(KERN_EMERG "Power down.\n");
        machine_power_off();
index 6ace893c17c94dc737bda11fb63ee2811d34de79..53a456ebf6d50dd3e4705ccc84e5b0a1c44f6c90 100644 (file)
@@ -303,6 +303,14 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "sched_compat_yield",
+               .data           = &sysctl_sched_compat_yield,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
 #ifdef CONFIG_PROVE_LOCKING
        {
                .ctl_name       = CTL_UNNUMBERED,
index aab881c86a1ab94eb03b3468fbfe3a2b65ebd7e9..0962e0577660722b11d69171a8d4ce5a57017ad6 100644 (file)
@@ -382,23 +382,8 @@ static int tick_broadcast_set_event(ktime_t expires, int force)
 
 int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
-       int cpu = smp_processor_id();
-
-       /*
-        * If the CPU is marked for broadcast, enforce oneshot
-        * broadcast mode. The jinxed VAIO does not resume otherwise.
-        * No idea why it ends up in a lower C State during resume
-        * without notifying the clock events layer.
-        */
-       if (cpu_isset(cpu, tick_broadcast_mask))
-               cpu_set(cpu, tick_broadcast_oneshot_mask);
-
        clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-
-       if(!cpus_empty(tick_broadcast_oneshot_mask))
-               tick_broadcast_set_event(ktime_get(), 1);
-
-       return cpu_isset(cpu, tick_broadcast_oneshot_mask);
+       return 0;
 }
 
 /*
index 3c38fb5eae1b4a6d5ccaab8b8b079b130af675fe..c36bb7ed0301e198753dc29eef982ddf02ed7faf 100644 (file)
@@ -327,8 +327,9 @@ static int tstats_show(struct seq_file *m, void *v)
                ms = 1;
 
        if (events && period.tv_sec)
-               seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events,
-                          events / period.tv_sec, events * 1000 / ms);
+               seq_printf(m, "%ld total events, %ld.%03ld events/sec\n",
+                          events, events * 1000 / ms,
+                          (events * 1000000 / ms) % 1000);
        else
                seq_printf(m, "%ld total events\n", events);
 
index e7d11cef6998fdb378506d72232c4041738dce2f..9ca2848fc35676fa8ebac52f20c33f7f056d09ff 100644 (file)
@@ -55,25 +55,22 @@ struct user_struct root_user = {
 /*
  * These routines must be called with the uidhash spinlock held!
  */
-static inline void uid_hash_insert(struct user_struct *up, struct list_head *hashent)
+static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent)
 {
-       list_add(&up->uidhash_list, hashent);
+       hlist_add_head(&up->uidhash_node, hashent);
 }
 
 static inline void uid_hash_remove(struct user_struct *up)
 {
-       list_del(&up->uidhash_list);
+       hlist_del_init(&up->uidhash_node);
 }
 
-static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent)
+static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
 {
-       struct list_head *up;
-
-       list_for_each(up, hashent) {
-               struct user_struct *user;
-
-               user = list_entry(up, struct user_struct, uidhash_list);
+       struct user_struct *user;
+       struct hlist_node *h;
 
+       hlist_for_each_entry(user, h, hashent, uidhash_node) {
                if(user->uid == uid) {
                        atomic_inc(&user->__count);
                        return user;
@@ -122,7 +119,7 @@ void free_uid(struct user_struct *up)
 
 struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 {
-       struct list_head *hashent = uidhashentry(ns, uid);
+       struct hlist_head *hashent = uidhashentry(ns, uid);
        struct user_struct *up;
 
        spin_lock_irq(&uidhash_lock);
@@ -202,6 +199,30 @@ void switch_uid(struct user_struct *new_user)
        suid_keys(current);
 }
 
+void release_uids(struct user_namespace *ns)
+{
+       int i;
+       unsigned long flags;
+       struct hlist_head *head;
+       struct hlist_node *nd;
+
+       spin_lock_irqsave(&uidhash_lock, flags);
+       /*
+        * collapse the chains so that the user_struct-s will
+        * be still alive, but not in hashes. subsequent free_uid()
+        * will free them.
+        */
+       for (i = 0; i < UIDHASH_SZ; i++) {
+               head = ns->uidhash_table + i;
+               while (!hlist_empty(head)) {
+                       nd = head->first;
+                       hlist_del_init(nd);
+               }
+       }
+       spin_unlock_irqrestore(&uidhash_lock, flags);
+
+       free_uid(ns->root_user);
+}
 
 static int __init uid_cache_init(void)
 {
@@ -211,7 +232,7 @@ static int __init uid_cache_init(void)
                        0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
 
        for(n = 0; n < UIDHASH_SZ; ++n)
-               INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
+               INIT_HLIST_HEAD(init_user_ns.uidhash_table + n);
 
        /* Insert the root user immediately (init already runs as root) */
        spin_lock_irq(&uidhash_lock);
index 85af9422ea6e0163afd849f59237752825a62406..7af90fc4f0fd3d870c1f5dbb3b0771fc16bbc5a4 100644 (file)
@@ -39,7 +39,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
        kref_init(&ns->kref);
 
        for (n = 0; n < UIDHASH_SZ; ++n)
-               INIT_LIST_HEAD(ns->uidhash_table + n);
+               INIT_HLIST_HEAD(ns->uidhash_table + n);
 
        /* Insert new root user.  */
        ns->root_user = alloc_uid(ns, 0);
@@ -81,7 +81,7 @@ void free_user_ns(struct kref *kref)
        struct user_namespace *ns;
 
        ns = container_of(kref, struct user_namespace, kref);
-       free_uid(ns->root_user);
+       release_uids(ns);
        kfree(ns);
 }
 
index 9d8180a0f0d815dbe051dbb6a710385d22f0b342..816d7b24fa031af51b08d9108366d21626e3d38e 100644 (file)
@@ -28,7 +28,9 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
        if (!ns)
                return ERR_PTR(-ENOMEM);
 
+       down_read(&uts_sem);
        memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
+       up_read(&uts_sem);
        kref_init(&ns->kref);
        return ns;
 }
index 50a94eee4d92565e2f247eac3c92ca80c7d45581..cdc9b099e620f9fa00398c746e2b4cdd29bce554 100644 (file)
@@ -284,7 +284,7 @@ config LOCKDEP
        select KALLSYMS_ALL
 
 config LOCK_STAT
-       bool "Lock usage statisitics"
+       bool "Lock usage statistics"
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
        select LOCKDEP
        select DEBUG_SPINLOCK
@@ -294,6 +294,8 @@ config LOCK_STAT
        help
         This feature enables tracking lock contention points
 
+        For more details, see Documentation/lockstat.txt
+
 config DEBUG_LOCKDEP
        bool "Lock dependency engine debugging"
        depends on DEBUG_KERNEL && LOCKDEP
index 6b0ba8cf4e5f9ab3fbc8fef0b4ead9c88af7cf4a..4f3f3e2565017e4e37c88d7c6f11f4326695cdcc 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for some libs needed in the kernel.
 #
 
-lib-y := ctype.o string.o vsprintf.o kasprintf.o cmdline.o \
+lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o \
         idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
         sha1.o irq_regs.o reciprocal_div.o argv_split.o
@@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o
 lib-y  += kobject.o kref.o kobject_uevent.o klist.o
 
 obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
-        bust_spinlocks.o hexdump.o
+        bust_spinlocks.o hexdump.o kasprintf.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
index e24d348083c34da69472bc22a9b7025d562a3ffe..a7609cbcb00d8ce3fb81f366d7c835af970452e7 100644 (file)
@@ -137,6 +137,7 @@ config SPLIT_PTLOCK_CPUS
        int
        default "4096" if ARM && !CPU_CACHE_VIPT
        default "4096" if PARISC && !PA20
+       default "4096" if XEN
        default "4"
 
 #
index 90b657b50f81413a8452313f8a7b225888971f7b..15c8413ee929200006e4eb5e8a96bf5b04f0f213 100644 (file)
@@ -1388,6 +1388,7 @@ retry_find:
        size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        if (unlikely(vmf->pgoff >= size)) {
                unlock_page(page);
+               page_cache_release(page);
                goto outside_data_content;
        }
 
index c395b1abf08275dc1d22a570f259f495cdb2cbc7..95bcb5641c722b6f4d7eb49801320e0a266f7c83 100644 (file)
@@ -160,7 +160,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
        if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
                goto out;
 
-       if (!vma->vm_flags & VM_CAN_NONLINEAR)
+       if (!(vma->vm_flags & VM_CAN_NONLINEAR))
                goto out;
 
        if (end <= start || start < vma->vm_start || end > vma->vm_end)
index de4cf458d6e1979432aad46613d0816146347fc1..eab8c428cc932028e202b4a8b8d547642fd10fa6 100644 (file)
@@ -42,7 +42,7 @@ static void clear_huge_page(struct page *page, unsigned long addr)
        might_sleep();
        for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) {
                cond_resched();
-               clear_user_highpage(page + i, addr);
+               clear_user_highpage(page + i, addr + i * PAGE_SIZE);
        }
 }
 
@@ -71,8 +71,9 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
 {
        int nid;
        struct page *page = NULL;
+       struct mempolicy *mpol;
        struct zonelist *zonelist = huge_zonelist(vma, address,
-                                               htlb_alloc_mask);
+                                       htlb_alloc_mask, &mpol);
        struct zone **z;
 
        for (z = zonelist->zones; *z; z++) {
@@ -87,6 +88,7 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
                        break;
                }
        }
+       mpol_free(mpol);        /* unref if mpol !NULL */
        return page;
 }
 
index ca8cac11bd2cf4930533f306a0209bbbea0e9c31..f82b359b27452dd1f7e682197479fa1391d19a46 100644 (file)
@@ -1639,6 +1639,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *old_page, *new_page;
        pte_t entry;
        int reuse = 0, ret = 0;
+       int page_mkwrite = 0;
        struct page *dirty_page = NULL;
 
        old_page = vm_normal_page(vma, address, orig_pte);
@@ -1687,6 +1688,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        page_cache_release(old_page);
                        if (!pte_same(*page_table, orig_pte))
                                goto unlock;
+
+                       page_mkwrite = 1;
                }
                dirty_page = old_page;
                get_page(dirty_page);
@@ -1774,7 +1777,7 @@ unlock:
                 * do_no_page is protected similarly.
                 */
                wait_on_page_locked(dirty_page);
-               set_page_dirty_balance(dirty_page);
+               set_page_dirty_balance(dirty_page, page_mkwrite);
                put_page(dirty_page);
        }
        return ret;
@@ -2307,13 +2310,14 @@ oom:
  * do not need to flush old virtual caches or the TLB.
  *
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
- * but allow concurrent faults), and pte mapped but not yet locked.
+ * but allow concurrent faults), and pte neither mapped nor locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
 static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
-               unsigned long address, pte_t *page_table, pmd_t *pmd,
+               unsigned long address, pmd_t *pmd,
                pgoff_t pgoff, unsigned int flags, pte_t orig_pte)
 {
+       pte_t *page_table;
        spinlock_t *ptl;
        struct page *page;
        pte_t entry;
@@ -2321,13 +2325,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *dirty_page = NULL;
        struct vm_fault vmf;
        int ret;
+       int page_mkwrite = 0;
 
        vmf.virtual_address = (void __user *)(address & PAGE_MASK);
        vmf.pgoff = pgoff;
        vmf.flags = flags;
        vmf.page = NULL;
 
-       pte_unmap(page_table);
        BUG_ON(vma->vm_flags & VM_PFNMAP);
 
        if (likely(vma->vm_ops->fault)) {
@@ -2398,6 +2402,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                                        anon = 1; /* no anon but release vmf.page */
                                        goto out;
                                }
+                               page_mkwrite = 1;
                        }
                }
 
@@ -2453,7 +2458,7 @@ out_unlocked:
        if (anon)
                page_cache_release(vmf.page);
        else if (dirty_page) {
-               set_page_dirty_balance(dirty_page);
+               set_page_dirty_balance(dirty_page, page_mkwrite);
                put_page(dirty_page);
        }
 
@@ -2468,8 +2473,8 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff;
        unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0);
 
-       return __do_fault(mm, vma, address, page_table, pmd, pgoff,
-                                                       flags, orig_pte);
+       pte_unmap(page_table);
+       return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
 
@@ -2552,9 +2557,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        }
 
        pgoff = pte_to_pgoff(orig_pte);
-
-       return __do_fault(mm, vma, address, page_table, pmd, pgoff,
-                                                       flags, orig_pte);
+       return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
 /*
index bb54b88c3d5aaab2752569f046129bea8082f4ec..3d6ac9505d0716e83c1eeee3a58ede5c5baa0a1b 100644 (file)
@@ -1077,21 +1077,37 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
 
 #endif
 
-/* Return effective policy for a VMA */
+/*
+ * get_vma_policy(@task, @vma, @addr)
+ * @task - task for fallback if vma policy == default
+ * @vma   - virtual memory area whose policy is sought
+ * @addr  - address in @vma for shared policy lookup
+ *
+ * Returns effective policy for a VMA at specified address.
+ * Falls back to @task or system default policy, as necessary.
+ * Returned policy has extra reference count if shared, vma,
+ * or some other task's policy [show_numa_maps() can pass
+ * @task != current].  It is the caller's responsibility to
+ * free the reference in these cases.
+ */
 static struct mempolicy * get_vma_policy(struct task_struct *task,
                struct vm_area_struct *vma, unsigned long addr)
 {
        struct mempolicy *pol = task->mempolicy;
+       int shared_pol = 0;
 
        if (vma) {
-               if (vma->vm_ops && vma->vm_ops->get_policy)
+               if (vma->vm_ops && vma->vm_ops->get_policy) {
                        pol = vma->vm_ops->get_policy(vma, addr);
-               else if (vma->vm_policy &&
+                       shared_pol = 1; /* if pol non-NULL, add ref below */
+               } else if (vma->vm_policy &&
                                vma->vm_policy->policy != MPOL_DEFAULT)
                        pol = vma->vm_policy;
        }
        if (!pol)
                pol = &default_policy;
+       else if (!shared_pol && pol != current->mempolicy)
+               mpol_get(pol);  /* vma or other task's policy */
        return pol;
 }
 
@@ -1207,19 +1223,45 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
 }
 
 #ifdef CONFIG_HUGETLBFS
-/* Return a zonelist suitable for a huge page allocation. */
+/*
+ * huge_zonelist(@vma, @addr, @gfp_flags, @mpol)
+ * @vma = virtual memory area whose policy is sought
+ * @addr = address in @vma for shared policy lookup and interleave policy
+ * @gfp_flags = for requested zone
+ * @mpol = pointer to mempolicy pointer for reference counted 'BIND policy
+ *
+ * Returns a zonelist suitable for a huge page allocation.
+ * If the effective policy is 'BIND, returns pointer to policy's zonelist.
+ * If it is also a policy for which get_vma_policy() returns an extra
+ * reference, we must hold that reference until after allocation.
+ * In that case, return policy via @mpol so hugetlb allocation can drop
+ * the reference.  For non-'BIND referenced policies, we can/do drop the
+ * reference here, so the caller doesn't need to know about the special case
+ * for default and current task policy.
+ */
 struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
-                                                       gfp_t gfp_flags)
+                               gfp_t gfp_flags, struct mempolicy **mpol)
 {
        struct mempolicy *pol = get_vma_policy(current, vma, addr);
+       struct zonelist *zl;
 
+       *mpol = NULL;           /* probably no unref needed */
        if (pol->policy == MPOL_INTERLEAVE) {
                unsigned nid;
 
                nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
+               __mpol_free(pol);               /* finished with pol */
                return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
        }
-       return zonelist_policy(GFP_HIGHUSER, pol);
+
+       zl = zonelist_policy(GFP_HIGHUSER, pol);
+       if (unlikely(pol != &default_policy && pol != current->mempolicy)) {
+               if (pol->policy != MPOL_BIND)
+                       __mpol_free(pol);       /* finished with pol */
+               else
+                       *mpol = pol;    /* unref needed after allocation */
+       }
+       return zl;
 }
 #endif
 
@@ -1264,6 +1306,7 @@ struct page *
 alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr)
 {
        struct mempolicy *pol = get_vma_policy(current, vma, addr);
+       struct zonelist *zl;
 
        cpuset_update_task_memory_state();
 
@@ -1273,7 +1316,19 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr)
                nid = interleave_nid(pol, vma, addr, PAGE_SHIFT);
                return alloc_page_interleave(gfp, 0, nid);
        }
-       return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol));
+       zl = zonelist_policy(gfp, pol);
+       if (pol != &default_policy && pol != current->mempolicy) {
+               /*
+                * slow path: ref counted policy -- shared or vma
+                */
+               struct page *page =  __alloc_pages(gfp, 0, zl);
+               __mpol_free(pol);
+               return page;
+       }
+       /*
+        * fast path:  default or task policy
+        */
+       return __alloc_pages(gfp, 0, zl);
 }
 
 /**
@@ -1872,6 +1927,7 @@ int show_numa_map(struct seq_file *m, void *v)
        struct numa_maps *md;
        struct file *file = vma->vm_file;
        struct mm_struct *mm = vma->vm_mm;
+       struct mempolicy *pol;
        int n;
        char buffer[50];
 
@@ -1882,8 +1938,13 @@ int show_numa_map(struct seq_file *m, void *v)
        if (!md)
                return 0;
 
-       mpol_to_str(buffer, sizeof(buffer),
-                           get_vma_policy(priv->task, vma, vma->vm_start));
+       pol = get_vma_policy(priv->task, vma, vma->vm_start);
+       mpol_to_str(buffer, sizeof(buffer), pol);
+       /*
+        * unref shared or other task's mempolicy
+        */
+       if (pol != &default_policy && pol != current->mempolicy)
+               __mpol_free(pol);
 
        seq_printf(m, "%08lx %s", vma->vm_start, buffer);
 
index 63512a9ed57e7df17bec12f4dff1685f8944042a..44720363374cb24ca3e90cb48db64d99e5bbdb5b 100644 (file)
@@ -274,9 +274,9 @@ static void balance_dirty_pages(struct address_space *mapping)
                pdflush_operation(background_writeout, 0);
 }
 
-void set_page_dirty_balance(struct page *page)
+void set_page_dirty_balance(struct page *page, int page_mkwrite)
 {
-       if (set_page_dirty(page)) {
+       if (set_page_dirty(page) || page_mkwrite) {
                struct address_space *mapping = page_mapping(page);
 
                if (mapping)
index f2de2e48b021cc960417cd330f8e9a72a648cc5c..6284c99b456eeb7fc992ffd9063d28d609fdce0f 100644 (file)
@@ -366,6 +366,12 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        frag = WLAN_GET_SEQ_FRAG(sc);
        hdrlen = ieee80211_get_hdrlen(fc);
 
+       if (skb->len < hdrlen) {
+               printk(KERN_INFO "%s: invalid SKB length %d\n",
+                       dev->name, skb->len);
+               goto rx_dropped;
+       }
+
        /* Put this code here so that we avoid duplicating it in all
         * Rx paths. - Jean II */
 #ifdef CONFIG_WIRELESS_EXT
index afb6c6698b279f84bbaf1e258e4de94d76e53fee..e475f2e1be1375e0125a6a51159833b70bbf6e4e 100644 (file)
@@ -273,8 +273,6 @@ ieee80211softmac_assoc_work(struct work_struct *work)
                        ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
                        if (ieee80211softmac_start_scan(mac)) {
                                dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
-                               mac->associnfo.associating = 0;
-                               mac->associnfo.associated = 0;
                        }
                        goto out;
                } else {
index d054e9224b3e270110790f08f540df208cbc0556..5742dc803b796af7423f36cf871ce60e74fe62fc 100644 (file)
@@ -70,44 +70,30 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
                              char *extra)
 {
        struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
-       struct ieee80211softmac_network *n;
        struct ieee80211softmac_auth_queue_item *authptr;
        int length = 0;
 
 check_assoc_again:
        mutex_lock(&sm->associnfo.mutex);
-       /* Check if we're already associating to this or another network
-        * If it's another network, cancel and start over with our new network
-        * If it's our network, ignore the change, we're already doing it!
-        */
        if((sm->associnfo.associating || sm->associnfo.associated) &&
           (data->essid.flags && data->essid.length)) {
-               /* Get the associating network */
-               n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
-               if(n && n->essid.len == data->essid.length &&
-                  !memcmp(n->essid.data, extra, n->essid.len)) {
-                       dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
-                               MAC_ARG(sm->associnfo.bssid));
-                       goto out;
-               } else {
-                       dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
-                       /* Cancel assoc work */
-                       cancel_delayed_work(&sm->associnfo.work);
-                       /* We don't have to do this, but it's a little cleaner */
-                       list_for_each_entry(authptr, &sm->auth_queue, list)
-                               cancel_delayed_work(&authptr->work);
-                       sm->associnfo.bssvalid = 0;
-                       sm->associnfo.bssfixed = 0;
-                       sm->associnfo.associating = 0;
-                       sm->associnfo.associated = 0;
-                       /* We must unlock to avoid deadlocks with the assoc workqueue
-                        * on the associnfo.mutex */
-                       mutex_unlock(&sm->associnfo.mutex);
-                       flush_scheduled_work();
-                       /* Avoid race! Check assoc status again. Maybe someone started an
-                        * association while we flushed. */
-                       goto check_assoc_again;
-               }
+               dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
+               /* Cancel assoc work */
+               cancel_delayed_work(&sm->associnfo.work);
+               /* We don't have to do this, but it's a little cleaner */
+               list_for_each_entry(authptr, &sm->auth_queue, list)
+                       cancel_delayed_work(&authptr->work);
+               sm->associnfo.bssvalid = 0;
+               sm->associnfo.bssfixed = 0;
+               sm->associnfo.associating = 0;
+               sm->associnfo.associated = 0;
+               /* We must unlock to avoid deadlocks with the assoc workqueue
+                * on the associnfo.mutex */
+               mutex_unlock(&sm->associnfo.mutex);
+               flush_scheduled_work();
+               /* Avoid race! Check assoc status again. Maybe someone started an
+                * association while we flushed. */
+               goto check_assoc_again;
        }
 
        sm->associnfo.static_essid = 0;
@@ -128,7 +114,7 @@ check_assoc_again:
        sm->associnfo.associating = 1;
        /* queue lower level code to do work (if necessary) */
        schedule_delayed_work(&sm->associnfo.work, 0);
-out:
+
        mutex_unlock(&sm->associnfo.mutex);
 
        return 0;
@@ -153,13 +139,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev,
                data->essid.length = sm->associnfo.req_essid.len;
                data->essid.flags = 1;  /* active */
                memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
-       }
-
+               dprintk(KERN_INFO PFX "Getting essid from req_essid\n");
+       } else if (sm->associnfo.associated || sm->associnfo.associating) {
        /* If we're associating/associated, return that */
-       if (sm->associnfo.associated || sm->associnfo.associating) {
                data->essid.length = sm->associnfo.associate_essid.len;
                data->essid.flags = 1;  /* active */
                memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
+               dprintk(KERN_INFO PFX "Getting essid from associate_essid\n");
        }
        mutex_unlock(&sm->associnfo.mutex);
 
index bbad2cdb74b7c18c0ae742be241857b126f06890..f893e90061ebfebe87ad359bd94c700db70b02d6 100644 (file)
@@ -2420,6 +2420,9 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
                        __u32 dval = min(tp->fackets_out, packets_acked);
                        tp->fackets_out -= dval;
                }
+               /* hint's skb might be NULL but we don't need to care */
+               tp->fastpath_cnt_hint -= min_t(u32, packets_acked,
+                                              tp->fastpath_cnt_hint);
                tp->packets_out -= packets_acked;
 
                BUG_ON(tcp_skb_pcount(skb) == 0);
index 9c94627c8c7e1888c3369f42fde366efbbe6d929..e089a978e128057e8b7bc245beaa3aad81be12a0 100644 (file)
@@ -833,8 +833,7 @@ static struct tcp_md5sig_key *
                return NULL;
        for (i = 0; i < tp->md5sig_info->entries4; i++) {
                if (tp->md5sig_info->keys4[i].addr == addr)
-                       return (struct tcp_md5sig_key *)
-                                               &tp->md5sig_info->keys4[i];
+                       return &tp->md5sig_info->keys4[i].base;
        }
        return NULL;
 }
@@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
        key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
        if (key) {
                /* Pre-existing entry - just update that one. */
-               kfree(key->key);
-               key->key = newkey;
-               key->keylen = newkeylen;
+               kfree(key->base.key);
+               key->base.key = newkey;
+               key->base.keylen = newkeylen;
        } else {
                struct tcp_md5sig_info *md5sig;
 
@@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
                        md5sig->alloced4++;
                }
                md5sig->entries4++;
-               md5sig->keys4[md5sig->entries4 - 1].addr   = addr;
-               md5sig->keys4[md5sig->entries4 - 1].key    = newkey;
-               md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen;
+               md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
+               md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
+               md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
        }
        return 0;
 }
@@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
        for (i = 0; i < tp->md5sig_info->entries4; i++) {
                if (tp->md5sig_info->keys4[i].addr == addr) {
                        /* Free the key */
-                       kfree(tp->md5sig_info->keys4[i].key);
+                       kfree(tp->md5sig_info->keys4[i].base.key);
                        tp->md5sig_info->entries4--;
 
                        if (tp->md5sig_info->entries4 == 0) {
@@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk)
        if (tp->md5sig_info->entries4) {
                int i;
                for (i = 0; i < tp->md5sig_info->entries4; i++)
-                       kfree(tp->md5sig_info->keys4[i].key);
+                       kfree(tp->md5sig_info->keys4[i].base.key);
                tp->md5sig_info->entries4 = 0;
                tcp_free_md5sig_pool();
        }
index 73a894a2152ca003b9c3de5bed0b8412d8aa42d7..5b596659177cbbd8bd5e6c2db62b803af4ca1817 100644 (file)
@@ -1268,9 +1268,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
 
        if (ipv6_addr_equal(dest, target)) {
                on_link = 1;
-       } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+       } else if (ipv6_addr_type(target) !=
+                  (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
                ND_PRINTK2(KERN_WARNING
-                          "ICMPv6 Redirect: target address is not link-local.\n");
+                          "ICMPv6 Redirect: target address is not link-local unicast.\n");
                return;
        }
 
@@ -1344,9 +1345,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
        }
 
        if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
-           !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+           ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
                ND_PRINTK2(KERN_WARNING
-                       "ICMPv6 Redirect: target address is not link-local.\n");
+                       "ICMPv6 Redirect: target address is not link-local unicast.\n");
                return;
        }
 
index 0f7defb482e9bf18411eef3d1911d922b6dbda1d..3e06799b37a65248047f050072b6208dacdca336 100644 (file)
@@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
 
        for (i = 0; i < tp->md5sig_info->entries6; i++) {
                if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
-                       return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i];
+                       return &tp->md5sig_info->keys6[i].base;
        }
        return NULL;
 }
@@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
        key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer);
        if (key) {
                /* modify existing entry - just update that one */
-               kfree(key->key);
-               key->key = newkey;
-               key->keylen = newkeylen;
+               kfree(key->base.key);
+               key->base.key = newkey;
+               key->base.keylen = newkeylen;
        } else {
                /* reallocate new list if current one is full. */
                if (!tp->md5sig_info) {
@@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
 
                ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr,
                               peer);
-               tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey;
-               tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen;
+               tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey;
+               tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen;
 
                tp->md5sig_info->entries6++;
        }
@@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
        for (i = 0; i < tp->md5sig_info->entries6; i++) {
                if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
                        /* Free the key */
-                       kfree(tp->md5sig_info->keys6[i].key);
+                       kfree(tp->md5sig_info->keys6[i].base.key);
                        tp->md5sig_info->entries6--;
 
                        if (tp->md5sig_info->entries6 == 0) {
@@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk)
 
        if (tp->md5sig_info->entries6) {
                for (i = 0; i < tp->md5sig_info->entries6; i++)
-                       kfree(tp->md5sig_info->keys6[i].key);
+                       kfree(tp->md5sig_info->keys6[i].base.key);
                tp->md5sig_info->entries6 = 0;
                tcp_free_md5sig_pool();
        }
@@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk)
 
        if (tp->md5sig_info->entries4) {
                for (i = 0; i < tp->md5sig_info->entries4; i++)
-                       kfree(tp->md5sig_info->keys4[i].key);
+                       kfree(tp->md5sig_info->keys4[i].base.key);
                tp->md5sig_info->entries4 = 0;
                tcp_free_md5sig_pool();
        }
index 7286c389a4d0ccd418a1d953e3dd921b179a9730..ff2172ffd8611758ba00efa2abc349892ca11015 100644 (file)
@@ -5259,7 +5259,7 @@ static void __exit ieee80211_exit(void)
 }
 
 
-module_init(ieee80211_init);
+subsys_initcall(ieee80211_init);
 module_exit(ieee80211_exit);
 
 MODULE_DESCRIPTION("IEEE 802.11 subsystem");
index f6780d63b34279e672b96cb0cf6400e37f770f5d..17b9f46bbf2bb6dd912c1b11e1d3b1891ee1208f 100644 (file)
@@ -431,7 +431,7 @@ static void __exit rate_control_simple_exit(void)
 }
 
 
-module_init(rate_control_simple_init);
+subsys_initcall(rate_control_simple_init);
 module_exit(rate_control_simple_exit);
 
 MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
index 89ce815296942651885fb6ec68949f082e9ca410..7ab82b376e1bc92f8d656bfa30f7a3cf4b2b1152 100644 (file)
@@ -424,7 +424,7 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt)
                skb_queue_head_init(&q->requeued[i]);
                q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
                                                 qd->handle);
-               if (q->queues[i] == 0) {
+               if (!q->queues[i]) {
                        q->queues[i] = &noop_qdisc;
                        printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
                }
index e185a5b55913ce8b37af7de85b5e9a9f8b46f2e1..2351533a850755bebd1c9ca6b26c9462fd296cf8 100644 (file)
@@ -58,7 +58,6 @@ struct nfulnl_instance {
 
        unsigned int qlen;              /* number of nlmsgs in skb */
        struct sk_buff *skb;            /* pre-allocatd skb */
-       struct nlmsghdr *lastnlh;       /* netlink header of last msg in skb */
        struct timer_list timer;
        int peer_pid;                   /* PID of the peer process */
 
@@ -345,10 +344,12 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
 static int
 __nfulnl_send(struct nfulnl_instance *inst)
 {
-       int status;
+       int status = -1;
 
        if (inst->qlen > 1)
-               inst->lastnlh->nlmsg_type = NLMSG_DONE;
+               NLMSG_PUT(inst->skb, 0, 0,
+                         NLMSG_DONE,
+                         sizeof(struct nfgenmsg));
 
        status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
        if (status < 0) {
@@ -358,8 +359,8 @@ __nfulnl_send(struct nfulnl_instance *inst)
 
        inst->qlen = 0;
        inst->skb = NULL;
-       inst->lastnlh = NULL;
 
+nlmsg_failure:
        return status;
 }
 
@@ -538,7 +539,6 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        nlh->nlmsg_len = inst->skb->tail - old_tail;
-       inst->lastnlh = nlh;
        return 0;
 
 nlmsg_failure:
@@ -644,7 +644,8 @@ nfulnl_log_packet(unsigned int pf,
        }
 
        if (inst->qlen >= qthreshold ||
-           (inst->skb && size > skb_tailroom(inst->skb))) {
+           (inst->skb && size >
+            skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) {
                /* either the queue len is too high or we don't have
                 * enough room in the skb left. flush to userspace. */
                UDEBUG("flushing old skb\n");
index cd01642f0491ae01f57e86ba6868bc13172eec9a..114df6eec8c3a7d1a7b0f6321eecca3f6afc3e63 100644 (file)
@@ -79,7 +79,7 @@ static void rose_loopback_timer(unsigned long param)
 
                skb_reset_transport_header(skb);
 
-               sk = rose_find_socket(lci_o, &rose_loopback_neigh);
+               sk = rose_find_socket(lci_o, rose_loopback_neigh);
                if (sk) {
                        if (rose_process_rx_frame(sk, skb) == 0)
                                kfree_skb(skb);
@@ -88,7 +88,7 @@ static void rose_loopback_timer(unsigned long param)
 
                if (frametype == ROSE_CALL_REQUEST) {
                        if ((dev = rose_dev_get(dest)) != NULL) {
-                               if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0)
+                               if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
                                        kfree_skb(skb);
                        } else {
                                kfree_skb(skb);
index bbcbad1da0d0facf25941e74a703bde898d941cd..96f61a71b2527da33c900acf34c92e9fa014b055 100644 (file)
@@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(rose_neigh_list_lock);
 static struct rose_route *rose_route_list;
 static DEFINE_SPINLOCK(rose_route_list_lock);
 
-struct rose_neigh rose_loopback_neigh;
+struct rose_neigh *rose_loopback_neigh;
 
 /*
  *     Add a new route to a node, and in the process add the node and the
@@ -362,7 +362,12 @@ out:
  */
 void rose_add_loopback_neigh(void)
 {
-       struct rose_neigh *sn = &rose_loopback_neigh;
+       struct rose_neigh *sn;
+
+       rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_KERNEL);
+       if (!rose_loopback_neigh)
+               return;
+       sn = rose_loopback_neigh;
 
        sn->callsign  = null_ax25_address;
        sn->digipeat  = NULL;
@@ -417,13 +422,13 @@ int rose_add_loopback_node(rose_address *address)
        rose_node->mask         = 10;
        rose_node->count        = 1;
        rose_node->loopback     = 1;
-       rose_node->neighbour[0] = &rose_loopback_neigh;
+       rose_node->neighbour[0] = rose_loopback_neigh;
 
        /* Insert at the head of list. Address is always mask=10 */
        rose_node->next = rose_node_list;
        rose_node_list  = rose_node;
 
-       rose_loopback_neigh.count++;
+       rose_loopback_neigh->count++;
 
 out:
        spin_unlock_bh(&rose_node_list_lock);
@@ -454,7 +459,7 @@ void rose_del_loopback_node(rose_address *address)
 
        rose_remove_node(rose_node);
 
-       rose_loopback_neigh.count--;
+       rose_loopback_neigh->count--;
 
 out:
        spin_unlock_bh(&rose_node_list_lock);
index 8dbe36912ecb226c370184d4d40b88b77163fa46..d4d5d2f271d2f77f17fc7dbfd605cbbe3ab14f5a 100644 (file)
@@ -502,7 +502,7 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
 
 #ifdef CONFIG_NET_CLS_IND
        if (tb[TCA_U32_INDEV-1]) {
-               int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
+               err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
                if (err < 0)
                        goto errout;
        }
index 9579573098598df19066e0910e181e68a94ef080..b542c875e154411cfaaf3d78abe443d9e5e4931d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/ipv6.h>
 #include <linux/skbuff.h>
+#include <linux/jhash.h>
 #include <net/ip.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -95,7 +96,7 @@ struct sfq_sched_data
 
 /* Variables */
        struct timer_list perturb_timer;
-       int             perturbation;
+       u32             perturbation;
        sfq_index       tail;           /* Index of current slot in round */
        sfq_index       max_depth;      /* Maximal depth */
 
@@ -109,12 +110,7 @@ struct sfq_sched_data
 
 static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1)
 {
-       int pert = q->perturbation;
-
-       /* Have we any rotation primitives? If not, WHY? */
-       h ^= (h1<<pert) ^ (h1>>(0x1F - pert));
-       h ^= h>>10;
-       return h & 0x3FF;
+       return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1);
 }
 
 static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
@@ -256,6 +252,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                q->ht[hash] = x = q->dep[SFQ_DEPTH].next;
                q->hash[x] = hash;
        }
+       /* If selected queue has length q->limit, this means that
+        * all another queues are empty and that we do simple tail drop,
+        * i.e. drop _this_ packet.
+        */
+       if (q->qs[x].qlen >= q->limit)
+               return qdisc_drop(skb, sch);
+
        sch->qstats.backlog += skb->len;
        __skb_queue_tail(&q->qs[x], skb);
        sfq_inc(q, x);
@@ -270,7 +273,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                        q->tail = x;
                }
        }
-       if (++sch->q.qlen < q->limit-1) {
+       if (++sch->q.qlen <= q->limit) {
                sch->bstats.bytes += skb->len;
                sch->bstats.packets++;
                return 0;
@@ -294,6 +297,19 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
        }
        sch->qstats.backlog += skb->len;
        __skb_queue_head(&q->qs[x], skb);
+       /* If selected queue has length q->limit+1, this means that
+        * all another queues are empty and we do simple tail drop.
+        * This packet is still requeued at head of queue, tail packet
+        * is dropped.
+        */
+       if (q->qs[x].qlen > q->limit) {
+               skb = q->qs[x].prev;
+               __skb_unlink(skb, &q->qs[x]);
+               sch->qstats.drops++;
+               sch->qstats.backlog -= skb->len;
+               kfree_skb(skb);
+               return NET_XMIT_CN;
+       }
        sfq_inc(q, x);
        if (q->qs[x].qlen == 1) {               /* The flow is new */
                if (q->tail == SFQ_DEPTH) {     /* It is the first flow */
@@ -306,7 +322,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
                        q->tail = x;
                }
        }
-       if (++sch->q.qlen < q->limit - 1) {
+       if (++sch->q.qlen <= q->limit) {
                sch->qstats.requeues++;
                return 0;
        }
@@ -370,12 +386,10 @@ static void sfq_perturbation(unsigned long arg)
        struct Qdisc *sch = (struct Qdisc*)arg;
        struct sfq_sched_data *q = qdisc_priv(sch);
 
-       q->perturbation = net_random()&0x1F;
+       get_random_bytes(&q->perturbation, 4);
 
-       if (q->perturb_period) {
-               q->perturb_timer.expires = jiffies + q->perturb_period;
-               add_timer(&q->perturb_timer);
-       }
+       if (q->perturb_period)
+               mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
 }
 
 static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
@@ -391,17 +405,17 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
        q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
        q->perturb_period = ctl->perturb_period*HZ;
        if (ctl->limit)
-               q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
+               q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1);
 
        qlen = sch->q.qlen;
-       while (sch->q.qlen >= q->limit-1)
+       while (sch->q.qlen > q->limit)
                sfq_drop(sch);
        qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
 
        del_timer(&q->perturb_timer);
        if (q->perturb_period) {
-               q->perturb_timer.expires = jiffies + q->perturb_period;
-               add_timer(&q->perturb_timer);
+               mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
+               get_random_bytes(&q->perturbation, 4);
        }
        sch_tree_unlock(sch);
        return 0;
@@ -423,12 +437,13 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt)
                q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH;
                q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH;
        }
-       q->limit = SFQ_DEPTH;
+       q->limit = SFQ_DEPTH - 1;
        q->max_depth = 0;
        q->tail = SFQ_DEPTH;
        if (opt == NULL) {
                q->quantum = psched_mtu(sch->dev);
                q->perturb_period = 0;
+               get_random_bytes(&q->perturbation, 4);
        } else {
                int err = sfq_change(sch, opt);
                if (err)
index d35cbf5aae33de7b56348cc235e532f69043caba..dfffa94fb9f636366616ca3e349ffcfee746f5cb 100644 (file)
@@ -181,7 +181,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
  * structure.
  */
 int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
-                       void (*rcu_call)(struct rcu_head *head,
+                       void fastcall (*rcu_call)(struct rcu_head *head,
                                         void (*func)(struct rcu_head *head)))
 {
        struct sctp_sockaddr_entry *addr, *temp;
index 47e56017f4ce887716e0dee8a4ba87d3ece37ac9..f9a0c9276e3b55f8c1497beacba30c8426ae0d28 100644 (file)
@@ -622,6 +622,14 @@ static int sctp_rcv_ootb(struct sk_buff *skb)
                if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type)
                        goto discard;
 
+               /* RFC 4460, 2.11.2
+                * This will discard packets with INIT chunk bundled as
+                * subsequent chunks in the packet.  When INIT is first,
+                * the normal INIT processing will discard the chunk.
+                */
+               if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data)
+                       goto discard;
+
                /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR
                 * or a COOKIE ACK the SCTP Packet should be silently
                 * discarded.
index 88aa2240754935522962a001088286516a8f8011..e4ea7fdf36ed798c23d3b2dfb6e3f2a0e54e893b 100644 (file)
@@ -130,6 +130,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
                        /* Force chunk->skb->data to chunk->chunk_end.  */
                        skb_pull(chunk->skb,
                                 chunk->chunk_end - chunk->skb->data);
+
+                       /* Verify that we have at least chunk headers
+                        * worth of buffer left.
+                        */
+                       if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) {
+                               sctp_chunk_free(chunk);
+                               chunk = queue->in_progress = NULL;
+                       }
                }
        }
 
index 2e34220d94cde899fffb551091305eddf9323b7c..23ae37ec871167d17c37ddbdbb9d4095e26a4575 100644 (file)
@@ -2499,6 +2499,52 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
        return SCTP_ERROR_NO_ERROR;
 }
 
+/* Verify the ASCONF packet before we process it.  */
+int sctp_verify_asconf(const struct sctp_association *asoc,
+                      struct sctp_paramhdr *param_hdr, void *chunk_end,
+                      struct sctp_paramhdr **errp) {
+       sctp_addip_param_t *asconf_param;
+       union sctp_params param;
+       int length, plen;
+
+       param.v = (sctp_paramhdr_t *) param_hdr;
+       while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) {
+               length = ntohs(param.p->length);
+               *errp = param.p;
+
+               if (param.v > chunk_end - length ||
+                   length < sizeof(sctp_paramhdr_t))
+                       return 0;
+
+               switch (param.p->type) {
+               case SCTP_PARAM_ADD_IP:
+               case SCTP_PARAM_DEL_IP:
+               case SCTP_PARAM_SET_PRIMARY:
+                       asconf_param = (sctp_addip_param_t *)param.v;
+                       plen = ntohs(asconf_param->param_hdr.length);
+                       if (plen < sizeof(sctp_addip_param_t) +
+                           sizeof(sctp_paramhdr_t))
+                               return 0;
+                       break;
+               case SCTP_PARAM_SUCCESS_REPORT:
+               case SCTP_PARAM_ADAPTATION_LAYER_IND:
+                       if (length != sizeof(sctp_addip_param_t))
+                               return 0;
+
+                       break;
+               default:
+                       break;
+               }
+
+               param.v += WORD_ROUND(length);
+       }
+
+       if (param.v != chunk_end)
+               return 0;
+
+       return 1;
+}
+
 /* Process an incoming ASCONF chunk with the next expected serial no. and
  * return an ASCONF_ACK chunk to be sent in response.
  */
index 177528ed3e1b1d9f50ea2c9be844d5a5d0553187..a583d67cab63859439c5a38fb54133afc406a401 100644 (file)
@@ -90,6 +90,11 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
                                             const sctp_subtype_t type,
                                             void *arg,
                                             sctp_cmd_seq_t *commands);
+static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
+                                       const struct sctp_association *asoc,
+                                       const sctp_subtype_t type,
+                                       void *arg,
+                                       sctp_cmd_seq_t *commands);
 static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
 
 static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
@@ -98,6 +103,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
                                           struct sctp_transport *transport);
 
 static sctp_disposition_t sctp_sf_abort_violation(
+                                    const struct sctp_endpoint *ep,
                                     const struct sctp_association *asoc,
                                     void *arg,
                                     sctp_cmd_seq_t *commands,
@@ -111,6 +117,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
                                     void *arg,
                                     sctp_cmd_seq_t *commands);
 
+static sctp_disposition_t sctp_sf_violation_paramlen(
+                                    const struct sctp_endpoint *ep,
+                                    const struct sctp_association *asoc,
+                                    const sctp_subtype_t type,
+                                    void *arg,
+                                    sctp_cmd_seq_t *commands);
+
 static sctp_disposition_t sctp_sf_violation_ctsn(
                                     const struct sctp_endpoint *ep,
                                     const struct sctp_association *asoc,
@@ -118,6 +131,13 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
                                     void *arg,
                                     sctp_cmd_seq_t *commands);
 
+static sctp_disposition_t sctp_sf_violation_chunk(
+                                    const struct sctp_endpoint *ep,
+                                    const struct sctp_association *asoc,
+                                    const sctp_subtype_t type,
+                                    void *arg,
+                                    sctp_cmd_seq_t *commands);
+
 /* Small helper function that checks if the chunk length
  * is of the appropriate length.  The 'required_length' argument
  * is set to be the size of a specific chunk we are testing.
@@ -181,16 +201,21 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
        struct sctp_chunk *chunk = arg;
        struct sctp_ulpevent *ev;
 
+       if (!sctp_vtag_verify_either(chunk, asoc))
+               return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
        /* RFC 2960 6.10 Bundling
         *
         * An endpoint MUST NOT bundle INIT, INIT ACK or
         * SHUTDOWN COMPLETE with any other chunks.
         */
        if (!chunk->singleton)
-               return SCTP_DISPOSITION_VIOLATION;
+               return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
 
-       if (!sctp_vtag_verify_either(chunk, asoc))
-               return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+       /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
 
        /* RFC 2960 10.2 SCTP-to-ULP
         *
@@ -450,17 +475,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
-       /* Make sure that the INIT-ACK chunk has a valid length */
-       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
-               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
-                                                 commands);
        /* 6.10 Bundling
         * An endpoint MUST NOT bundle INIT, INIT ACK or
         * SHUTDOWN COMPLETE with any other chunks.
         */
        if (!chunk->singleton)
-               return SCTP_DISPOSITION_VIOLATION;
+               return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
 
+       /* Make sure that the INIT-ACK chunk has a valid length */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
        /* Grab the INIT header.  */
        chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
 
@@ -585,7 +610,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
         * control endpoint, respond with an ABORT.
         */
        if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
-               return sctp_sf_ootb(ep, asoc, type, arg, commands);
+               return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 
        /* Make sure that the COOKIE_ECHO chunk has a valid length.
         * In this case, we check that we have enough for at least a
@@ -2496,6 +2521,11 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
        struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
        struct sctp_chunk *reply;
 
+       /* Make sure that the chunk has a valid length */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
+
        /* Since we are not going to really process this INIT, there
         * is no point in verifying chunk boundries.  Just generate
         * the SHUTDOWN ACK.
@@ -2929,7 +2959,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
  *
  * The return value is the disposition of the chunk.
 */
-sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
                                        const struct sctp_association *asoc,
                                        const sctp_subtype_t type,
                                        void *arg,
@@ -2965,6 +2995,7 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
 
                SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
 
+               sctp_sf_pdiscard(ep, asoc, type, arg, commands);
                return SCTP_DISPOSITION_CONSUME;
        }
 
@@ -3125,14 +3156,14 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
 
        ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
        do {
-               /* Break out if chunk length is less then minimal. */
+               /* Report violation if the chunk is less then minimal */
                if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
-                       break;
-
-               ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
-               if (ch_end > skb_tail_pointer(skb))
-                       break;
+                       return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
 
+               /* Now that we know we at least have a chunk header,
+                * do things that are type appropriate.
+                */
                if (SCTP_CID_SHUTDOWN_ACK == ch->type)
                        ootb_shut_ack = 1;
 
@@ -3144,15 +3175,19 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
                if (SCTP_CID_ABORT == ch->type)
                        return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
+               /* Report violation if chunk len overflows */
+               ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+               if (ch_end > skb_tail_pointer(skb))
+                       return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
+
                ch = (sctp_chunkhdr_t *) ch_end;
        } while (ch_end < skb_tail_pointer(skb));
 
        if (ootb_shut_ack)
-               sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
+               return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
        else
-               sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
-
-       return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+               return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 }
 
 /*
@@ -3218,7 +3253,11 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
                if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
                        return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
-               return SCTP_DISPOSITION_CONSUME;
+               /* We need to discard the rest of the packet to prevent
+                * potential bomming attacks from additional bundled chunks.
+                * This is documented in SCTP Threats ID.
+                */
+               return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
        }
 
        return SCTP_DISPOSITION_NOMEM;
@@ -3241,6 +3280,13 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
                                      void *arg,
                                      sctp_cmd_seq_t *commands)
 {
+       struct sctp_chunk *chunk = arg;
+
+       /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
+
        /* Although we do have an association in this case, it corresponds
         * to a restarted association. So the packet is treated as an OOTB
         * packet and the state function that handles OOTB SHUTDOWN_ACK is
@@ -3257,8 +3303,11 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
 {
        struct sctp_chunk       *chunk = arg;
        struct sctp_chunk       *asconf_ack = NULL;
+       struct sctp_paramhdr    *err_param = NULL;
        sctp_addiphdr_t         *hdr;
+       union sctp_addr_param   *addr_param;
        __u32                   serial;
+       int                     length;
 
        if (!sctp_vtag_verify(chunk, asoc)) {
                sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -3274,6 +3323,20 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
        hdr = (sctp_addiphdr_t *)chunk->skb->data;
        serial = ntohl(hdr->serial);
 
+       addr_param = (union sctp_addr_param *)hdr->params;
+       length = ntohs(addr_param->p.length);
+       if (length < sizeof(sctp_paramhdr_t))
+               return sctp_sf_violation_paramlen(ep, asoc, type,
+                          (void *)addr_param, commands);
+
+       /* Verify the ASCONF chunk before processing it. */
+       if (!sctp_verify_asconf(asoc,
+           (sctp_paramhdr_t *)((void *)addr_param + length),
+           (void *)chunk->chunk_end,
+           &err_param))
+               return sctp_sf_violation_paramlen(ep, asoc, type,
+                          (void *)&err_param, commands);
+
        /* ADDIP 4.2 C1) Compare the value of the serial number to the value
         * the endpoint stored in a new association variable
         * 'Peer-Serial-Number'.
@@ -3328,6 +3391,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
        struct sctp_chunk       *asconf_ack = arg;
        struct sctp_chunk       *last_asconf = asoc->addip_last_asconf;
        struct sctp_chunk       *abort;
+       struct sctp_paramhdr    *err_param = NULL;
        sctp_addiphdr_t         *addip_hdr;
        __u32                   sent_serial, rcvd_serial;
 
@@ -3345,6 +3409,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
        addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
        rcvd_serial = ntohl(addip_hdr->serial);
 
+       /* Verify the ASCONF-ACK chunk before processing it. */
+       if (!sctp_verify_asconf(asoc,
+           (sctp_paramhdr_t *)addip_hdr->params,
+           (void *)asconf_ack->chunk_end,
+           &err_param))
+               return sctp_sf_violation_paramlen(ep, asoc, type,
+                          (void *)&err_param, commands);
+
        if (last_asconf) {
                addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
                sent_serial = ntohl(addip_hdr->serial);
@@ -3655,6 +3727,16 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep,
                                         void *arg,
                                         sctp_cmd_seq_t *commands)
 {
+       struct sctp_chunk *chunk = arg;
+
+       /* Make sure that the chunk has a valid length.
+        * Since we don't know the chunk type, we use a general
+        * chunkhdr structure to make a comparison.
+        */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
+
        SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk);
        return SCTP_DISPOSITION_DISCARD;
 }
@@ -3710,6 +3792,13 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
                                     void *arg,
                                     sctp_cmd_seq_t *commands)
 {
+       struct sctp_chunk *chunk = arg;
+
+       /* Make sure that the chunk has a valid length. */
+       if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+               return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+                                                 commands);
+
        return SCTP_DISPOSITION_VIOLATION;
 }
 
@@ -3717,12 +3806,14 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
  * Common function to handle a protocol violation.
  */
 static sctp_disposition_t sctp_sf_abort_violation(
+                                    const struct sctp_endpoint *ep,
                                     const struct sctp_association *asoc,
                                     void *arg,
                                     sctp_cmd_seq_t *commands,
                                     const __u8 *payload,
                                     const size_t paylen)
 {
+       struct sctp_packet *packet = NULL;
        struct sctp_chunk *chunk =  arg;
        struct sctp_chunk *abort = NULL;
 
@@ -3731,30 +3822,51 @@ static sctp_disposition_t sctp_sf_abort_violation(
        if (!abort)
                goto nomem;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
-       SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+       if (asoc) {
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+               SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
 
-       if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
-               sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
-                               SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
-               sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-                               SCTP_ERROR(ECONNREFUSED));
-               sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
-                               SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
+               if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
+                       sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+                                       SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+                       sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+                                       SCTP_ERROR(ECONNREFUSED));
+                       sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+                                       SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
+               } else {
+                       sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+                                       SCTP_ERROR(ECONNABORTED));
+                       sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+                                       SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
+                       SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+               }
        } else {
-               sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-                               SCTP_ERROR(ECONNABORTED));
-               sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-                               SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
-               SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+               packet = sctp_ootb_pkt_new(asoc, chunk);
+
+               if (!packet)
+                       goto nomem_pkt;
+
+               if (sctp_test_T_bit(abort))
+                       packet->vtag = ntohl(chunk->sctp_hdr->vtag);
+
+               abort->skb->sk = ep->base.sk;
+
+               sctp_packet_append_chunk(packet, abort);
+
+               sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
+                       SCTP_PACKET(packet));
+
+               SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
        }
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
+       sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
 
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
 
        return SCTP_DISPOSITION_ABORT;
 
+nomem_pkt:
+       sctp_chunk_free(abort);
 nomem:
        return SCTP_DISPOSITION_NOMEM;
 }
@@ -3787,7 +3899,24 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
 {
        char err_str[]="The following chunk had invalid length:";
 
-       return sctp_sf_abort_violation(asoc, arg, commands, err_str,
+       return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+                                       sizeof(err_str));
+}
+
+/*
+ * Handle a protocol violation when the parameter length is invalid.
+ * "Invalid" length is identified as smaller then the minimal length a
+ * given parameter can be.
+ */
+static sctp_disposition_t sctp_sf_violation_paramlen(
+                                    const struct sctp_endpoint *ep,
+                                    const struct sctp_association *asoc,
+                                    const sctp_subtype_t type,
+                                    void *arg,
+                                    sctp_cmd_seq_t *commands) {
+       char err_str[] = "The following parameter had invalid length:";
+
+       return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
                                        sizeof(err_str));
 }
 
@@ -3806,10 +3935,31 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
 {
        char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
 
-       return sctp_sf_abort_violation(asoc, arg, commands, err_str,
+       return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
                                        sizeof(err_str));
 }
 
+/* Handle protocol violation of an invalid chunk bundling.  For example,
+ * when we have an association and we recieve bundled INIT-ACK, or
+ * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle"
+ * statement from the specs.  Additinally, there might be an attacker
+ * on the path and we may not want to continue this communication.
+ */
+static sctp_disposition_t sctp_sf_violation_chunk(
+                                    const struct sctp_endpoint *ep,
+                                    const struct sctp_association *asoc,
+                                    const sctp_subtype_t type,
+                                    void *arg,
+                                    sctp_cmd_seq_t *commands)
+{
+       char err_str[]="The following chunk violates protocol:";
+
+       if (!asoc)
+               return sctp_sf_violation(ep, asoc, type, arg, commands);
+
+       return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+                                       sizeof(err_str));
+}
 /***************************************************************************
  * These are the state functions for handling primitive (Section 10) events.
  ***************************************************************************/
@@ -5176,7 +5326,22 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
         * association exists, otherwise, use the peer's vtag.
         */
        if (asoc) {
-               vtag = asoc->peer.i.init_tag;
+               /* Special case the INIT-ACK as there is no peer's vtag
+                * yet.
+                */
+               switch(chunk->chunk_hdr->type) {
+               case SCTP_CID_INIT_ACK:
+               {
+                       sctp_initack_chunk_t *initack;
+
+                       initack = (sctp_initack_chunk_t *)chunk->chunk_hdr;
+                       vtag = ntohl(initack->init_hdr.init_tag);
+                       break;
+               }
+               default:
+                       vtag = asoc->peer.i.init_tag;
+                       break;
+               }
        } else {
                /* Special case the INIT and stale COOKIE_ECHO as there is no
                 * vtag yet.
index 70a91ece3c49444de91b41b7db7f4b486a16e7de..ddb0ba3974b05a31807c8652f97ad9a2cfc10fcf 100644 (file)
@@ -110,7 +110,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /* SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -173,7 +173,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /*  SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -194,7 +194,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /*  SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -216,7 +216,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /*  SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_violation), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -258,7 +258,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /* SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -300,7 +300,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
        /* SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -499,7 +499,7 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_
        /* SCTP_STATE_EMPTY */ \
        TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_CLOSED */ \
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
+       TYPE_SCTP_FUNC(sctp_sf_ootb), \
        /* SCTP_STATE_COOKIE_WAIT */ \
        TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
        /* SCTP_STATE_COOKIE_ECHOED */ \
@@ -528,7 +528,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
        /* SCTP_STATE_EMPTY */
        TYPE_SCTP_FUNC(sctp_sf_ootb),
        /* SCTP_STATE_CLOSED */
-       TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8),
+       TYPE_SCTP_FUNC(sctp_sf_ootb),
        /* SCTP_STATE_COOKIE_WAIT */
        TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
        /* SCTP_STATE_COOKIE_ECHOED */
index 7d44453dfae13a43a4e4a1a72e077ff644d96661..b09eb9036a17a3563e9ad5ca08a1734b86aa0df5 100644 (file)
@@ -777,9 +777,6 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (pos != 0)
                return -ESPIPE;
 
-       if (iocb->ki_left == 0) /* Match SYS5 behaviour */
-               return 0;
-
        x = alloc_sock_iocb(iocb, &siocb);
        if (!x)
                return -ENOMEM;
index 1a899924023faefc4e6a65b2ab80f4918306e05a..036ab520df21ec5ecea04342e979fc58762aa059 100644 (file)
@@ -1110,7 +1110,8 @@ svc_tcp_accept(struct svc_sock *svsk)
                                                   serv->sv_name);
                                printk(KERN_NOTICE
                                       "%s: last TCP connect from %s\n",
-                                      serv->sv_name, buf);
+                                      serv->sv_name, __svc_print_addr(sin,
+                                                       buf, sizeof(buf)));
                        }
                        /*
                         * Always select the oldest socket. It's not fair,
index 7eabd55417a5eab222a4c756d1e2181513575cc7..9771451eae217d9624db3efbac4e08f91ec9ab5c 100644 (file)
@@ -213,7 +213,7 @@ out_fail_notifier:
 out_fail_sysfs:
        return err;
 }
-module_init(cfg80211_init);
+subsys_initcall(cfg80211_init);
 
 static void cfg80211_exit(void)
 {
index 88aaacd9f82275a3266b67165bb9a470d8069f4c..2d5d2255a27cd54bb12c1a21724680a5cdba617d 100644 (file)
@@ -52,12 +52,14 @@ static void wiphy_dev_release(struct device *dev)
        cfg80211_dev_free(rdev);
 }
 
+#ifdef CONFIG_HOTPLUG
 static int wiphy_uevent(struct device *dev, char **envp,
                        int num_envp, char *buf, int size)
 {
        /* TODO, we probably need stuff here */
        return 0;
 }
+#endif
 
 struct class ieee80211_class = {
        .name = "ieee80211",
index 36946629b6cafa391baa7168e55a8aab2bef3b78..0753b20e23fed48c80f4864b67fbe476de8daced 100644 (file)
@@ -316,6 +316,7 @@ static inline int inode_doinit(struct inode *inode)
 }
 
 enum {
+       Opt_error = -1,
        Opt_context = 1,
        Opt_fscontext = 2,
        Opt_defcontext = 4,
@@ -327,6 +328,7 @@ static match_table_t tokens = {
        {Opt_fscontext, "fscontext=%s"},
        {Opt_defcontext, "defcontext=%s"},
        {Opt_rootcontext, "rootcontext=%s"},
+       {Opt_error, NULL},
 };
 
 #define SEL_MOUNT_FAIL_MSG "SELinux:  duplicate or incompatible mount options\n"
index f057430db0d01021d6b2c27df157b64a4958fd7a..9b5656d8bccac7d140168bfbd1e65af4a0e96c13 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
@@ -481,53 +482,54 @@ static void free_all_reserved_pages(void)
 #define SND_MEM_PROC_FILE      "driver/snd-page-alloc"
 static struct proc_dir_entry *snd_mem_proc;
 
-static int snd_mem_proc_read(char *page, char **start, off_t off,
-                            int count, int *eof, void *data)
+static int snd_mem_proc_read(struct seq_file *seq, void *offset)
 {
-       int len = 0;
        long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
        struct snd_mem_list *mem;
        int devno;
        static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
 
        mutex_lock(&list_mutex);
-       len += snprintf(page + len, count - len,
-                       "pages  : %li bytes (%li pages per %likB)\n",
-                       pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
+       seq_printf(seq, "pages  : %li bytes (%li pages per %likB)\n",
+                  pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
        devno = 0;
        list_for_each_entry(mem, &mem_list_head, list) {
                devno++;
-               len += snprintf(page + len, count - len,
-                               "buffer %d : ID %08x : type %s\n",
-                               devno, mem->id, types[mem->buffer.dev.type]);
-               len += snprintf(page + len, count - len,
-                               "  addr = 0x%lx, size = %d bytes\n",
-                               (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes);
+               seq_printf(seq, "buffer %d : ID %08x : type %s\n",
+                          devno, mem->id, types[mem->buffer.dev.type]);
+               seq_printf(seq, "  addr = 0x%lx, size = %d bytes\n",
+                          (unsigned long)mem->buffer.addr,
+                          (int)mem->buffer.bytes);
        }
        mutex_unlock(&list_mutex);
-       return len;
+       return 0;
+}
+
+static int snd_mem_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, snd_mem_proc_read, NULL);
 }
 
 /* FIXME: for pci only - other bus? */
 #ifdef CONFIG_PCI
 #define gettoken(bufp) strsep(bufp, " \t\n")
 
-static int snd_mem_proc_write(struct file *file, const char __user *buffer,
-                             unsigned long count, void *data)
+static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
+                                 size_t count, loff_t * ppos)
 {
        char buf[128];
        char *token, *p;
 
-       if (count > ARRAY_SIZE(buf) - 1)
-               count = ARRAY_SIZE(buf) - 1;
+       if (count > sizeof(buf) - 1)
+               return -EINVAL;
        if (copy_from_user(buf, buffer, count))
                return -EFAULT;
-       buf[ARRAY_SIZE(buf) - 1] = '\0';
+       buf[count] = '\0';
 
        p = buf;
        token = gettoken(&p);
        if (! token || *token == '#')
-               return (int)count;
+               return count;
        if (strcmp(token, "add") == 0) {
                char *endp;
                int vendor, device, size, buffers;
@@ -548,7 +550,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
                    (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
                    buffers > 4) {
                        printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
-                       return (int)count;
+                       return count;
                }
                vendor &= 0xffff;
                device &= 0xffff;
@@ -560,7 +562,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
                                if (pci_set_dma_mask(pci, mask) < 0 ||
                                    pci_set_consistent_dma_mask(pci, mask) < 0) {
                                        printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
-                                       return (int)count;
+                                       return count;
                                }
                        }
                        for (i = 0; i < buffers; i++) {
@@ -570,7 +572,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
                                                        size, &dmab) < 0) {
                                        printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
                                        pci_dev_put(pci);
-                                       return (int)count;
+                                       return count;
                                }
                                snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
                        }
@@ -596,9 +598,21 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
                free_all_reserved_pages();
        else
                printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
-       return (int)count;
+       return count;
 }
 #endif /* CONFIG_PCI */
+
+static const struct file_operations snd_mem_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = snd_mem_proc_open,
+       .read           = seq_read,
+#ifdef CONFIG_PCI
+       .write          = snd_mem_proc_write,
+#endif
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -609,12 +623,8 @@ static int __init snd_mem_init(void)
 {
 #ifdef CONFIG_PROC_FS
        snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
-       if (snd_mem_proc) {
-               snd_mem_proc->read_proc = snd_mem_proc_read;
-#ifdef CONFIG_PCI
-               snd_mem_proc->write_proc = snd_mem_proc_write;
-#endif
-       }
+       if (snd_mem_proc)
+               snd_mem_proc->proc_fops = &snd_mem_proc_fops;
 #endif
        return 0;
 }