Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Dec 2010 18:37:37 +0000 (10:37 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Dec 2010 18:37:37 +0000 (10:37 -0800)
* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  sched: Fix the irqtime code for 32bit
  sched: Fix the irqtime code to deal with u64 wraps
  nohz: Fix get_next_timer_interrupt() vs cpu hotplug
  Sched: fix skip_clock_update optimization
  sched: Cure more NO_HZ load average woes

384 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
Documentation/kernel-parameters.txt
Documentation/power/runtime_pm.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/stamp9g20.h [new file with mode: 0644]
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-pxa/palmtx.c
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-macros.S
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/sram.c
arch/arm/tools/mach-types
arch/mips/Kconfig
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/devboards/prom.c
arch/mips/ar7/clock.c
arch/mips/ar7/time.c
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/io.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-bcm47xx/nvram.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/prom.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/prom.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/lib/memset.S
arch/mips/loongson/common/env.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-mips.c
arch/mips/pmc-sierra/yosemite/py-console.c
arch/mips/sibyte/swarm/setup.c
arch/sh/Kconfig
arch/sh/include/asm/unistd_32.h
arch/sh/kernel/syscalls_32.S
arch/sparc/include/asm/openprom.h
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/prom/Makefile
arch/sparc/prom/console_32.c
arch/sparc/prom/console_64.c
arch/sparc/prom/devops_32.c [deleted file]
arch/sparc/prom/devops_64.c [deleted file]
arch/sparc/prom/misc_64.c
arch/sparc/prom/printf.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/tile/include/asm/signal.h
arch/tile/kernel/compat_signal.c
arch/tile/kernel/intvec_32.S
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/x86/crypto/ghash-clmulni-intel_glue.c
arch/x86/include/asm/e820.h
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/Makefile
arch/x86/kernel/head_32.S
arch/x86/kernel/resource.c [new file with mode: 0644]
arch/x86/kernel/setup.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/lguest/i386_head.S
arch/x86/pci/i386.c
block/bsg.c
drivers/acpi/ac.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/hest.c
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_thermal.c
drivers/acpi/sleep.c
drivers/atm/adummy.c
drivers/atm/ambassador.c
drivers/atm/atmtcp.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/horizon.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/lanai.c
drivers/atm/nicstar.c
drivers/atm/solos-pci.c
drivers/atm/zatm.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/connector/connector.c
drivers/dma/Makefile
drivers/dma/at_hdmac.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/Makefile
drivers/dma/pch_dma.c
drivers/dma/ppc4xx/adma.c
drivers/edac/amd64_edac.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/firewire/ohci.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/radeon/r600.c
drivers/hwmon/adm1026.c
drivers/hwmon/it87.c
drivers/hwmon/ltc4215.c
drivers/i2c/busses/i2c-intel-mid.c
drivers/idle/intel_idle.c
drivers/infiniband/core/uverbs_cmd.c
drivers/input/evdev.c
drivers/input/tablet/wacom_wac.c
drivers/md/md.c
drivers/md/raid10.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/arv.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cx18/cx18-alsa-pcm.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/meye.c
drivers/media/video/pms.c
drivers/media/video/sh_vou.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/w9966.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/nand/omap2.c
drivers/net/b44.c
drivers/net/benet/be_cmds.c
drivers/net/bnx2x/bnx2x.h
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bnx2x/bnx2x_init_ops.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/caif/caif_shm_u5500.c
drivers/net/caif/caif_shmcore.c
drivers/net/cxgb4/t4_hw.c
drivers/net/cxgb4vf/cxgb4vf_main.c
drivers/net/ehea/ehea_ethtool.c
drivers/net/ehea/ehea_main.c
drivers/net/enic/enic_main.c
drivers/net/ifb.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/phy/Kconfig
drivers/net/phy/icplus.c
drivers/net/pppoe.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c
drivers/net/r8169.c
drivers/net/sfc/efx.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/stmmac/stmmac_main.c
drivers/net/tulip/dmfe.c
drivers/net/usb/hso.c
drivers/net/wan/hd64572.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/scan.c
drivers/net/wireless/orinoco/scan.h
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/orinoco/wext.c
drivers/net/xen-netfront.c
drivers/pci/bus.c
drivers/pci/quirks.c
drivers/pnp/pnpacpi/core.c
drivers/regulator/tps6586x-regulator.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/hpsa.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/pmcraid.c
drivers/scsi/pmcraid.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/serial/kgdboc.c
drivers/spi/dw_spi.c
drivers/usb/atm/usbatm.c
drivers/vhost/vhost.c
drivers/video/modedb.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/orphan.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/dir.c
fs/ceph/ioctl.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/cifs/Makefile
fs/cifs/README
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fuse/file.c
fs/namei.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/mount_clnt.c
fs/nfs/nfs4proc.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/xdr4.h
fs/nilfs2/gcinode.c
fs/nilfs2/ioctl.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
fs/xfs/xfs_rename.c
include/acpi/video.h
include/linux/acpi.h
include/linux/atmdev.h
include/linux/fanotify.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
include/linux/input.h
include/linux/ioport.h
include/linux/mfd/wm8994/pdata.h
include/linux/nfs_fs.h
include/linux/nfs_page.h
include/linux/pm_runtime.h
include/linux/snmp.h
include/linux/ssb/ssb_driver_gige.h
include/linux/video_output.h
include/media/v4l2-device.h
include/net/sock.h
include/xen/interface/io/ring.h
kernel/power/swap.c
kernel/power/user.c
kernel/resource.c
kernel/workqueue.c
mm/filemap.c
mm/mmap.c
mm/truncate.c
mm/vmscan.c
net/atm/atm_sysfs.c
net/atm/resources.c
net/atm/resources.h
net/bluetooth/sco.c
net/core/filter.c
net/core/timestamping.c
net/econet/af_econet.c
net/ipv4/proc.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_tunnel.c
net/ipv6/sit.c
net/l2tp/l2tp_ip.c
net/llc/af_llc.c
net/mac80211/rx.c
net/mac80211/tx.c
net/sctp/socket.c
net/socket.c
net/sunrpc/svc_xprt.c
net/x25/x25_link.c
net/xfrm/xfrm_state.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm_hubs.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c

index a91f308..b6426f1 100644 (file)
@@ -173,12 +173,13 @@ prototypes:
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*launder_page) (struct page *);
 
 locking rules:
-       All except set_page_dirty may block
+       All except set_page_dirty and freepage may block
 
                        BKL     PageLocked(page)        i_mutex
 writepage:             no      yes, unlocks (see below)
@@ -193,6 +194,7 @@ perform_write:              no      n/a                     yes
 bmap:                  no
 invalidatepage:                no      yes
 releasepage:           no      yes
+freepage:              no      yes
 direct_IO:             no
 launder_page:          no      yes
 
@@ -288,6 +290,9 @@ buffers from the page in preparation for freeing it.  It returns zero to
 indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
 the kernel assumes that the fs has no private interest in the buffers.
 
+       ->freepage() is called when the kernel is done dropping the page
+from the page cache.
+
        ->launder_page() may be called prior to releasing a page if
 it is still found to be dirty. It returns zero if the page was successfully
 cleaned, or an error value if not. Note that in order to prevent the page
index 55c28b7..20899e0 100644 (file)
@@ -534,6 +534,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
@@ -678,6 +679,12 @@ struct address_space_operations {
         need to ensure this.  Possibly it can clear the PageUptodate
         bit if it cannot free private data yet.
 
+  freepage: freepage is called once the page is no longer visible in
+        the page cache in order to allow the cleanup of any private
+       data. Since it may be called by the memory reclaimer, it
+       should not assume that the original address_space mapping still
+       exists, and it should not block.
+
   direct_IO: called by the generic read/write routines to perform
         direct_IO - that is IO requests which bypass the page cache
         and transfer data directly between the storage and the
index cdd2a6e..8b61c93 100644 (file)
@@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file
        reset_devices   [KNL] Force drivers to reset the underlying device
                        during initialization.
 
-       resource_alloc_from_bottom
-                       Allocate new resources from the beginning of available
-                       space, not the end.  If you need to use this, please
-                       report a bug.
-
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
index 489e9ba..41cc7b3 100644 (file)
@@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       zero)
 
   bool pm_runtime_suspended(struct device *dev);
-    - return true if the device's runtime PM status is 'suspended', or false
-      otherwise
+    - return true if the device's runtime PM status is 'suspended' and its
+      'power.disable_depth' field is equal to zero, or false otherwise
 
   void pm_runtime_allow(struct device *dev);
     - set the power.runtime_auto flag for the device and decrease its usage
index 1a1c27b..6a58887 100644 (file)
@@ -559,14 +559,14 @@ W:        http://maxim.org.za/at91_26.html
 S:     Maintained
 
 ARM/BCMRING ARM ARCHITECTURE
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-bcmring
 
 ARM/BCMRING MTD NAND DRIVER
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
@@ -815,7 +815,7 @@ F:  drivers/mmc/host/msm_sdcc.c
 F:     drivers/mmc/host/msm_sdcc.h
 F:     drivers/serial/msm_serial.h
 F:     drivers/serial/msm_serial.c
-T:     git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git
+T:     git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
 S:     Maintained
 
 ARM/TOSA MACHINE SUPPORT
@@ -5932,7 +5932,6 @@ F:        include/linux/tty.h
 
 TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
-M:     Kyle McMartin <kyle@mcmartin.ca>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/tulip/
@@ -6584,6 +6583,15 @@ F:       include/linux/mfd/wm8400*
 F:     include/sound/wm????.h
 F:     sound/soc/codecs/wm*
 
+WORKQUEUE
+M:     Tejun Heo <tj@kernel.org>
+L:     linux-kernel@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
+S:     Maintained
+F:     include/linux/workqueue.h
+F:     kernel/workqueue.c
+F:     Documentation/workqueue.txt
+
 X.25 NETWORK LAYER
 M:     Andrew Hendry <andrew.hendry@gmail.com>
 L:     linux-x25@vger.kernel.org
index 3d94974..5aa4427 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index f1d9297..d56d21c 100644 (file)
@@ -1311,7 +1311,7 @@ config HZ
 
 config THUMB2_KERNEL
        bool "Compile the kernel in Thumb-2 mode"
-       depends on CPU_V7 && EXPERIMENTAL
+       depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
        select AEABI
        select ARM_ASM_UNIFIED
        help
@@ -1759,7 +1759,7 @@ comment "At least one emulation must be selected"
 
 config FPE_NWFPE
        bool "NWFPE math emulation"
-       depends on !AEABI || OABI_COMPAT
+       depends on (!AEABI || OABI_COMPAT) && !THUMB2_KERNEL
        ---help---
          Say Y to include the NWFPE floating point emulator in the kernel.
          This is necessary to run most binaries. Linux does not currently
index 62d686f..d13add7 100644 (file)
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o board-stamp9g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
index bba5a56..feb6578 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/board.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/stamp9g20.h>
 
 #include "sam9_smc.h"
 #include "generic.h"
 
 static void __init pcontrol_g20_map_io(void)
 {
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
-       at91_register_uart(0, 0, 0);
+       stamp9g20_map_io();
 
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
@@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)
 
        /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
        at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 
@@ -66,38 +60,6 @@ static void __init init_irq(void)
 }
 
 
-/*
- * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
- */
-static struct atmel_nand_data __initdata nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-};
-
-/*
- * Bus timings; unit = 7.57ns
- */
-static struct sam9_smc_config __initdata nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-
 static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .ncs_read_setup         = 16,
        .nrd_setup              = 18,
@@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .tdf_cycles             = 1,
 } };
 
-static void __init add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(3, &nand_smc_config);
-       at91_add_device_nand(&nand_data);
-}
-
-
 static void __init add_device_pcontrol(void)
 {
        /* configure chip-select 4 (IO compatible to 8051  X4 ) */
@@ -155,23 +109,6 @@ static void __init add_device_pcontrol(void)
 }
 
 
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-       },
-};
-#else
-static struct at91_mmc_data __initdata mmc_data = {
-       .wire4          = 1,
-};
-#endif
-
-
 /*
  * USB Host port
  */
@@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
 };
 
 
-/*
- * Dallas 1-Wire  DS2431
- */
-static struct w1_gpio_platform_data w1_gpio_pdata = {
-       .pin            = AT91_PIN_PA29,
-       .is_open_drain  = 1,
-};
-
-static struct platform_device w1_device = {
-       .name                   = "w1-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &w1_gpio_pdata,
-};
-
-static void add_wire1(void)
-{
-       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
-       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
-       platform_device_register(&w1_device);
-}
-
-
 static void __init pcontrol_g20_board_init(void)
 {
-       at91_add_device_serial();
-       add_device_nand();
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-       at91_add_device_mci(0, &mmc_data);
-#else
-       at91_add_device_mmc(0, &mmc_data);
-#endif
+       stamp9g20_board_init();
        at91_add_device_usbh(&usbh_data);
        at91_add_device_eth(&macb_data);
        at91_add_device_i2c(pcontrol_g20_i2c_devices,
                ARRAY_SIZE(pcontrol_g20_i2c_devices));
-       add_wire1();
        add_device_pcontrol();
        at91_add_device_spi(pcontrol_g20_spi_devices,
                ARRAY_SIZE(pcontrol_g20_spi_devices));
index 5206eef..f8902b1 100644 (file)
@@ -32,7 +32,7 @@
 #include "generic.h"
 
 
-static void __init portuxg20_map_io(void)
+void __init stamp9g20_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91sam9260_initialize(18432000);
@@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
 
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+static void __init stamp9g20evb_map_io(void)
+{
+       stamp9g20_map_io();
+
+       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
+                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
+}
+
+static void __init portuxg20_map_io(void)
+{
+       stamp9g20_map_io();
+
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
                                                | ATMEL_UART_DTR | ATMEL_UART_DSR
@@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)
 
        /* USART5 on ttyS6. (Rx, Tx only) */
        at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
-}
-
-static void __init stamp9g20_map_io(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 static void __init init_irq(void)
@@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
 
-static struct at91_udc_data __initdata stamp9g20_udc_data = {
+static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
        .vbus_pin       = AT91_PIN_PA22,
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
@@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {
        }
 };
 
-static struct gpio_led stamp9g20_leds[] = {
+static struct gpio_led stamp9g20evb_leds[] = {
        {
                .name                   = "D8",
                .gpio                   = AT91_PIN_PB18,
@@ -250,7 +248,7 @@ void add_w1(void)
 }
 
 
-static void __init generic_board_init(void)
+void __init stamp9g20_board_init(void)
 {
        /* Serial */
        at91_add_device_serial();
@@ -262,34 +260,40 @@ static void __init generic_board_init(void)
 #else
        at91_add_device_mmc(0, &mmc_data);
 #endif
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
        /* W1 */
        add_w1();
 }
 
 static void __init portuxg20_board_init(void)
 {
-       generic_board_init();
-       /* SPI */
-       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
        at91_add_device_udc(&portuxg20_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
+       /* SPI */
+       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
        /* LEDs */
        at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
 }
 
-static void __init stamp9g20_board_init(void)
+static void __init stamp9g20evb_board_init(void)
 {
-       generic_board_init();
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
-       at91_add_device_udc(&stamp9g20_udc_data);
+       at91_add_device_udc(&stamp9g20evb_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
        /* LEDs */
-       at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds));
+       at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
 }
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
@@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
-       .map_io         = stamp9g20_map_io,
+       .map_io         = stamp9g20evb_map_io,
        .init_irq       = init_irq,
-       .init_machine   = stamp9g20_board_init,
+       .init_machine   = stamp9g20evb_board_init,
 MACHINE_END
index 7525cee..9113da6 100644 (file)
@@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
        /* Now set uhpck values */
        uhpck.parent = &utmi_clk;
        uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-       uhpck.rate_hz = utmi_clk.parent->rate_hz;
+       uhpck.rate_hz = utmi_clk.rate_hz;
        uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h
new file mode 100644 (file)
index 0000000..6120f9c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __MACH_STAMP9G20_H
+#define __MACH_STAMP9G20_H
+
+void stamp9g20_map_io(void);
+void stamp9g20_board_init(void);
+
+#endif
index daf3993..2e3dd08 100644 (file)
@@ -126,7 +126,6 @@ static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
 static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
 static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
 static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
-static APBC_CLK(rtc, MMP2_RTC, 0, 32768);
 
 static APMU_CLK(nand, NAND, 0xbf, 100000000);
 
index 86c9b21..9db9203 100644 (file)
@@ -216,7 +216,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "wl1271",
                .mmc            = 3,
-               .caps           = MMC_CAP_4_BIT_DATA,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
                .gpio_wp        = -EINVAL,
                .gpio_cd        = -EINVAL,
                .nonremovable   = true,
index 40562dd..a1939b1 100644 (file)
@@ -297,7 +297,7 @@ static int __init _omap2_init_reprogram_sdrc(void)
                return 0;
 
        dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
-       if (!dpll3_m2_ck)
+       if (IS_ERR(dpll3_m2_ck))
                return -EINVAL;
 
        rate = clk_get_rate(dpll3_m2_ck);
index 5e81517..a8afb61 100644 (file)
@@ -161,6 +161,23 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
                printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -354,23 +371,6 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
-void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
index c85923e..aaeea49 100644 (file)
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 static void (*omap2_sram_idle)(void);
 static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
                                  void __iomem *sdrc_power);
@@ -120,8 +133,9 @@ static void omap2_enter_full_retention(void)
                goto no_sleep;
 
        /* Block console output in case it is on one of the OMAP UARTs */
-       if (try_acquire_console_sem())
-               goto no_sleep;
+       if (!is_suspending())
+               if (try_acquire_console_sem())
+                       goto no_sleep;
 
        omap_uart_prepare_idle(0);
        omap_uart_prepare_idle(1);
@@ -136,7 +150,8 @@ static void omap2_enter_full_retention(void)
        omap_uart_resume_idle(1);
        omap_uart_resume_idle(0);
 
-       release_console_sem();
+       if (!is_suspending())
+               release_console_sem();
 
 no_sleep:
        if (omap2_pm_debug) {
@@ -284,6 +299,12 @@ out:
        local_irq_enable();
 }
 
+static int omap2_pm_begin(suspend_state_t state)
+{
+       suspend_state = state;
+       return 0;
+}
+
 static int omap2_pm_prepare(void)
 {
        /* We cannot sleep in idle until we have resumed */
@@ -333,10 +354,17 @@ static void omap2_pm_finish(void)
        enable_hlt();
 }
 
+static void omap2_pm_end(void)
+{
+       suspend_state = PM_SUSPEND_ON;
+}
+
 static struct platform_suspend_ops omap_pm_ops = {
+       .begin          = omap2_pm_begin,
        .prepare        = omap2_pm_prepare,
        .enter          = omap2_pm_enter,
        .finish         = omap2_pm_finish,
+       .end            = omap2_pm_end,
        .valid          = suspend_valid_only_mem,
 };
 
index 0ec8a04..648b8c5 100644 (file)
 #include "sdrc.h"
 #include "control.h"
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 /* Scratchpad offsets */
 #define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
 #define OMAP343X_TABLE_VALUE_OFFSET       0xc0
@@ -387,10 +400,11 @@ void omap_sram_idle(void)
        }
 
        /* Block console output in case it is on one of the OMAP UARTs */
-       if (per_next_state < PWRDM_POWER_ON ||
-           core_next_state < PWRDM_POWER_ON)
-               if (try_acquire_console_sem())
-                       goto console_still_active;
+       if (!is_suspending())
+               if (per_next_state < PWRDM_POWER_ON ||
+                   core_next_state < PWRDM_POWER_ON)
+                       if (try_acquire_console_sem())
+                               goto console_still_active;
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
@@ -470,7 +484,8 @@ void omap_sram_idle(void)
                omap_uart_resume_idle(3);
        }
 
-       release_console_sem();
+       if (!is_suspending())
+               release_console_sem();
 
 console_still_active:
        /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -514,8 +529,6 @@ out:
 }
 
 #ifdef CONFIG_SUSPEND
-static suspend_state_t suspend_state;
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
index 298a22a..f81acee 100644 (file)
 #define OMAP24XX_EN_GPT1_MASK                          (1 << 0)
 
 /* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
-#define OMAP24XX_ST_GPIOS_SHIFT                                (1 << 2)
-#define OMAP24XX_ST_GPIOS_MASK                         2
-#define OMAP24XX_ST_GPT1_SHIFT                         (1 << 0)
-#define OMAP24XX_ST_GPT1_MASK                          0
+#define OMAP24XX_ST_GPIOS_SHIFT                                2
+#define OMAP24XX_ST_GPIOS_MASK                         (1 << 2)
+#define OMAP24XX_ST_GPT1_SHIFT                         0
+#define OMAP24XX_ST_GPT1_MASK                          (1 << 0)
 
 /* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
-#define OMAP2430_ST_MDM_SHIFT                          (1 << 0)
+#define OMAP2430_ST_MDM_SHIFT                          0
+#define OMAP2430_ST_MDM_MASK                           (1 << 0)
 
 
 /* 3430 register bits shared between CM & PRM registers */
index d2060a1..e5c9932 100644 (file)
@@ -241,7 +241,8 @@ static inline void palmtx_keys_init(void) {}
 /******************************************************************************
  * NAND Flash
  ******************************************************************************/
-#if defined(CONFIG_MTD_NAND_GPIO) || defined(CONFIG_MTD_NAND_GPIO_MODULE)
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+       defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
                                 unsigned int ctrl)
 {
index 99fa688..c96fa1b 100644 (file)
@@ -203,6 +203,10 @@ ENTRY(v6_flush_kern_dcache_area)
  *     - end     - virtual end address of region
  */
 v6_dma_inv_range:
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrb    r2, [r0]                        @ read for ownership
+       strb    r2, [r0]                        @ write for ownership
+#endif
        tst     r0, #D_CACHE_LINE_SIZE - 1
        bic     r0, r0, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
@@ -211,6 +215,10 @@ v6_dma_inv_range:
        mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
 #endif
        tst     r1, #D_CACHE_LINE_SIZE - 1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrneb  r2, [r1, #-1]                   @ read for ownership
+       strneb  r2, [r1, #-1]                   @ write for ownership
+#endif
        bic     r1, r1, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
        mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
@@ -218,10 +226,6 @@ v6_dma_inv_range:
        mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
 #endif
 1:
-#ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
-#endif
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
 #else
@@ -229,6 +233,10 @@ v6_dma_inv_range:
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlo   r2, [r0]                        @ read for ownership
+       strlo   r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
@@ -263,12 +271,12 @@ v6_dma_clean_range:
  *     - end     - virtual end address of region
  */
 ENTRY(v6_dma_flush_range)
-       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
-1:
 #ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
+       ldrb    r2, [r0]                @ read for ownership
+       strb    r2, [r0]                @ write for ownership
 #endif
+       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
+1:
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
 #else
@@ -276,6 +284,10 @@ ENTRY(v6_dma_flush_range)
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlob  r2, [r0]                        @ read for ownership
+       strlob  r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
index a3ebf7a..6136e68 100644 (file)
@@ -173,15 +173,22 @@ ENTRY(v7_coherent_user_range)
  UNWIND(.fnstart               )
        dcache_line_size r2, r3
        sub     r3, r2, #1
-       bic     r0, r0, r3
+       bic     r12, r0, r3
 1:
- USER( mcr     p15, 0, r0, c7, c11, 1  )       @ clean D line to the point of unification
+ USER( mcr     p15, 0, r12, c7, c11, 1 )       @ clean D line to the point of unification
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     1b
        dsb
- USER( mcr     p15, 0, r0, c7, c5, 1   )       @ invalidate I line
-       add     r0, r0, r2
+       icache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r12, r0, r3
 2:
-       cmp     r0, r1
-       blo     1b
+ USER( mcr     p15, 0, r12, c7, c5, 1  )       @ invalidate I line
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     2b
+3:
        mov     r0, #0
        ALT_SMP(mcr     p15, 0, r0, c7, c1, 6)  @ invalidate BTB Inner Shareable
        ALT_UP(mcr      p15, 0, r0, c7, c5, 6)  @ invalidate BTB
@@ -194,10 +201,10 @@ ENTRY(v7_coherent_user_range)
  * isn't mapped, just try the next page.
  */
 9001:
-       mov     r0, r0, lsr #12
-       mov     r0, r0, lsl #12
-       add     r0, r0, #4096
-       b       2b
+       mov     r12, r12, lsr #12
+       mov     r12, r12, lsl #12
+       add     r12, r12, #4096
+       b       3b
  UNWIND(.fnend         )
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
index 7d63bea..b795afd 100644 (file)
        .endm
 
 /*
- * cache_line_size - get the cache line size from the CSIDR register
- * (available on ARMv7+). It assumes that the CSSR register was configured
- * to access the L1 data cache CSIDR.
+ * dcache_line_size - get the minimum D-cache line size from the CTR register
+ * on ARMv7.
  */
        .macro  dcache_line_size, reg, tmp
-       mrc     p15, 1, \tmp, c0, c0, 0         @ read CSIDR
-       and     \tmp, \tmp, #7                  @ cache line size encoding
-       mov     \reg, #16                       @ size offset
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       lsr     \tmp, \tmp, #16
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
        mov     \reg, \reg, lsl \tmp            @ actual cache line size
        .endm
 
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register
+ * on ARMv7.
+ */
+       .macro  icache_line_size, reg, tmp
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
+       mov     \reg, \reg, lsl \tmp            @ actual cache line size
+       .endm
 
 /*
  * Sanity check the PTE configuration for the code below - which makes
index 155fe43..8722a13 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <plat/common.h>
 #include <plat/board.h>
@@ -164,7 +165,7 @@ static int __init omap_init_clocksource_32k(void)
                        return -ENODEV;
 
                sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-               if (sync_32k_ick)
+               if (!IS_ERR(sync_32k_ick))
                        clk_enable(sync_32k_ick);
 
                clocksource_32k.mult = clocksource_hz2mult(32768,
index e2c8eeb..74dac41 100644 (file)
@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void)
                     cpu_is_omap1710())
                        omap_sram_size = 0x4000;        /* 16K */
                else if (cpu_is_omap1611())
-                       omap_sram_size = 0x3e800;       /* 250K */
+                       omap_sram_size = SZ_256K;
                else {
                        printk(KERN_ERR "Could not detect SRAM size\n");
                        omap_sram_size = 0x4000;
index 55590a4..2fea897 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Thu Sep 9 22:43:01 2010
+# Last update: Sun Dec 12 23:24:27 2010
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -2321,7 +2321,7 @@ mx31txtr          MACH_MX31TXTR           MX31TXTR                2332
 u380                   MACH_U380               U380                    2333
 oamp3_hualu            MACH_HUALU_BOARD        HUALU_BOARD             2334
 npcmx50                        MACH_NPCMX50            NPCMX50                 2335
-mx51_lange51           MACH_MX51_LANGE51       MX51_LANGE51            2336
+mx51_efikamx           MACH_MX51_EFIKAMX       MX51_EFIKAMX            2336
 mx51_lange52           MACH_MX51_LANGE52       MX51_LANGE52            2337
 riom                   MACH_RIOM               RIOM                    2338
 comcas                 MACH_COMCAS             COMCAS                  2339
@@ -2355,7 +2355,7 @@ at91sam9263cs             MACH_AT91SAM9263CS      AT91SAM9263CS           2366
 csb732                 MACH_CSB732             CSB732                  2367
 u8500                  MACH_U8500              U8500                   2368
 huqiu                  MACH_HUQIU              HUQIU                   2369
-mx51_kunlun            MACH_MX51_KUNLUN        MX51_KUNLUN             2370
+mx51_efikasb           MACH_MX51_EFIKASB       MX51_EFIKASB            2370
 pmt1g                  MACH_PMT1G              PMT1G                   2371
 htcelf                 MACH_HTCELF             HTCELF                  2372
 armadillo420           MACH_ARMADILLO420       ARMADILLO420            2373
@@ -2971,7 +2971,7 @@ premierwave_en            MACH_PREMIERWAVE_EN     PREMIERWAVE_EN          2985
 wasabi                 MACH_WASABI             WASABI                  2986
 vivow                  MACH_VIVOW              VIVOW                   2987
 mx50_rdp               MACH_MX50_RDP           MX50_RDP                2988
-universal              MACH_UNIVERSAL          UNIVERSAL               2989
+universal_c210         MACH_UNIVERSAL_C210     UNIVERSAL_C210          2989
 real6410               MACH_REAL6410           REAL6410                2990
 spx_sakura             MACH_SPX_SAKURA         SPX_SAKURA              2991
 ij3k_2440              MACH_IJ3K_2440          IJ3K_2440               2992
@@ -3044,3 +3044,178 @@ harvest_desoto          MACH_HARVEST_DESOTO     HARVEST_DESOTO          3059
 msm8x60_qrdc           MACH_MSM8X60_QRDC       MSM8X60_QRDC            3060
 spear900               MACH_SPEAR900           SPEAR900                3061
 pcontrol_g20           MACH_PCONTROL_G20       PCONTROL_G20            3062
+rdstor                 MACH_RDSTOR             RDSTOR                  3063
+usdloader              MACH_USDLOADER          USDLOADER               3064
+tsoploader             MACH_TSOPLOADER         TSOPLOADER              3065
+kronos                 MACH_KRONOS             KRONOS                  3066
+ffcore                 MACH_FFCORE             FFCORE                  3067
+mone                   MACH_MONE               MONE                    3068
+unit2s                 MACH_UNIT2S             UNIT2S                  3069
+acer_a5                        MACH_ACER_A5            ACER_A5                 3070
+etherpro_isp           MACH_ETHERPRO_ISP       ETHERPRO_ISP            3071
+stretchs7000           MACH_STRETCHS7000       STRETCHS7000            3072
+p87_smartsim           MACH_P87_SMARTSIM       P87_SMARTSIM            3073
+tulip                  MACH_TULIP              TULIP                   3074
+sunflower              MACH_SUNFLOWER          SUNFLOWER               3075
+rib                    MACH_RIB                RIB                     3076
+clod                   MACH_CLOD               CLOD                    3077
+rump                   MACH_RUMP               RUMP                    3078
+tenderloin             MACH_TENDERLOIN         TENDERLOIN              3079
+shortloin              MACH_SHORTLOIN          SHORTLOIN               3080
+crespo                 MACH_CRESPO             CRESPO                  3081
+antares                        MACH_ANTARES            ANTARES                 3082
+wb40n                  MACH_WB40N              WB40N                   3083
+herring                        MACH_HERRING            HERRING                 3084
+naxy400                        MACH_NAXY400            NAXY400                 3085
+naxy1200               MACH_NAXY1200           NAXY1200                3086
+vpr200                 MACH_VPR200             VPR200                  3087
+bug20                  MACH_BUG20              BUG20                   3088
+goflexnet              MACH_GOFLEXNET          GOFLEXNET               3089
+torbreck               MACH_TORBRECK           TORBRECK                3090
+saarb_mg1              MACH_SAARB_MG1          SAARB_MG1               3091
+callisto               MACH_CALLISTO           CALLISTO                3092
+multhsu                        MACH_MULTHSU            MULTHSU                 3093
+saluda                 MACH_SALUDA             SALUDA                  3094
+pemp_omap3_apollo      MACH_PEMP_OMAP3_APOLLO  PEMP_OMAP3_APOLLO       3095
+vc0718                 MACH_VC0718             VC0718                  3096
+mvblx                  MACH_MVBLX              MVBLX                   3097
+inhand_apeiron         MACH_INHAND_APEIRON     INHAND_APEIRON          3098
+inhand_fury            MACH_INHAND_FURY        INHAND_FURY             3099
+inhand_siren           MACH_INHAND_SIREN       INHAND_SIREN            3100
+hdnvp                  MACH_HDNVP              HDNVP                   3101
+softwinner             MACH_SOFTWINNER         SOFTWINNER              3102
+prima2_evb             MACH_PRIMA2_EVB         PRIMA2_EVB              3103
+nas6210                        MACH_NAS6210            NAS6210                 3104
+unisdev                        MACH_UNISDEV            UNISDEV                 3105
+sbca11                 MACH_SBCA11             SBCA11                  3106
+saga                   MACH_SAGA               SAGA                    3107
+ns_k330                        MACH_NS_K330            NS_K330                 3108
+tanna                  MACH_TANNA              TANNA                   3109
+imate8502              MACH_IMATE8502          IMATE8502               3110
+aspen                  MACH_ASPEN              ASPEN                   3111
+daintree_cwac          MACH_DAINTREE_CWAC      DAINTREE_CWAC           3112
+zmx25                  MACH_ZMX25              ZMX25                   3113
+maple1                 MACH_MAPLE1             MAPLE1                  3114
+qsd8x72_surf           MACH_QSD8X72_SURF       QSD8X72_SURF            3115
+qsd8x72_ffa            MACH_QSD8X72_FFA        QSD8X72_FFA             3116
+abilene                        MACH_ABILENE            ABILENE                 3117
+eigen_ttr              MACH_EIGEN_TTR          EIGEN_TTR               3118
+iomega_ix2_200         MACH_IOMEGA_IX2_200     IOMEGA_IX2_200          3119
+coretec_vcx7400                MACH_CORETEC_VCX7400    CORETEC_VCX7400         3120
+santiago               MACH_SANTIAGO           SANTIAGO                3121
+mx257sol               MACH_MX257SOL           MX257SOL                3122
+strasbourg             MACH_STRASBOURG         STRASBOURG              3123
+msm8x60_fluid          MACH_MSM8X60_FLUID      MSM8X60_FLUID           3124
+smartqv5               MACH_SMARTQV5           SMARTQV5                3125
+smartqv3               MACH_SMARTQV3           SMARTQV3                3126
+smartqv7               MACH_SMARTQV7           SMARTQV7                3127
+paz00                  MACH_PAZ00              PAZ00                   3128
+acmenetusfoxg20                MACH_ACMENETUSFOXG20    ACMENETUSFOXG20         3129
+htcwillow              MACH_HTCWILLOW          HTCWILLOW               3130
+fwbd_0404              MACH_FWBD_0404          FWBD_0404               3131
+hdgu                   MACH_HDGU               HDGU                    3132
+pyramid                        MACH_PYRAMID            PYRAMID                 3133
+epiphan                        MACH_EPIPHAN            EPIPHAN                 3134
+omap_bender            MACH_OMAP_BENDER        OMAP_BENDER             3135
+gurnard                        MACH_GURNARD            GURNARD                 3136
+gtl_it5100             MACH_GTL_IT5100         GTL_IT5100              3137
+bcm2708                        MACH_BCM2708            BCM2708                 3138
+mx51_ggc               MACH_MX51_GGC           MX51_GGC                3139
+sharespace             MACH_SHARESPACE         SHARESPACE              3140
+haba_knx_explorer      MACH_HABA_KNX_EXPLORER  HABA_KNX_EXPLORER       3141
+simtec_kirkmod         MACH_SIMTEC_KIRKMOD     SIMTEC_KIRKMOD          3142
+crux                   MACH_CRUX               CRUX                    3143
+mx51_bravo             MACH_MX51_BRAVO         MX51_BRAVO              3144
+charon                 MACH_CHARON             CHARON                  3145
+picocom3               MACH_PICOCOM3           PICOCOM3                3146
+picocom4               MACH_PICOCOM4           PICOCOM4                3147
+serrano                        MACH_SERRANO            SERRANO                 3148
+doubleshot             MACH_DOUBLESHOT         DOUBLESHOT              3149
+evsy                   MACH_EVSY               EVSY                    3150
+huashan                        MACH_HUASHAN            HUASHAN                 3151
+lausanne               MACH_LAUSANNE           LAUSANNE                3152
+emerald                        MACH_EMERALD            EMERALD                 3153
+tqma35                 MACH_TQMA35             TQMA35                  3154
+marvel                 MACH_MARVEL             MARVEL                  3155
+manuae                 MACH_MANUAE             MANUAE                  3156
+chacha                 MACH_CHACHA             CHACHA                  3157
+lemon                  MACH_LEMON              LEMON                   3158
+csc                    MACH_CSC                CSC                     3159
+gira_knxip_router      MACH_GIRA_KNXIP_ROUTER  GIRA_KNXIP_ROUTER       3160
+t20                    MACH_T20                T20                     3161
+hdmini                 MACH_HDMINI             HDMINI                  3162
+sciphone_g2            MACH_SCIPHONE_G2        SCIPHONE_G2             3163
+express                        MACH_EXPRESS            EXPRESS                 3164
+express_kt             MACH_EXPRESS_KT         EXPRESS_KT              3165
+maximasp               MACH_MAXIMASP           MAXIMASP                3166
+nitrogen_imx51         MACH_NITROGEN_IMX51     NITROGEN_IMX51          3167
+nitrogen_imx53         MACH_NITROGEN_IMX53     NITROGEN_IMX53          3168
+sunfire                        MACH_SUNFIRE            SUNFIRE                 3169
+arowana                        MACH_AROWANA            AROWANA                 3170
+tegra_daytona          MACH_TEGRA_DAYTONA      TEGRA_DAYTONA           3171
+tegra_swordfish                MACH_TEGRA_SWORDFISH    TEGRA_SWORDFISH         3172
+edison                 MACH_EDISON             EDISON                  3173
+svp8500v1              MACH_SVP8500V1          SVP8500V1               3174
+svp8500v2              MACH_SVP8500V2          SVP8500V2               3175
+svp5500                        MACH_SVP5500            SVP5500                 3176
+b5500                  MACH_B5500              B5500                   3177
+s5500                  MACH_S5500              S5500                   3178
+icon                   MACH_ICON               ICON                    3179
+elephant               MACH_ELEPHANT           ELEPHANT                3180
+msm8x60_fusion         MACH_MSM8X60_FUSION     MSM8X60_FUSION          3181
+shooter                        MACH_SHOOTER            SHOOTER                 3182
+spade_lte              MACH_SPADE_LTE          SPADE_LTE               3183
+philhwani              MACH_PHILHWANI          PHILHWANI               3184
+gsncomm                        MACH_GSNCOMM            GSNCOMM                 3185
+strasbourg_a2          MACH_STRASBOURG_A2      STRASBOURG_A2           3186
+mmm                    MACH_MMM                MMM                     3187
+davinci_dm365_bv       MACH_DAVINCI_DM365_BV   DAVINCI_DM365_BV        3188
+ag5evm                 MACH_AG5EVM             AG5EVM                  3189
+sc575plc               MACH_SC575PLC           SC575PLC                3190
+sc575hmi               MACH_SC575IPC           SC575IPC                3191
+omap3_tdm3730          MACH_OMAP3_TDM3730      OMAP3_TDM3730           3192
+g7                     MACH_G7                 G7                      3193
+top9000_eval           MACH_TOP9000_EVAL       TOP9000_EVAL            3194
+top9000_su             MACH_TOP9000_SU         TOP9000_SU              3195
+utm300                 MACH_UTM300             UTM300                  3196
+tsunagi                        MACH_TSUNAGI            TSUNAGI                 3197
+ts75xx                 MACH_TS75XX             TS75XX                  3198
+msm8x60_fusn_ffa       MACH_MSM8X60_FUSN_FFA   MSM8X60_FUSN_FFA        3199
+ts47xx                 MACH_TS47XX             TS47XX                  3200
+da850_k5               MACH_DA850_K5           DA850_K5                3201
+ax502                  MACH_AX502              AX502                   3202
+igep0032               MACH_IGEP0032           IGEP0032                3203
+antero                 MACH_ANTERO             ANTERO                  3204
+synergy                        MACH_SYNERGY            SYNERGY                 3205
+ics_if_voip            MACH_ICS_IF_VOIP        ICS_IF_VOIP             3206
+wlf_cragg_6410         MACH_WLF_CRAGG_6410     WLF_CRAGG_6410          3207
+punica                 MACH_PUNICA             PUNICA                  3208
+sbc_nt250              MACH_SBC_NT250          SBC_NT250               3209
+mx27_wmultra           MACH_MX27_WMULTRA       MX27_WMULTRA            3210
+mackerel               MACH_MACKEREL           MACKEREL                3211
+fa9x27                 MACH_FA9X27             FA9X27                  3213
+ns2816tb               MACH_NS2816TB           NS2816TB                3214
+ns2816_ntpad           MACH_NS2816_NTPAD       NS2816_NTPAD            3215
+ns2816_ntnb            MACH_NS2816_NTNB        NS2816_NTNB             3216
+kaen                   MACH_KAEN               KAEN                    3217
+nv1000                 MACH_NV1000             NV1000                  3218
+nuc950ts               MACH_NUC950TS           NUC950TS                3219
+nokia_rm680            MACH_NOKIA_RM680        NOKIA_RM680             3220
+ast2200                        MACH_AST2200            AST2200                 3221
+lead                   MACH_LEAD               LEAD                    3222
+unino1                 MACH_UNINO1             UNINO1                  3223
+greeco                 MACH_GREECO             GREECO                  3224
+verdi                  MACH_VERDI              VERDI                   3225
+dm6446_adbox           MACH_DM6446_ADBOX       DM6446_ADBOX            3226
+quad_salsa             MACH_QUAD_SALSA         QUAD_SALSA              3227
+abb_gma_1_1            MACH_ABB_GMA_1_1        ABB_GMA_1_1             3228
+svcid                  MACH_SVCID              SVCID                   3229
+msm8960_sim            MACH_MSM8960_SIM        MSM8960_SIM             3230
+msm8960_rumi3          MACH_MSM8960_RUMI3      MSM8960_RUMI3           3231
+icon_g                 MACH_ICON_G             ICON_G                  3232
+mb3                    MACH_MB3                MB3                     3233
+gsia18s                        MACH_GSIA18S            GSIA18S                 3234
+pivicc                 MACH_PIVICC             PIVICC                  3235
+pcm048                 MACH_PCM048             PCM048                  3236
+dds                    MACH_DDS                DDS                     3237
+chalten_xa1            MACH_CHALTEN_XA1        CHALTEN_XA1             3238
index 67a2fa2..0a9b5b8 100644 (file)
@@ -19,6 +19,8 @@ config MIPS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_PROBE
 
 menu "Machine selection"
 
@@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB
 
 endchoice
 
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       range 11 64
+       default "11"
+       help
+         The kernel memory allocator divides physically contiguous memory
+         blocks into "zones", where each zone is a power of two number of
+         pages.  This option selects the largest power of two that the kernel
+         keeps in the memory allocator.  If you need to allocate very large
+         blocks of physically contiguous memory, then you may need to
+         increase this value.
+
+         This config option is actually maximum order plus one. For example,
+         a value of 11 means that the largest free memory block is 2^10 pages.
+
+         The page size is not necessarily 4KB.  Keep this in mind
+         when choosing a value for this option.
+
 config BOARD_SCACHE
        bool
 
@@ -1921,20 +1945,6 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
        bool
 
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-       bool
-       default y
-
-config GENERIC_IRQ_PROBE
-       bool
-       default y
-
-config IRQ_PER_CPU
-       bool
-
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
index 3691630..9e7814d 100644 (file)
@@ -27,6 +27,7 @@
 static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                            unsigned int old_state)
 {
+#ifdef CONFIG_SERIAL_8250
        switch (state) {
        case 0:
                if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
@@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                serial8250_do_pm(port, state, old_state);
                break;
        }
+#endif
 }
 
 #define PORT(_base, _irq)                                      \
index b30df5c..baeb213 100644 (file)
@@ -54,10 +54,9 @@ void __init prom_init(void)
 
        prom_init_cmdline();
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
                memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
+
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index fc0e715..2ca4ada 100644 (file)
@@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
        calculate(base_clock, frequency, &prediv, &postdiv, &mul);
 
        writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
-       msleep(1);
+       mdelay(1);
        writel(4, &clock->pll);
        while (readl(&clock->pll) & PLL_STATUS)
                ;
        writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
-       msleep(75);
+       mdelay(75);
 }
 
 static void __init tnetd7300_init_clocks(void)
@@ -456,7 +456,7 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-int __init ar7_init_clocks(void)
+void __init ar7_init_clocks(void)
 {
        switch (ar7_chip_id()) {
        case AR7_CHIP_7100:
@@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)
        }
        /* adjust vbus clock rate */
        vbus_clk.rate = bus_clk.rate / 2;
-
-       return 0;
 }
-arch_initcall(ar7_init_clocks);
index 5fb8a01..22c9321 100644 (file)
@@ -30,6 +30,9 @@ void __init plat_time_init(void)
 {
        struct clk *cpu_clk;
 
+       /* Initialize ar7 clocks so the CPU clock frequency is correct */
+       ar7_init_clocks();
+
        cpu_clk = clk_get(NULL, "cpu");
        if (IS_ERR(cpu_clk)) {
                printk(KERN_ERR "unable to get cpu clock\n");
index b1aee33..c95f90b 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <asm/fw/cfe/cfe_api.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
 struct ssb_bus ssb_bcm47xx;
@@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)
                cpu_relax();
 }
 
-static void str2eaddr(char *str, char *dest)
-{
-       int i = 0;
+#define READ_FROM_NVRAM(_outvar, name, buf) \
+       if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
 
-       if (str == NULL) {
-               memset(dest, 0, 6);
-               return;
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+       char buf[100];
+       u32 boardflags;
+
+       memset(sprom, 0, sizeof(struct ssb_sprom));
+
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+       if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+       if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+       READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
+       READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
+       READ_FROM_NVRAM(board_rev, "boardrev", buf);
+       READ_FROM_NVRAM(country_code, "ccode", buf);
+       READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
+       READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
+       READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
+       READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
+       READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
+       READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
+       READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
+       READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
+       READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
+       READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
+       READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+       READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+       READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+       READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+       READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+       READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+       READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+       READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+       READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
+       READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
+       READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
+       READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
+       READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+       READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+       READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+
+       if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
-
-       for (;;) {
-               dest[i++] = (char) simple_strtoul(str, NULL, 16);
-               str += 2;
-               if (!*str++ || i == 6)
-                       break;
+       if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
 }
 
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                   struct ssb_init_invariants *iv)
 {
-       char buf[100];
+       char buf[20];
 
        /* Fill boardinfo structure */
        memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
 
-       if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
-               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
+       else
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+       if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
                iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
-       /* Fill sprom structure */
-       memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
-       iv->sprom.revision = 3;
-
-       if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et0mac);
+       bcm47xx_fill_sprom(&iv->sprom);
 
-       if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et1mac);
-
-       if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
-       if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
 
        return 0;
 }
@@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 void __init plat_mem_setup(void)
 {
        int err;
+       char buf[100];
+       struct ssb_mipscore *mcore;
 
        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
                                      bcm47xx_get_invariants);
        if (err)
                panic("Failed to initialize SSB bus (err %d)\n", err);
 
+       mcore = &ssb_bcm47xx.mipscore;
+       if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+               if (strstr(buf, "console=ttyS1")) {
+                       struct ssb_serial_port port;
+
+                       printk(KERN_DEBUG "Swapping serial ports!\n");
+                       /* swap serial ports */
+                       memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+                       memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
+                              sizeof(port));
+                       memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+               }
+       }
+
        _machine_restart = bcm47xx_machine_restart;
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
index 06d59dc..8687753 100644 (file)
  * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
  */
 
-#define PRID_IMP_BMIPS4KC      0x4000
-#define PRID_IMP_BMIPS32       0x8000
+#define PRID_IMP_BMIPS32_REV4  0x4000
+#define PRID_IMP_BMIPS32_REV8  0x8000
 #define PRID_IMP_BMIPS3300     0x9000
 #define PRID_IMP_BMIPS3300_ALT 0x9100
 #define PRID_IMP_BMIPS3300_BUG 0x0000
index fd1d39e..455c0ac 100644 (file)
@@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
-       set_personality(PER_LINUX);                                     \
+       if (personality(current->personality) != PER_LINUX)             \
+               set_personality(PER_LINUX);                             \
                                                                        \
        current->thread.abi = &mips_abi;                                \
 } while (0)
@@ -296,6 +297,8 @@ do {                                                                        \
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
+       unsigned int p;                                                 \
+                                                                       \
        clear_thread_flag(TIF_32BIT_REGS);                              \
        clear_thread_flag(TIF_32BIT_ADDR);                              \
                                                                        \
@@ -304,7 +307,8 @@ do {                                                                        \
        else                                                            \
                current->thread.abi = &mips_abi;                        \
                                                                        \
-       if (current->personality != PER_LINUX32)                        \
+       p = personality(current->personality);                          \
+       if (p != PER_LINUX32 && p != PER_LINUX)                         \
                set_personality(PER_LINUX);                             \
 } while (0)
 
index c98bf51..5b017f2 100644 (file)
@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,                             \
                        "dsrl32 %L0, %L0, 0"                    "\n\t"  \
                        "dsll32 %M0, %M0, 0"                    "\n\t"  \
                        "or     %L0, %L0, %M0"                  "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "sd     %L0, %2"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__tmp)                                  \
-                       : "0" (__val), "m" (*__mem));                   \
+                       : "0" (__val), "R" (*__mem));                   \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else                                                          \
@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)      \
                        local_irq_save(__flags);                        \
                __asm__ __volatile__(                                   \
                        ".set   mips3"          "\t\t# __readq" "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "ld     %L0, %1"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        "dsra32 %M0, %L0, 0"                    "\n\t"  \
                        "sll    %L0, %L0, 0"                    "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__val)                                  \
-                       : "m" (*__mem));                                \
+                       : "R" (*__mem));                                \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else {                                                        \
index 7919d76..07d3fad 100644 (file)
@@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)
 }
 
 int __init ar7_gpio_init(void);
-
-int __init ar7_gpio_init(void);
+void __init ar7_init_clocks(void);
 
 #endif /* __AR7_H__ */
index c58ebd8..9759588 100644 (file)
@@ -12,6 +12,7 @@
 #define __NVRAM_H
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 
 struct nvram_header {
        u32 magic;
@@ -36,4 +37,10 @@ struct nvram_header {
 
 extern int nvram_getenv(char *name, char *val, size_t val_len);
 
+static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+{
+       sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1],
+              &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]);
+}
+
 #endif
index 5742bb4..5c0a357 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2009 Qi Hardware inc.,
  * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
- * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de>
+ * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or later
@@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {
        QI_LB60_GPIO_KEYIN(3),
        QI_LB60_GPIO_KEYIN(4),
        QI_LB60_GPIO_KEYIN(5),
-       QI_LB60_GPIO_KEYIN(7),
+       QI_LB60_GPIO_KEYIN(6),
        QI_LB60_GPIO_KEYIN8,
 };
 
index 95bc2b5..1cc9e54 100644 (file)
@@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {
 
 /* PCM */
 struct platform_device jz4740_pcm_device = {
-       .name           = "jz4740-pcm",
+       .name           = "jz4740-pcm-audio",
        .id             = -1,
 };
 
index cfeac15..4a70407 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/bootinfo.h>
 #include <asm/mach-jz4740/base.h>
 
-void jz4740_init_cmdline(int argc, char *argv[])
+static __init void jz4740_init_cmdline(int argc, char *argv[])
 {
        unsigned int count = COMMAND_LINE_SIZE - 1;
        int i;
index 2f4d7a9..98c5a97 100644 (file)
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,
        cnt = read_c0_count();
        cnt += delta;
        write_c0_compare(cnt);
-       res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+       res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;
        return res;
 }
 
index 71620e1..68dae7b 100644 (file)
@@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
        switch (c->processor_id & 0xff00) {
-       case PRID_IMP_BMIPS32:
+       case PRID_IMP_BMIPS32_REV4:
+       case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
                __cpu_name[cpu] = "Broadcom BMIPS32";
                break;
@@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                __cpu_name[cpu] = "Broadcom BMIPS5000";
                c->options |= MIPS_CPU_ULRI;
                break;
-       case PRID_IMP_BMIPS4KC:
-               c->cputype = CPU_4KC;
-               __cpu_name[cpu] = "MIPS 4Kc";
-               break;
        }
 }
 
index 6343b4a..876a75c 100644 (file)
@@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
 
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
+       unsigned int p = personality & 0xffffffff;
        int ret;
-       personality &= 0xffffffff;
+
        if (personality(current->personality) == PER_LINUX32 &&
-           personality == PER_LINUX)
-               personality = PER_LINUX32;
-       ret = sys_personality(personality);
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
+           personality(p) == PER_LINUX)
+               p = (p & ~PER_MASK) | PER_LINUX32;
+       ret = sys_personality(p);
+       if (ret != -1 && personality(ret) == PER_LINUX32)
+               ret = (ret & ~PER_MASK) | PER_LINUX;
        return ret;
 }
 
index 9996094..ae167df 100644 (file)
@@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->regs[7] = 0; /* Clear error flag */
 
        childregs->regs[2] = 0; /* Child gets zero as return value */
-       regs->regs[2] = p->pid;
 
        if (childregs->cp0_status & ST0_CU0) {
                childregs->regs[28] = (unsigned long) ti;
index e000b27..9dbe583 100644 (file)
@@ -100,7 +100,7 @@ void __init device_tree_init(void)
                return;
 
        base = virt_to_phys((void *)initial_boot_params);
-       size = initial_boot_params->totalsize;
+       size = be32_to_cpu(initial_boot_params->totalsize);
 
        /* Before we do anything, lets reserve the dt blob */
        reserve_mem_mach(base, size);
index 43e7cdc..c0e8141 100644 (file)
@@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)
 {
        extern int gic_present;
 
-       /* This is Malta specific: IPI,performance and timer inetrrupts */
+       /* This is Malta specific: IPI,performance and timer interrupts */
        if (gic_present)
                change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
                                         STATUSF_IP6 | STATUSF_IP7);
index 8e9fbe7..e971043 100644 (file)
@@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_struct *ctx, int has_fpu);
+                                   struct mips_fpu_struct *ctx, int has_fpu,
+                                   void *__user *fault_addr);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)
        force_sig_info(SIGFPE, &info, current);
 }
 
+static int process_fpemu_return(int sig, void __user *fault_addr)
+{
+       if (sig == SIGSEGV || sig == SIGBUS) {
+               struct siginfo si = {0};
+               si.si_addr = fault_addr;
+               si.si_signo = sig;
+               if (sig == SIGSEGV) {
+                       if (find_vma(current->mm, (unsigned long)fault_addr))
+                               si.si_code = SEGV_ACCERR;
+                       else
+                               si.si_code = SEGV_MAPERR;
+               } else {
+                       si.si_code = BUS_ADRERR;
+               }
+               force_sig_info(sig, &si, current);
+               return 1;
+       } else if (sig) {
+               force_sig(sig, current);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 /*
  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  */
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       siginfo_t info;
+       siginfo_t info = {0};
 
        if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
            == NOTIFY_STOP)
@@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 
        if (fcr31 & FPU_CSR_UNI_X) {
                int sig;
+               void __user *fault_addr = NULL;
 
                /*
                 * Unimplemented operation exception.  If we've got the full
@@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                lose_fpu(1);
 
                /* Run the emulator */
-               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1);
+               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
+                                              &fault_addr);
 
                /*
                 * We can't allow the emulated instruction to leave any of
@@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                own_fpu(1);     /* Using the FPU again.  */
 
                /* If something went wrong, signal */
-               if (sig)
-                       force_sig(sig, current);
+               process_fpemu_return(sig, fault_addr);
 
                return;
        } else if (fcr31 & FPU_CSR_INV_X)
@@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                if (!raw_cpu_has_fpu) {
                        int sig;
+                       void __user *fault_addr = NULL;
                        sig = fpu_emulator_cop1Handler(regs,
-                                               &current->thread.fpu, 0);
-                       if (sig)
-                               force_sig(sig, current);
-                       else
+                                                      &current->thread.fpu,
+                                                      0, &fault_addr);
+                       if (!process_fpemu_return(sig, fault_addr))
                                mt_ase_fp_affinity();
                }
 
index 3eb3cde..6a1fdfe 100644 (file)
@@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)
 
        /* this of-course trashes what was there before... */
        v->pbuffer = vmalloc(P_SIZE);
+       if (!v->pbuffer) {
+               pr_warning("VPE loader: unable to allocate memory\n");
+               return -ENOMEM;
+       }
        v->plen = P_SIZE;
        v->load_addr = NULL;
        v->len = 0;
@@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)
        if (ret < 0)
                v->shared_ptr = NULL;
 
-       // cleanup any temp buffers
-       if (v->pbuffer)
-               vfree(v->pbuffer);
+       vfree(v->pbuffer);
        v->plen = 0;
+
        return ret;
 }
 
@@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
        if (v == NULL)
                return -ENODEV;
 
-       if (v->pbuffer == NULL) {
-               printk(KERN_ERR "VPE loader: no buffer for program\n");
-               return -ENOMEM;
-       }
-
        if ((count + v->len) > v->plen) {
                printk(KERN_WARNING
                       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
index 77dc3b2..606c8a9 100644 (file)
@@ -161,16 +161,16 @@ FEXPORT(__bzero)
 
 .Lfwd_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, 0x3f
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
 
 .Lpartial_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, LONGMASK
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
index ae4cff9..11b193f 100644 (file)
@@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
+       int ret;                                                        \
        if (strncmp(option, (char *)p, strlen(option)) == 0)            \
-                       strict_strtol((char *)p + strlen(option"="),    \
-                                       10, &res);                      \
+               ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
index b2ad1b0..d32cb05 100644 (file)
@@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-       struct mips_fpu_struct *, mips_instruction);
+       struct mips_fpu_struct *, mips_instruction, void *__user *);
 #endif
 
 /* Further private data for which no space exists in mips_fpu_struct */
@@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+                      void *__user *fault_addr)
 {
        mips_instruction ir;
        unsigned long emulpc, contpc;
        unsigned int cond;
 
-       if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+       if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                return SIGBUS;
        }
+       if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+               MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+               return SIGSEGV;
+       }
 
        /* XXX NEC Vr54xx bug workaround */
        if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
@@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 #endif
                        return SIGILL;
                }
-               if (get_user(ir, (mips_instruction __user *) emulpc)) {
+               if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
                        return SIGBUS;
                }
+               if (__get_user(ir, (mips_instruction __user *) emulpc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
+                       return SIGSEGV;
+               }
                /* __compute_return_epc() will have updated cp0_epc */
                contpc = xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
@@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u64 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+
+               if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                DITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                DIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u32 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+               if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                SITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                SIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                contpc = (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
-                               if (get_user(ir,
-                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                               if (!access_ok(VERIFY_READ, xcp->cp0_epc,
+                                              sizeof(mips_instruction))) {
                                        MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                                        return SIGBUS;
                                }
+                               if (__get_user(ir,
+                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                                       MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                                       return SIGSEGV;
+                               }
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
@@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
 #if __mips >= 4 && __mips != 32
        case cop1x_op:{
-               int sig;
-
-               if ((sig = fpux_emu(xcp, ctx, ir)))
+               int sig = fpux_emu(xcp, ctx, ir, fault_addr);
+               if (sig)
                        return sig;
                break;
        }
@@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       mips_instruction ir)
+       mips_instruction ir, void *__user *fault_addr)
 {
        unsigned rcsr = 0;      /* resulting csr */
 
@@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        SITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        MIPS_FPU_EMU_INC_STATS(stores);
 
                        SIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_s_op:
@@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        DITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
                        MIPS_FPU_EMU_INC_STATS(stores);
                        DIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_d_op:
@@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 }
 
 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       int has_fpu)
+       int has_fpu, void *__user *fault_addr)
 {
        unsigned long oldepc, prevepc;
        mips_instruction insn;
@@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        do {
                prevepc = xcp->cp0_epc;
 
-               if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+               if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                        return SIGBUS;
                }
+               if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                       return SIGSEGV;
+               }
                if (insn == 0)
                        xcp->cp0_epc += 4;      /* skip nops */
                else {
@@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                         */
                        /* convert to ieee library modes */
                        ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
-                       sig = cop1Emulate(xcp, ctx);
+                       sig = cop1Emulate(xcp, ctx, fault_addr);
                        /* revert to mips rounding mode */
                        ieee754_csr.rm = mips_rm[ieee754_csr.rm];
                }
index 4fc1a0f..21ea14e 100644 (file)
@@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)
        return plat_dma_supported(dev, mask);
 }
 
-void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                         enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
@@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                __dma_sync((unsigned long)vaddr, size, direction);
 }
 
+EXPORT_SYMBOL(dma_cache_sync);
+
 static struct dma_map_ops mips_default_dma_map_ops = {
        .alloc_coherent = mips_dma_alloc_coherent,
        .free_coherent = mips_dma_free_coherent,
index 505feca..9cca8de 100644 (file)
@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {
  */
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 {
+       unsigned int config2 = read_c0_config2();
+       unsigned int tmp;
+
        /* Check the bypass bit (L2B) */
        switch (c->cputype) {
        case CPU_34K:
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
                c->scache.linesz = 2 << tmp;
        else
                return 0;
+       return 1;
 }
 
 static inline int __init mips_sc_probe(void)
index b7f1d9c..434d7b1 100644 (file)
@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       lbu     %0, (%0)        \n"
        "       .set    mips0           \n"
        : "=r" (res)
-       : "m" (vaddr));
+       : "R" (vaddr));
 
        write_c0_status(sr);
        ssnop_4();
@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       sb      %2, (%0)        \n"
        "       .set    mips0           \n"
        : "=&r" (tmp)
-       : "m" (vaddr), "r" (c));
+       : "R" (vaddr), "r" (c));
 
        write_c0_status(sr);
        ssnop_4();
index c308989..41707a2 100644 (file)
@@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
 enum swarm_rtc_type {
        RTC_NONE,
        RTC_XICOR,
-       RTC_M4LT81
+       RTC_M41T81,
 };
 
 enum swarm_rtc_type swarm_rtc_type;
@@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)
                sec = xicor_get_time();
                break;
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                sec = m41t81_get_time();
                break;
 
@@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)
        case RTC_XICOR:
                return xicor_set_time(sec);
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                return m41t81_set_time(sec);
 
        case RTC_NONE:
@@ -141,7 +141,7 @@ void __init plat_mem_setup(void)
        if (xicor_probe())
                swarm_rtc_type = RTC_XICOR;
        if (m41t81_probe())
-               swarm_rtc_type = RTC_M4LT81;
+               swarm_rtc_type = RTC_M41T81;
 
 #ifdef CONFIG_VT
        screen_info = (struct screen_info) {
index 7f217b3..2e9d78d 100644 (file)
@@ -22,7 +22,8 @@ config SUPERH
        select HAVE_SPARSE_IRQ
        select RTC_LIB
        select GENERIC_ATOMIC64
-       select GENERIC_HARDIRQS_NO_DEPRECATED
+       # Support the deprecated APIs until MFD and GPIOLIB catch up.
+       select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
index 903cd61..d6741fc 100644 (file)
 #define __NR_sendmsg           355
 #define __NR_recvmsg           356
 #define __NR_recvmmsg          357
+#define __NR_accept4           358
 
-#define NR_syscalls 358
+#define NR_syscalls 359
 
 #ifdef __KERNEL__
 
index e872e81..6fc347e 100644 (file)
@@ -375,3 +375,4 @@ ENTRY(sys_call_table)
        .long sys_sendmsg               /* 355 */
        .long sys_recvmsg
        .long sys_recvmmsg
+       .long sys_accept4
index 81cd434..47eaafa 100644 (file)
@@ -39,7 +39,7 @@ struct linux_dev_v2_funcs {
        int (*v2_dev_open)(char *devpath);
        void (*v2_dev_close)(int d);
        int (*v2_dev_read)(int d, char *buf, int nbytes);
-       int (*v2_dev_write)(int d, char *buf, int nbytes);
+       int (*v2_dev_write)(int d, const char *buf, int nbytes);
        int (*v2_dev_seek)(int d, int hi, int lo);
 
        /* Never issued (multistage load support) */
index 51296a6..9e5c640 100644 (file)
@@ -60,25 +60,6 @@ extern char *prom_getbootargs(void);
 extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
 extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
 
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -121,19 +102,8 @@ extern int prom_getrev(void);
 /* Get the prom firmware revision. */
 extern int prom_getprev(void);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -238,7 +208,6 @@ extern int prom_node_has_property(phandle node, char *property);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(char *path);
 extern phandle prom_inst2pkg(int);
 
 /* Dorking with Bus ranges... */
index c9cc078..8cd0df3 100644 (file)
@@ -67,27 +67,6 @@ extern void prom_init(void *cif_handler, void *cif_stack);
 /* Boot argument acquisition, returns the boot command line string. */
 extern char *prom_getbootargs(void);
 
-/* Device utilities. */
-
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(const char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -109,33 +88,14 @@ extern void prom_halt(void) __attribute__ ((noreturn));
 /* Halt and power-off the machine. */
 extern void prom_halt_power_off(void) __attribute__ ((noreturn));
 
-/* Set the PROM 'sync' callback function to the passed function pointer.
- * When the user gives the 'sync' command at the prom prompt while the
- * kernel is still active, the prom will call this routine.
- *
- */
-typedef int (*callback_func_t)(long *cmd);
-extern void prom_setcallback(callback_func_t func_ptr);
-
 /* Acquire the IDPROM of the root node in the prom device tree.  This
  * gets passed a buffer where you would like it stuffed.  The return value
  * is the format type of this idprom or 0xff on error.
  */
 extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -279,9 +239,7 @@ extern phandle prom_finddevice(const char *name);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(const char *path);
 extern phandle prom_inst2pkg(int);
-extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
 extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
index 2d51527..f01c426 100644 (file)
@@ -114,7 +114,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
        if (leon3_gptimer_regs && leon3_irqctrl_regs) {
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
-                                     (((1000000 / 100) - 1)));
+                                     (((1000000 / HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
 
 #ifdef CONFIG_SMP
@@ -128,7 +128,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
                }
 
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
-               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1)));
+               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 # endif
 
index 1b8c073..816c0fa 100644 (file)
@@ -6,7 +6,6 @@ ccflags := -Werror
 
 lib-y                 := bootstr_$(BITS).o
 lib-$(CONFIG_SPARC32) += devmap.o
-lib-y                 += devops_$(BITS).o
 lib-y                 += init_$(BITS).o
 lib-$(CONFIG_SPARC32) += memory.o
 lib-y                 += misc_$(BITS).o
index 5340264..4886310 100644 (file)
 
 extern void restore_current(void);
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-int
-prom_nbgetchar(void)
-{
-       static char inc;
-       int i = -1;
-       unsigned long flags;
-
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               i = (*(romvec->pv_nbgetchar))();
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) {
-                       i = inc;
-               } else {
-                       i = -1;
-               }
-               break;
-       default:
-               i = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return i; /* Ugh, we could spin forever on unsupported proms ;( */
-}
-
 /* Non blocking put character to console device, returns -1 if
  * unsuccessful.
  */
-int
-prom_nbputchar(char c)
+static int prom_nbputchar(const char *buf)
 {
-       static char outc;
        unsigned long flags;
        int i = -1;
 
        spin_lock_irqsave(&prom_lock, flags);
        switch(prom_vers) {
        case PROM_V0:
-               i = (*(romvec->pv_nbputchar))(c);
+               i = (*(romvec->pv_nbputchar))(*buf);
                break;
        case PROM_V2:
        case PROM_V3:
-               outc = c;
-               if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1)
+               if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
+                                                         buf, 0x1) == 1)
                        i = 0;
-               else
-                       i = -1;
                break;
        default:
-               i = -1;
                break;
        };
        restore_current();
@@ -80,18 +43,14 @@ prom_nbputchar(char c)
        return i; /* Ugh, we could spin forever on unsupported proms ;( */
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
+void prom_console_write_buf(const char *buf, int len)
 {
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
+       while (len) {
+               int n = prom_nbputchar(buf);
+               if (n)
+                       continue;
+               len--;
+               buf++;
+       }
 }
 
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
-{
-       while(prom_nbputchar(c) == -1) ;
-}
index 10322dc..ed39e75 100644 (file)
 
 extern int prom_stdin, prom_stdout;
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-inline int
-prom_nbgetchar(void)
-{
-       unsigned long args[7];
-       char inc;
-
-       args[0] = (unsigned long) "read";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdin;
-       args[4] = (unsigned long) &inc;
-       args[5] = 1;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       if (args[6] == 1)
-               return inc;
-       return -1;
-}
-
-/* Non blocking put character to console device, returns -1 if
- * unsuccessful.
- */
-inline int
-prom_nbputchar(char c)
+static int __prom_console_write_buf(const char *buf, int len)
 {
        unsigned long args[7];
-       char outc;
-       
-       outc = c;
+       int ret;
 
        args[0] = (unsigned long) "write";
        args[1] = 3;
        args[2] = 1;
        args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) &outc;
-       args[5] = 1;
+       args[4] = (unsigned long) buf;
+       args[5] = (unsigned int) len;
        args[6] = (unsigned long) -1;
 
        p1275_cmd_direct(args);
 
-       if (args[6] == 1)
-               return 0;
-       else
+       ret = (int) args[6];
+       if (ret < 0)
                return -1;
+       return ret;
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
-{
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
-}
-
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
+void prom_console_write_buf(const char *buf, int len)
 {
-       prom_nbputchar(c);
-}
-
-void
-prom_puts(const char *s, int len)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "write";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) s;
-       args[5] = len;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
+       while (len) {
+               int n = __prom_console_write_buf(buf, len);
+               if (n < 0)
+                       continue;
+               len -= n;
+               buf += len;
+       }
 }
diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c
deleted file mode 100644 (file)
index 9c5d468..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns -1 on failure.
- */
-int
-prom_devopen(char *dstr)
-{
-       int handle;
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               handle = (*(romvec->pv_v0devops.v0_devopen))(dstr);
-               if(handle == 0) handle = -1;
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr);
-               break;
-       default:
-               handle = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-
-       return handle;
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_devclose))(dhandle);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_close))(dhandle);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-}
diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c
deleted file mode 100644 (file)
index a017119..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns 0 on failure.
- */
-int
-prom_devopen(const char *dstr)
-{
-       unsigned long args[5];
-
-       args[0] = (unsigned long) "open";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) dstr;
-       args[4] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       return (int) args[4];
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long args[4];
-
-       args[0] = (unsigned long) "close";
-       args[1] = 1;
-       args[2] = 0;
-       args[3] = (unsigned int) dhandle;
-
-       p1275_cmd_direct(args);
-
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "seek";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) dhandle;
-       args[4] = seekhi;
-       args[5] = seeklo;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-}
index d24bc44..e4f31d4 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldc.h>
 
-int prom_service_exists(const char *service_name)
+static int prom_service_exists(const char *service_name)
 {
        unsigned long args[5];
 
@@ -150,20 +150,6 @@ void prom_halt_power_off(void)
        prom_halt();
 }
 
-/* Set prom sync handler to call function 'funcp'. */
-void prom_setcallback(callback_func_t funcp)
-{
-       unsigned long args[5];
-       if (!funcp)
-               return;
-       args[0] = (unsigned long) "set-callback";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) funcp;
-       args[4] = (unsigned long) -1;
-       p1275_cmd_direct(args);
-}
-
 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
  * format type.  'num_bytes' is the number of bytes that your idbuf
  * has space for.  Returns 0xff on error.
index ca86926..d9682f0 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/compiler.h>
+#include <linux/spinlock.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
+#define CONSOLE_WRITE_BUF_SIZE 1024
+
 static char ppbuf[1024];
+static char console_write_buf[CONSOLE_WRITE_BUF_SIZE];
+static DEFINE_RAW_SPINLOCK(console_write_lock);
 
 void notrace prom_write(const char *buf, unsigned int n)
 {
-       char ch;
+       unsigned int dest_len;
+       unsigned long flags;
+       char *dest;
+
+       dest = console_write_buf;
+       raw_spin_lock_irqsave(&console_write_lock, flags);
 
-       while (n != 0) {
-               --n;
-               if ((ch = *buf++) == '\n')
-                       prom_putchar('\r');
-               prom_putchar(ch);
+       dest_len = 0;
+       while (n-- != 0) {
+               char ch = *buf++;
+               if (ch == '\n') {
+                       *dest++ = '\r';
+                       dest_len++;
+               }
+               *dest++ = ch;
+               dest_len++;
+               if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) {
+                       prom_console_write_buf(console_write_buf, dest_len);
+                       dest = console_write_buf;
+                       dest_len = 0;
+               }
        }
+       if (dest_len)
+               prom_console_write_buf(console_write_buf, dest_len);
+
+       raw_spin_unlock_irqrestore(&console_write_lock, flags);
 }
 
 void notrace prom_printf(const char *fmt, ...)
index 63e08e1..535e2e6 100644 (file)
@@ -342,19 +342,3 @@ phandle prom_inst2pkg(int inst)
        if (node == -1) return 0;
        return node;
 }
-
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(char *path)
-{
-       phandle node;
-       int inst;
-       
-       inst = prom_devopen (path);
-       if (inst == -1) return 0;
-       node = prom_inst2pkg (inst);
-       prom_devclose (inst);
-       if (node == -1) return 0;
-       return node;
-}
index 691be68..d936600 100644 (file)
@@ -374,24 +374,6 @@ inline phandle prom_inst2pkg(int inst)
        return node;
 }
 
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(const char *path)
-{
-       phandle node;
-       int inst;
-
-       inst = prom_devopen (path);
-       if (inst == 0)
-               return 0;
-       node = prom_inst2pkg(inst);
-       prom_devclose(inst);
-       if (node == -1)
-               return 0;
-       return node;
-}
-
 int prom_ihandle2path(int handle, char *buffer, int bufsize)
 {
        unsigned long args[7];
index c1ee1d6..81d92a4 100644 (file)
@@ -25,7 +25,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
 #endif
index 543d6a3..dbb0dfc 100644 (file)
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        return ret;
 }
 
+/* The assembly shim for this function arranges to ignore the return value. */
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index f582162..5eed4a0 100644 (file)
@@ -1342,8 +1342,8 @@ handle_syscall:
        lw      r20, r20
 
        /* Jump to syscall handler. */
-       jalr    r20; .Lhandle_syscall_link:
-       FEEDBACK_REENTER(handle_syscall)
+       jalr    r20
+.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */
 
        /*
         * Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
        PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
        sw      r29, r0
 
+.Lsyscall_sigreturn_skip:
+       FEEDBACK_REENTER(handle_syscall)
+
        /* Do syscall trace again, if requested. */
        lw      r30, r31
        andi    r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
+/*
+ * Special-case sigreturn to not write r0 to the stack on return.
+ * This is technically more efficient, but it also avoids difficulties
+ * in the 64-bit OS when handling 32-bit compat code, since we must not
+ * sign-extend r0 for the sigreturn return-value case.
+ */
+#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \
+       STD_ENTRY(_##x);                                \
+       addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
+       {                                               \
+        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
+        j      x                                       \
+       };                                              \
+       STD_ENDPROC(_##x)
+
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
-PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
index 8430f45..e90eb53 100644 (file)
@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        childregs->regs[0] = 0;         /* return value is zero */
        childregs->sp = sp;  /* override with new user stack pointer */
 
+       /*
+        * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
+        * which is passed in as arg #5 to sys_clone().
+        */
+       if (clone_flags & CLONE_SETTLS)
+               childregs->tp = regs->regs[4];
+
        /*
         * Copy the callee-saved registers from the passed pt_regs struct
         * into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
        return __switch_to(prev, next, next_current_ksp0(next));
 }
 
+/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                void __user *, parent_tidptr, void __user *, child_tidptr,
                struct pt_regs *, regs)
index 757407e..1260321 100644 (file)
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
  */
 
 int restore_sigcontext(struct pt_regs *regs,
-                      struct sigcontext __user *sc, long *pr0)
+                      struct sigcontext __user *sc)
 {
        int err = 0;
        int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
 
        regs->faultnum = INT_SWINT_1_SIGRETURN;
 
-       err |= __get_user(*pr0, &sc->gregs[0]);
        return err;
 }
 
-/* sigreturn() returns long since it restores r0 in the interrupted code. */
+/* The assembly shim for this function arranges to ignore the return value. */
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index cbcc8d8..7a6e68e 100644 (file)
@@ -10,6 +10,7 @@
  * by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
index 5be1542..e99d55d 100644 (file)
@@ -72,6 +72,9 @@ struct e820map {
 #define BIOS_BEGIN             0x000a0000
 #define BIOS_END               0x00100000
 
+#define BIOS_ROM_BASE          0xffe00000
+#define BIOS_ROM_END           0xffffffff
+
 #ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
index 9e6fe39..f702f82 100644 (file)
@@ -79,7 +79,7 @@
 #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
-#define KVM_MAX_CPUID_ENTRIES 40
+#define KVM_MAX_CPUID_ENTRIES 80
 #define KVM_NR_FIXED_MTRR_REGION 88
 #define KVM_NR_VAR_MTRR 8
 
index 9e13763..1e99475 100644 (file)
@@ -45,6 +45,7 @@ obj-y                 += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y                  += tsc.o io_delay.o rtc.o
 obj-y                  += pci-iommu_table.o
+obj-y                  += resource.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
index bcece91..f0bea76 100644 (file)
@@ -620,13 +620,13 @@ ENTRY(initial_code)
 __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-initial_pg_pmd:
+ENTRY(initial_pg_pmd)
        .fill 1024*KPMDS,4,0
 #else
 ENTRY(initial_page_table)
        .fill 1024,4,0
 #endif
-initial_pg_fixmap:
+ENTRY(initial_pg_fixmap)
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
new file mode 100644 (file)
index 0000000..2a26819
--- /dev/null
@@ -0,0 +1,48 @@
+#include <linux/ioport.h>
+#include <asm/e820.h>
+
+static void resource_clip(struct resource *res, resource_size_t start,
+                         resource_size_t end)
+{
+       resource_size_t low = 0, high = 0;
+
+       if (res->end < start || res->start > end)
+               return;         /* no conflict */
+
+       if (res->start < start)
+               low = start - res->start;
+
+       if (res->end > end)
+               high = res->end - end;
+
+       /* Keep the area above or below the conflict, whichever is larger */
+       if (low > high)
+               res->end = start - 1;
+       else
+               res->start = end + 1;
+}
+
+static void remove_e820_regions(struct resource *avail)
+{
+       int i;
+       struct e820entry *entry;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               entry = &e820.map[i];
+
+               resource_clip(avail, entry->addr,
+                             entry->addr + entry->size - 1);
+       }
+}
+
+void arch_remove_reservations(struct resource *avail)
+{
+       /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+       if (avail->flags & IORESOURCE_MEM) {
+               if (avail->start < BIOS_END)
+                       avail->start = BIOS_END;
+               resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+               remove_e820_regions(avail);
+       }
+}
index 21c6746..85268f8 100644 (file)
@@ -769,7 +769,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.oem.arch_setup();
 
-       resource_alloc_from_bottom = 0;
        iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
        setup_memory_map();
        parse_setup_data();
index 1ca1229..b81a9b7 100644 (file)
@@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
        switch (func) {
+       case 0x00000001:
+               /* Mask out xsave bit as long as it is not supported by SVM */
+               entry->ecx &= ~(bit(X86_FEATURE_XSAVE));
+               break;
        case 0x80000001:
                if (nested)
                        entry->ecx |= (1 << 2); /* Set SVM bit */
index ff21fdd..81fcbe9 100644 (file)
@@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void)
                return PT_PDPE_LEVEL;
 }
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cdac9e5..b989e1f 100644 (file)
@@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
        unsigned slot;
@@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)
 #ifdef CONFIG_CPU_FREQ
                struct cpufreq_policy policy;
                memset(&policy, 0, sizeof(policy));
-               cpufreq_get_policy(&policy, get_cpu());
+               cpu = get_cpu();
+               cpufreq_get_policy(&policy, cpu);
                if (policy.cpuinfo.max_freq)
                        max_tsc_khz = policy.cpuinfo.max_freq;
+               put_cpu();
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
        kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
+       if (sregs->cr4 & X86_CR4_OSXSAVE)
+               update_cpuid(vcpu);
        if (!is_long_mode(vcpu) && is_pae(vcpu)) {
                load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
                mmu_reset_needed = 1;
index 2cea414..c600da8 100644 (file)
@@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
        return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 }
 
+static inline u32 bit(int bitno)
+{
+       return 1 << (bitno & 31);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq);
index 73b1e1a..4996cf5 100644 (file)
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)
 {
        lguest_data.pgdir = cr3;
        lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
-       cr3_changed = true;
+
+       /* These two page tables are simple, linear, and used during boot */
+       if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
+               cr3_changed = true;
 }
 
 static unsigned long lguest_read_cr3(void)
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
  * to forget all of them.  Fortunately, this is very rare.
  *
  * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
- * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds.
+ * which makes booting astonishingly slow: 48 seconds!  So we don't even tell
+ * the Host anything changed until we've done the first real page table switch,
+ * which brings boot back to 4.3 seconds.
  */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void)
        clockevents_register_device(&lguest_clockevent);
 
        /* Finally, we unblock the timer interrupt. */
-       enable_lguest_irq(0);
+       clear_bit(0, lguest_data.blocked_interrupts);
 }
 
 /*
@@ -1349,9 +1352,6 @@ __init void lguest_init(void)
         */
        switch_to_new_gdt(0);
 
-       /* We actually boot with all memory mapped, but let's say 128MB. */
-       max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
-
        /*
         * The Host<->Guest Switcher lives at the top of our address space, and
         * the Host told us how big it is when we made LGUEST_INIT hypercall:
index 4f420c2..e7d5382 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
+#include <asm/pgtable.h>
 
 /*G:020
  * Our story starts with the kernel booting into startup_32 in
@@ -37,9 +38,113 @@ ENTRY(lguest_entry)
        /* Set up the initial stack so we can run C code. */
        movl $(init_thread_union+THREAD_SIZE),%esp
 
+       call init_pagetables
+
        /* Jumps are relative: we're running __PAGE_OFFSET too low. */
        jmp lguest_init+__PAGE_OFFSET
 
+/*
+ * Initialize page tables.  This creates a PDE and a set of page
+ * tables, which are located immediately beyond __brk_base.  The variable
+ * _brk_end is set up to point to the first "safe" location.
+ * Mappings are created both at virtual address 0 (identity mapping)
+ * and PAGE_OFFSET for up to _end.
+ *
+ * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
+ * don't have a stack at this point, so we can't just use call and ret.
+ */
+init_pagetables:
+#if PTRS_PER_PMD > 1
+#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+#else
+#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
+#endif
+#define pa(X) ((X) - __PAGE_OFFSET)
+
+/* Enough space to fit pagetables for the low memory linear map */
+MAPPING_BEYOND_END = \
+       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+#ifdef CONFIG_X86_PAE
+
+       /*
+        * In PAE mode initial_page_table is statically defined to contain
+        * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD entries
+        * to the first kernel PMD.
+        *
+        * Note the upper half of each PMD or PTE are always zero at this stage.
+        */
+
+#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_pg_pmd), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       addl $0x1000,%eax
+       loop 11b
+
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_page_table), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PDE entry */
+       movl %ecx,(%edx)                        /* Store identity PDE entry */
+       movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
+       addl $4,%edx
+       movl $1024, %ecx
+11:
+       stosl
+       addl $0x1000,%eax
+       loop 11b
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_page_table+0xffc)
+#endif
+       ret
+
 /*G:055
  * We create a macro which puts the assembler code between lgstart_ and lgend_
  * markers.  These templates are put in the .text section: they can't be
index c4bb261..b1805b7 100644 (file)
@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,
                        resource_size_t size, resource_size_t align)
 {
        struct pci_dev *dev = data;
-       resource_size_t start = round_down(res->end - size + 1, align);
+       resource_size_t start = res->start;
 
        if (res->flags & IORESOURCE_IO) {
-
-               /*
-                * If we're avoiding ISA aliases, the largest contiguous I/O
-                * port space is 256 bytes.  Clearing bits 9 and 10 preserves
-                * all 256-byte and smaller alignments, so the result will
-                * still be correctly aligned.
-                */
-               if (!skip_isa_ioresource_align(dev))
-                       start &= ~0x300;
-       } else if (res->flags & IORESOURCE_MEM) {
-               if (start < BIOS_END)
-                       start = res->end;       /* fail; no space */
+               if (skip_isa_ioresource_align(dev))
+                       return start;
+               if (start & 0x300)
+                       start = (start + 0x3ff) & ~0x3ff;
        }
        return start;
 }
index f20d6a7..0c8b64a 100644 (file)
@@ -250,6 +250,14 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
        int ret, rw;
        unsigned int dxfer_len;
        void *dxferp = NULL;
+       struct bsg_class_device *bcd = &q->bsg_dev;
+
+       /* if the LLD has been removed then the bsg_unregister_queue will
+        * eventually be called and the class_dev was freed, so we can no
+        * longer use this request_queue. Return no such address.
+        */
+       if (!bcd->class_dev)
+               return ERR_PTR(-ENXIO);
 
        dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
                hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
index ba9afea..25d3aae 100644 (file)
@@ -100,24 +100,7 @@ static const struct file_operations acpi_ac_fops = {
        .release = single_release,
 };
 #endif
-static int get_ac_property(struct power_supply *psy,
-                          enum power_supply_property psp,
-                          union power_supply_propval *val)
-{
-       struct acpi_ac *ac = to_acpi_ac(psy);
-       switch (psp) {
-       case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = ac->state;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
 
-static enum power_supply_property ac_props[] = {
-       POWER_SUPPLY_PROP_ONLINE,
-};
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -140,6 +123,35 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
        return 0;
 }
 
+/* --------------------------------------------------------------------------
+                            sysfs I/F
+   -------------------------------------------------------------------------- */
+static int get_ac_property(struct power_supply *psy,
+                          enum power_supply_property psp,
+                          union power_supply_propval *val)
+{
+       struct acpi_ac *ac = to_acpi_ac(psy);
+
+       if (!ac)
+               return -ENODEV;
+
+       if (acpi_ac_get_state(ac))
+               return -ENODEV;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = ac->state;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static enum power_supply_property ac_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
 #ifdef CONFIG_ACPI_PROCFS_POWER
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
index 1211c03..5850d32 100644 (file)
@@ -86,7 +86,7 @@ static struct erst_erange {
  * It is used to provide exclusive accessing for ERST Error Log
  * Address Range too.
  */
-static DEFINE_SPINLOCK(erst_lock);
+static DEFINE_RAW_SPINLOCK(erst_lock);
 
 static inline int erst_errno(int command_status)
 {
@@ -421,9 +421,9 @@ ssize_t erst_get_record_count(void)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        count = __erst_get_record_count();
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return count;
 }
@@ -456,9 +456,9 @@ int erst_get_next_record_id(u64 *record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -624,17 +624,17 @@ int erst_write(const struct cper_record_header *record)
                return -EINVAL;
 
        if (erst_erange.attr & ERST_RANGE_NVRAM) {
-               if (!spin_trylock_irqsave(&erst_lock, flags))
+               if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                        return -EBUSY;
                rc = __erst_write_to_nvram(record);
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
 
        if (record->record_length > erst_erange.size)
                return -EINVAL;
 
-       if (!spin_trylock_irqsave(&erst_lock, flags))
+       if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                return -EBUSY;
        memcpy(erst_erange.vaddr, record, record->record_length);
        rcd_erange = erst_erange.vaddr;
@@ -642,7 +642,7 @@ int erst_write(const struct cper_record_header *record)
        memcpy(&rcd_erange->persistence_information, "ER", 2);
 
        rc = __erst_write_to_storage(0);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -696,9 +696,9 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record,
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
        return len;
 }
 EXPORT_SYMBOL_GPL(erst_read);
@@ -719,20 +719,20 @@ ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(&record_id);
        if (rc) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return 0;
        }
 
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return len;
 }
@@ -746,12 +746,12 @@ int erst_clear(u64 record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        if (erst_erange.attr & ERST_RANGE_NVRAM)
                rc = __erst_clear_from_nvram(record_id);
        else
                rc = __erst_clear_from_storage(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
index 1a3508a..daa7bc6 100644 (file)
@@ -46,9 +46,9 @@ EXPORT_SYMBOL_GPL(hest_disable);
 
 /* HEST table parsing */
 
-static struct acpi_table_hest *hest_tab;
+static struct acpi_table_hest *__read_mostly hest_tab;
 
-static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
+static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
        [ACPI_HEST_TYPE_IA32_CHECK] = -1,       /* need further calculation */
        [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
        [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi),
@@ -126,7 +126,7 @@ struct ghes_arr {
        unsigned int count;
 };
 
-static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
 {
        int *count = data;
 
@@ -135,7 +135,7 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
        return 0;
 }
 
-static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
        struct platform_device *ghes_dev;
        struct ghes_arr *ghes_arr = data;
@@ -165,7 +165,7 @@ err:
        return rc;
 }
 
-static int hest_ghes_dev_register(unsigned int ghes_count)
+static int __init hest_ghes_dev_register(unsigned int ghes_count)
 {
        int rc, i;
        struct ghes_arr ghes_arr;
index 95649d3..9fb9d5a 100644 (file)
@@ -130,6 +130,8 @@ struct acpi_battery {
        unsigned long flags;
 };
 
+static int acpi_battery_update(struct acpi_battery *battery);
+
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -184,6 +186,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
        int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
+       if (acpi_battery_update(battery))
+               return -ENODEV;
+
        if (acpi_battery_present(battery)) {
                /* run battery update only if it is present */
                acpi_battery_get_state(battery);
index 372ff80..302b31e 100644 (file)
@@ -934,6 +934,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        ec_flag_msi, "MSI hardware", {
        DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
        {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
+       {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
        {},
index 966fedd..055d7b7 100644 (file)
@@ -110,9 +110,6 @@ struct acpi_ioremap {
 static LIST_HEAD(acpi_ioremaps);
 static DEFINE_SPINLOCK(acpi_ioremap_lock);
 
-#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
-static char osi_setup_string[OSI_STRING_LENGTH_MAX];
-
 static void __init acpi_osi_setup_late(void);
 
 /*
@@ -152,8 +149,7 @@ static struct osi_linux {
        unsigned int    enable:1;
        unsigned int    dmi:1;
        unsigned int    cmdline:1;
-       unsigned int    known:1;
-} osi_linux = { 0, 0, 0, 0};
+} osi_linux = {0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -1055,13 +1051,53 @@ static int __init acpi_os_name_setup(char *str)
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
+#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
+#define        OSI_STRING_ENTRIES_MAX 16       /* arbitrary */
+
+struct osi_setup_entry {
+       char string[OSI_STRING_LENGTH_MAX];
+       bool enable;
+};
+
+static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX];
+
+void __init acpi_osi_setup(char *str)
+{
+       struct osi_setup_entry *osi;
+       bool enable = true;
+       int i;
+
+       if (!acpi_gbl_create_osi_method)
+               return;
+
+       if (str == NULL || *str == '\0') {
+               printk(KERN_INFO PREFIX "_OSI method disabled\n");
+               acpi_gbl_create_osi_method = FALSE;
+               return;
+       }
+
+       if (*str == '!') {
+               str++;
+               enable = false;
+       }
+
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               if (!strcmp(osi->string, str)) {
+                       osi->enable = enable;
+                       break;
+               } else if (osi->string[0] == '\0') {
+                       osi->enable = enable;
+                       strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+                       break;
+               }
+       }
+}
+
 static void __init set_osi_linux(unsigned int enable)
 {
-       if (osi_linux.enable != enable) {
+       if (osi_linux.enable != enable)
                osi_linux.enable = enable;
-               printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
-                       enable ? "Add": "Delet");
-       }
 
        if (osi_linux.enable)
                acpi_osi_setup("Linux");
@@ -1073,7 +1109,8 @@ static void __init set_osi_linux(unsigned int enable)
 
 static void __init acpi_cmdline_osi_linux(unsigned int enable)
 {
-       osi_linux.cmdline = 1;  /* cmdline set the default */
+       osi_linux.cmdline = 1;  /* cmdline set the default and override DMI */
+       osi_linux.dmi = 0;
        set_osi_linux(enable);
 
        return;
@@ -1081,15 +1118,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable)
 
 void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
 {
-       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
-
        printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
 
        if (enable == -1)
                return;
 
-       osi_linux.known = 1;    /* DMI knows which OSI(Linux) default needed */
-
+       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
        set_osi_linux(enable);
 
        return;
@@ -1104,37 +1138,44 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
  */
 static void __init acpi_osi_setup_late(void)
 {
-       char *str = osi_setup_string;
+       struct osi_setup_entry *osi;
+       char *str;
+       int i;
+       acpi_status status;
 
-       if (*str == '\0')
-               return;
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               str = osi->string;
 
-       if (!strcmp("!Linux", str)) {
-               acpi_cmdline_osi_linux(0);      /* !enable */
-       } else if (*str == '!') {
-               if (acpi_remove_interface(++str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-       } else if (!strcmp("Linux", str)) {
-               acpi_cmdline_osi_linux(1);      /* enable */
-       } else {
-               if (acpi_install_interface(str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               if (*str == '\0')
+                       break;
+               if (osi->enable) {
+                       status = acpi_install_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               } else {
+                       status = acpi_remove_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+               }
        }
 }
 
-int __init acpi_osi_setup(char *str)
+static int __init osi_setup(char *str)
 {
-       if (str == NULL || *str == '\0') {
-               printk(KERN_INFO PREFIX "_OSI method disabled\n");
-               acpi_gbl_create_osi_method = FALSE;
-       } else {
-               strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
-       }
+       if (str && !strcmp("Linux", str))
+               acpi_cmdline_osi_linux(1);
+       else if (str && !strcmp("!Linux", str))
+               acpi_cmdline_osi_linux(0);
+       else
+               acpi_osi_setup(str);
 
        return 1;
 }
 
-__setup("acpi_osi=", acpi_osi_setup);
+__setup("acpi_osi=", osi_setup);
 
 /* enable serialization to combat AE_ALREADY_EXISTS errors */
 static int __init acpi_serialize_setup(char *str)
@@ -1530,7 +1571,7 @@ acpi_status __init acpi_os_initialize(void)
        return AE_OK;
 }
 
-acpi_status acpi_os_initialize1(void)
+acpi_status __init acpi_os_initialize1(void)
 {
        kacpid_wq = create_workqueue("kacpid");
        kacpi_notify_wq = create_workqueue("kacpi_notify");
index 67dedee..4c9c2fb 100644 (file)
@@ -213,11 +213,13 @@ static int acpi_power_on(acpi_handle handle)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
+               if (result)
+                       resource->ref_count--;
        }
 
        mutex_unlock(&resource->resource_lock);
 
-       return 0;
+       return result;
 }
 
 static int acpi_power_off_device(acpi_handle handle)
@@ -465,10 +467,12 @@ int acpi_power_transition(struct acpi_device *device, int state)
        struct acpi_handle_list *tl = NULL;     /* Target Resources */
        int i = 0;
 
-
        if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
                return -EINVAL;
 
+       if (device->power.state == state)
+               return 0;
+
        if ((device->power.state < ACPI_STATE_D0)
            || (device->power.state > ACPI_STATE_D3))
                return -ENODEV;
@@ -488,10 +492,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
                        goto end;
        }
 
-       if (device->power.state == state) {
-               goto end;
-       }
-
        /*
         * Then we dereference all power resources used in the current list.
         */
index fde49b9..79cb653 100644 (file)
@@ -156,15 +156,6 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
        return 0;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-       return -ENODEV;
-}
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-       return -ENODEV;
-}
-
 #endif
 
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
index 721d93b..febb153 100644 (file)
@@ -27,8 +27,6 @@
 
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
        union acpi_object in_arg = { ACPI_TYPE_INTEGER };
@@ -81,6 +79,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
 }
 
 #ifdef CONFIG_ACPI_SLEEP
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -427,6 +427,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-NW130D",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index 46b9476..f9b983a 100644 (file)
@@ -154,7 +154,7 @@ static int __init adummy_init(void)
                err = -ENOMEM;
                goto out;
        }
-       atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL);
        if (!atm_dev) {
                printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n");
                err = -ENODEV;
index a33896a..ffe9b65 100644 (file)
@@ -2244,7 +2244,8 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
                goto out_reset;
        }
 
-       dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register (DEV_LABEL, &pci_dev->dev, &amb_ops, -1,
+                                        NULL);
        if (!dev->atm_dev) {
                PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index b910181..2b464b6 100644 (file)
@@ -366,7 +366,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result)
        if (!dev_data)
                return -ENOMEM;
 
-       dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
+       dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL);
        if (!dev) {
                kfree(dev_data);
                return itf == -1 ? -ENOMEM : -EBUSY;
index 97c5898..c495fae 100644 (file)
@@ -2244,7 +2244,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
                    &zeroes);
                if (!cpu_zeroes) goto out1;
        }
-       dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev) goto out2;
        pci_set_drvdata(pci_dev, dev);
        eni_dev->pci_dev = pci_dev;
index 5d86bb8..7d912ba 100644 (file)
@@ -1911,7 +1911,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev,
                    fs_dev, sizeof (struct fs_dev));
        if (!fs_dev)
                goto err_out;
-       atm_dev = atm_dev_register("fs", &ops, -1, NULL);
+       atm_dev = atm_dev_register("fs", &pci_dev->dev, &ops, -1, NULL);
        if (!atm_dev)
                goto err_out_free_fs_dev;
   
index c8fc69c..962c309 100644 (file)
@@ -2567,14 +2567,14 @@ release:
 
 
 static int __devinit
-fore200e_register(struct fore200e* fore200e)
+fore200e_register(struct fore200e* fore200e, struct device *parent)
 {
     struct atm_dev* atm_dev;
 
     DPRINTK(2, "device %s being registered\n", fore200e->name);
 
-    atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1,
-      NULL); 
+    atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops,
+                               -1, NULL);
     if (atm_dev == NULL) {
        printk(FORE200E "unable to register device %s\n", fore200e->name);
        return -ENODEV;
@@ -2594,9 +2594,9 @@ fore200e_register(struct fore200e* fore200e)
 
 
 static int __devinit
-fore200e_init(struct fore200e* fore200e)
+fore200e_init(struct fore200e* fore200e, struct device *parent)
 {
-    if (fore200e_register(fore200e) < 0)
+    if (fore200e_register(fore200e, parent) < 0)
        return -ENODEV;
     
     if (fore200e->bus->configure(fore200e) < 0)
@@ -2662,7 +2662,7 @@ static int __devinit fore200e_sba_probe(struct platform_device *op,
 
        sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-       err = fore200e_init(fore200e);
+       err = fore200e_init(fore200e, &op->dev);
        if (err < 0) {
                fore200e_shutdown(fore200e);
                kfree(fore200e);
@@ -2740,7 +2740,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent
 
     sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-    err = fore200e_init(fore200e);
+    err = fore200e_init(fore200e, &pci_dev->dev);
     if (err < 0) {
        fore200e_shutdown(fore200e);
        goto out_free;
index 801e8b6..6cf59bf 100644 (file)
@@ -366,7 +366,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
                goto init_one_failure;
        }
 
-       atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL);
        if (!atm_dev) {
                err = -ENODEV;
                goto init_one_failure;
index a957904..24761e1 100644 (file)
@@ -2733,7 +2733,8 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_
        PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
               iobase, irq, membase);
 
-       dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1,
+                                       NULL);
        if (!(dev->atm_dev)) {
                PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index bce5732..bfb7fee 100644 (file)
@@ -3698,7 +3698,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                goto err_out_iounmap;
        }
 
-       dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
+       dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
+                              NULL);
        if (!dev) {
                printk("%s: can't register atm device\n", card->name);
                err = -EIO;
index 9309d47..7292540 100644 (file)
@@ -3172,7 +3172,7 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
                ret = -ENODEV;
                goto err_out_free_iadev;
        }
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
        if (!dev) {
                ret = -ENOMEM;
                goto err_out_disable_dev;
index cbe15a8..a395c9a 100644 (file)
@@ -2591,7 +2591,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
                return -ENOMEM;
        }
 
-       atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL);
        if (atmdev == NULL) {
                printk(KERN_ERR DEV_LABEL
                    ": couldn't register atm device!\n");
index 2f3516b..6b313ee 100644 (file)
@@ -771,7 +771,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
        }
 
        /* Register device */
-       card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);
+       card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
+                                       -1, NULL);
        if (card->atmdev == NULL) {
                printk("nicstar%d: can't register device.\n", i);
                error = 17;
index 2e08c99..73fb1c4 100644 (file)
@@ -166,7 +166,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
 static void release_vccs(struct atm_dev *dev);
-static int atm_init(struct solos_card *);
+static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
 static void solos_bh(unsigned long);
@@ -1210,7 +1210,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (db_firmware_upgrade)
                flash_upgrade(card, 3);
 
-       err = atm_init(card);
+       err = atm_init(card, &dev->dev);
        if (err)
                goto out_free_irq;
 
@@ -1233,7 +1233,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        return err;
 }
 
-static int atm_init(struct solos_card *card)
+static int atm_init(struct solos_card *card, struct device *parent)
 {
        int i;
 
@@ -1244,7 +1244,7 @@ static int atm_init(struct solos_card *card)
                skb_queue_head_init(&card->tx_queue[i]);
                skb_queue_head_init(&card->cli_queue[i]);
 
-               card->atmdev[i] = atm_dev_register("solos-pci", &fpga_ops, -1, NULL);
+               card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL);
                if (!card->atmdev[i]) {
                        dev_err(&card->dev->dev, "Could not register ATM device %d\n", i);
                        atm_remove(card);
index 4e885d2..6249179 100644 (file)
@@ -1597,7 +1597,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
                goto out;
        }
 
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev)
                goto out_free;
 
index 4f9e22f..657873e 100644 (file)
@@ -72,7 +72,7 @@ struct blk_shadow {
 static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
-#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
+#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE)
 
 /*
  * We have one of these per vbd, whether ide, scsi or 'other'.  They
index 128cae4..949ed09 100644 (file)
 static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 */
        { USB_DEVICE(0x0CF3, 0x3000) },
+
+       /* Atheros AR3011 with sflash firmware*/
+       { USB_DEVICE(0x0CF3, 0x3002) },
+
        { }     /* Terminating entry */
 };
 
index ab3894f..1da773f 100644 (file)
@@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = {
        /* Broadcom BCM2033 without firmware */
        { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
+       /* Atheros 3011 with sflash firmware */
+       { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
+
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -239,7 +242,8 @@ static void btusb_intr_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -323,7 +327,8 @@ static void btusb_bulk_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -412,7 +417,8 @@ static void btusb_isoc_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
index e16c3fa..05117f1 100644 (file)
@@ -36,6 +36,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
 
 static struct cn_dev cdev;
 
index a8a84f4..64b21f5 100644 (file)
@@ -1,8 +1,8 @@
 ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-       EXTRA_CFLAGS    += -DDEBUG
+       ccflags-y       += -DDEBUG
 endif
 ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-       EXTRA_CFLAGS    += -DVERBOSE_DEBUG
+       ccflags-y       += -DVERBOSE_DEBUG
 endif
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
index a0f3e6a..ea0ee81 100644 (file)
@@ -722,7 +722,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        desc->lli.daddr = mem;
                        desc->lli.ctrla = ctrla
                                        | ATC_DST_WIDTH(mem_width)
-                                       | len >> mem_width;
+                                       | len >> reg_width;
                        desc->lli.ctrlb = ctrlb;
 
                        if (!first) {
index 286c3ac..e5e172d 100644 (file)
@@ -50,9 +50,11 @@ static void dma_init(struct fsldma_chan *chan)
                 * EIE - Error interrupt enable
                 * EOSIE - End of segments interrupt enable (basic mode)
                 * EOLNIE - End of links interrupt enable
+                * BWC - Bandwidth sharing among channels
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
-                               | FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+                               | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+                               | FSL_DMA_MR_EOSIE, 32);
                break;
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
index cb4d6ff..ba9f403 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author:
  *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
 #define FSL_DMA_MR_DAHE                0x00002000
 #define FSL_DMA_MR_SAHE                0x00001000
 
+/*
+ * Bandwidth/pause control determines how many bytes a given
+ * channel is allowed to transfer before the DMA engine pauses
+ * the current channel and switches to the next channel
+ */
+#define FSL_DMA_MR_BWC         0x08000000
+
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE       0x00000080
 #define FSL_DMA_MR_PRC_RM      0x00000800
index f629e49..e53d438 100644 (file)
@@ -379,7 +379,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
        return 0;
 
 err_init:
-       while (i-- >= 0) {
+       while (--i >= 0) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
                imx_dma_free(imxdmac->imxdma_channel);
        }
index 0834323..d0602dd 100644 (file)
@@ -951,7 +951,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
                int param;
 
-               bd->buffer_addr = sgl->dma_address;
+               bd->buffer_addr = sg->dma_address;
 
                count = sg->length;
 
@@ -1385,7 +1385,7 @@ static int __init sdma_module_init(void)
 {
        return platform_driver_probe(&sdma_driver, sdma_probe);
 }
-subsys_initcall(sdma_module_init);
+module_init(sdma_module_init);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX SDMA driver");
index 338bc4e..3109bd9 100644 (file)
@@ -1075,7 +1075,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
        if (NULL == dma->dma_pool) {
                pr_err("ERR_MDMA:pci_pool_create failed\n");
                err = -ENOMEM;
-               kfree(dma);
                goto err_dma_pool;
        }
 
@@ -1186,7 +1185,6 @@ err_engine:
        free_irq(pdev->irq, dma);
 err_irq:
        pci_pool_destroy(dma->dma_pool);
-       kfree(dma);
 err_dma_pool:
        pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
        return err;
@@ -1413,7 +1411,7 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
        .runtime_idle = dma_runtime_idle,
 };
 
-static struct pci_driver intel_mid_dma_pci = {
+static struct pci_driver intel_mid_dma_pci_driver = {
        .name           =       "Intel MID DMA",
        .id_table       =       intel_mid_dma_ids,
        .probe          =       intel_mid_dma_probe,
@@ -1431,13 +1429,13 @@ static int __init intel_mid_dma_init(void)
 {
        pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
                        INTEL_MID_DMA_DRIVER_VERSION);
-       return pci_register_driver(&intel_mid_dma_pci);
+       return pci_register_driver(&intel_mid_dma_pci_driver);
 }
 fs_initcall(intel_mid_dma_init);
 
 static void __exit intel_mid_dma_exit(void)
 {
-       pci_unregister_driver(&intel_mid_dma_pci);
+       pci_unregister_driver(&intel_mid_dma_pci_driver);
 }
 module_exit(intel_mid_dma_exit);
 
index 8997d3f..0ff7270 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
-ioatdma-objs := pci.o dma.o dma_v2.o dma_v3.o dca.o
+ioatdma-y := pci.o dma.o dma_v2.o dma_v3.o dca.o
index 92b6790..c064c89 100644 (file)
@@ -259,11 +259,6 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
                return;
        }
 
-       channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
-       channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
-       channel_writel(pd_chan, SIZE, desc->regs.size);
-       channel_writel(pd_chan, NEXT, desc->regs.next);
-
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n",
                pd_chan->chan.chan_id, desc->regs.dev_addr);
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n",
@@ -273,10 +268,16 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n",
                pd_chan->chan.chan_id, desc->regs.next);
 
-       if (list_empty(&desc->tx_list))
+       if (list_empty(&desc->tx_list)) {
+               channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
+               channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
+               channel_writel(pd_chan, SIZE, desc->regs.size);
+               channel_writel(pd_chan, NEXT, desc->regs.next);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_ONESHOT);
-       else
+       } else {
+               channel_writel(pd_chan, NEXT, desc->txd.phys);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG);
+       }
 
        val = dma_readl(pd, CTL2);
        val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id);
index 0d58a4a..cef5845 100644 (file)
@@ -4449,9 +4449,8 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
 
        if (!request_mem_region(res.start, resource_size(&res),
                                dev_driver_string(&ofdev->dev))) {
-               dev_err(&ofdev->dev, "failed to request memory region "
-                       "(0x%016llx-0x%016llx)\n",
-                       (u64)res.start, (u64)res.end);
+               dev_err(&ofdev->dev, "failed to request memory region %pR\n",
+                       &res);
                initcode = PPC_ADMA_INIT_MEMREG;
                ret = -EBUSY;
                goto out;
index 8521401..eca9ba1 100644 (file)
@@ -1572,7 +1572,7 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
        debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
                        hole_off, hole_valid, intlv_sel);
 
-       if (intlv_en ||
+       if (intlv_en &&
            (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
 
index d7ca43a..251440c 100644 (file)
 #define MC_PROC_NAME_MAX_LEN   7
 
 #if PAGE_SHIFT < 20
-#define PAGES_TO_MiB( pages )  ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
-#define MiB_TO_PAGES(mb)       ((mb) >> (20 - PAGE_SHIFT))
+#define PAGES_TO_MiB(pages)    ((pages) >> (20 - PAGE_SHIFT))
+#define MiB_TO_PAGES(mb)       ((mb) << (20 - PAGE_SHIFT))
 #else                          /* PAGE_SHIFT > 20 */
-#define PAGES_TO_MiB( pages )  ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define PAGES_TO_MiB(pages)    ((pages) << (PAGE_SHIFT - 20))
 #define MiB_TO_PAGES(mb)       ((mb) >> (PAGE_SHIFT - 20))
 #endif
 
index ba6586a..795ea69 100644 (file)
@@ -586,14 +586,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
                return NULL;
        }
 
-       /* marking MCI offline */
-       mci->op_state = OP_OFFLINE;
-
        del_mc_from_global_list(mci);
        mutex_unlock(&mem_ctls_mutex);
 
-       /* flush workq processes and remove sysfs */
+       /* flush workq processes */
        edac_mc_workq_teardown(mci);
+
+       /* marking MCI offline */
+       mci->op_state = OP_OFFLINE;
+
+       /* remove from sysfs */
        edac_remove_sysfs_mci_device(mci);
 
        edac_printk(KERN_INFO, EDAC_MC,
index 84eb607..e3c8b60 100644 (file)
@@ -242,6 +242,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 
@@ -253,18 +254,34 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
-       unsigned short vendor, device, flags;
+       unsigned short vendor, device, revision, flags;
 } ohci_quirks[] = {
-       {PCI_VENDOR_ID_TI,      PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
-                                                           QUIRK_RESET_PACKET |
-                                                           QUIRK_NO_1394A},
-       {PCI_VENDOR_ID_TI,      PCI_ANY_ID,     QUIRK_RESET_PACKET},
-       {PCI_VENDOR_ID_AL,      PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
-       {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_VIA,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_RICOH,   PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_APPLE,   PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
+       {PCI_VENDOR_ID_AL, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, PCI_ANY_ID,
+               QUIRK_BE_HEADERS},
+
+       {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+
+       {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
+       {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 };
 
 /* This overrides anything that was found in ohci_quirks[]. */
@@ -2927,9 +2944,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
        }
 
        for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
-               if (ohci_quirks[i].vendor == dev->vendor &&
-                   (ohci_quirks[i].device == dev->device ||
-                    ohci_quirks[i].device == (unsigned short)PCI_ANY_ID)) {
+               if ((ohci_quirks[i].vendor == dev->vendor) &&
+                   (ohci_quirks[i].device == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].device == dev->device) &&
+                   (ohci_quirks[i].revision == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].revision >= dev->revision)) {
                        ohci->quirks = ohci_quirks[i].flags;
                        break;
                }
index 6985cb1..2baa670 100644 (file)
@@ -156,12 +156,12 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
        { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
        { DRM_MODE_CONNECTOR_Component, "Component", 0 },
-       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
-       { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
-       { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
-       { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
+       { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+       { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
-       { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 },
+       { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
index 722700d..16d5155 100644 (file)
@@ -628,7 +628,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        if ((seq - vblwait->request.sequence) <= (1 << 23)) {
                e->event.tv_sec = now.tv_sec;
                e->event.tv_usec = now.tv_usec;
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                list_add_tail(&e->base.link, &e->base.file_priv->event_list);
                wake_up_interruptible(&e->base.file_priv->event_wait);
                trace_drm_vblank_event_delivered(current->pid, pipe,
@@ -645,7 +645,7 @@ err_unlock:
        spin_unlock_irqrestore(&dev->event_lock, flags);
        kfree(e);
 err_put:
-       drm_vblank_put(dev, e->pipe);
+       drm_vblank_put(dev, pipe);
        return ret;
 }
 
index a322d4f..4d7a2e1 100644 (file)
@@ -878,12 +878,15 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
        u32 tmp;
 
        /* flush hdp cache so updates hit vram */
-       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+           !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
                u32 tmp;
 
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
                 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+                * This seems to cause problems on some AGP cards. Just use the old
+                * method for them.
                 */
                WREG32(HDP_DEBUG1, 0);
                tmp = readl((void __iomem *)ptr);
@@ -3485,10 +3488,12 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
 void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
 {
        /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
-        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
+        * This seems to cause problems on some AGP cards. Just use the old
+        * method for them.
         */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
-           rdev->vram_scratch.ptr) {
+           rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
                u32 tmp;
 
index 4bf969c..be0fdd5 100644 (file)
@@ -916,27 +916,27 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        int nr = sensor_attr->index;
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1026_data *data = i2c_get_clientdata(client);
-       int val, orig_div, new_div, shift;
+       int val, orig_div, new_div;
 
        val = simple_strtol(buf, NULL, 10);
        new_div = DIV_TO_REG(val);
-       if (new_div == 0) {
-               return -EINVAL;
-       }
+
        mutex_lock(&data->update_lock);
        orig_div = data->fan_div[nr];
        data->fan_div[nr] = DIV_FROM_REG(new_div);
 
        if (nr < 4) { /* 0 <= nr < 4 */
-               shift = 2 * nr;
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[0]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[1]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[2]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[3]) << 6));
        } else { /* 3 < nr < 8 */
-               shift = 2 * (nr - 4);
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[4]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[5]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[6]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[7]) << 6));
        }
 
        if (data->fan_div[nr] != orig_div) {
index 14a5d98..a428a92 100644 (file)
@@ -187,6 +187,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
+#define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
 
 #define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
@@ -251,12 +252,16 @@ struct it87_data {
        u8 fan_main_ctrl;       /* Register value */
        u8 fan_ctl;             /* Register value */
 
-       /* The following 3 arrays correspond to the same registers. The
-        * meaning of bits 6-0 depends on the value of bit 7, and we want
-        * to preserve settings on mode changes, so we have to track all
-        * values separately. */
+       /* The following 3 arrays correspond to the same registers up to
+        * the IT8720F. The meaning of bits 6-0 depends on the value of bit
+        * 7, and we want to preserve settings on mode changes, so we have
+        * to track all values separately.
+        * Starting with the IT8721F, the manual PWM duty cycles are stored
+        * in separate registers (8-bit values), so the separate tracking
+        * is no longer needed, but it is still done to keep the driver
+        * simple. */
        u8 pwm_ctrl[3];         /* Register value */
-       u8 pwm_duty[3];         /* Manual PWM value set by user (bit 6-0) */
+       u8 pwm_duty[3];         /* Manual PWM value set by user */
        u8 pwm_temp_map[3];     /* PWM to temp. chan. mapping (bits 1-0) */
 
        /* Automatic fan speed control registers */
@@ -832,7 +837,9 @@ static ssize_t set_pwm_enable(struct device *dev,
                                 data->fan_main_ctrl);
        } else {
                if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       data->pwm_ctrl[nr] = data->type == it8721 ?
+                                            data->pwm_temp_map[nr] :
+                                            data->pwm_duty[nr];
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
@@ -858,12 +865,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       data->pwm_duty[nr] = pwm_to_reg(data, val);
-       /* If we are in manual mode, write the duty cycle immediately;
-        * otherwise, just store it for later use. */
-       if (!(data->pwm_ctrl[nr] & 0x80)) {
-               data->pwm_ctrl[nr] = data->pwm_duty[nr];
-               it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+       if (data->type == it8721) {
+               /* If we are in automatic mode, the PWM duty cycle register
+                * is read-only so we can't write the value */
+               if (data->pwm_ctrl[nr] & 0x80) {
+                       mutex_unlock(&data->update_lock);
+                       return -EBUSY;
+               }
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               it87_write_value(data, IT87_REG_PWM_DUTY(nr),
+                                data->pwm_duty[nr]);
+       } else {
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               /* If we are in manual mode, write the duty cycle immediately;
+                * otherwise, just store it for later use. */
+               if (!(data->pwm_ctrl[nr] & 0x80)) {
+                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       it87_write_value(data, IT87_REG_PWM(nr),
+                                        data->pwm_ctrl[nr]);
+               }
        }
        mutex_unlock(&data->update_lock);
        return count;
@@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev)
         *   channels to use when later setting to automatic mode later.
         *   Use a 1:1 mapping by default (we are clueless.)
         * In both cases, the value can (and should) be changed by the user
-        * prior to switching to a different mode. */
+        * prior to switching to a different mode.
+        * Note that this is no longer needed for the IT8721F and later, as
+        * these have separate registers for the temperature mapping and the
+        * manual duty cycle. */
        for (i = 0; i < 3; i++) {
                data->pwm_temp_map[i] = i;
                data->pwm_duty[i] = 0x7f;       /* Full speed */
@@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
        data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-       if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+       if (data->type == it8721) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-       else                            /* Manual mode */
-               data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+               data->pwm_duty[nr] = it87_read_value(data,
+                                                    IT87_REG_PWM_DUTY(nr));
+       } else {
+               if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+               else                            /* Manual mode */
+                       data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+       }
 
        if (has_old_autopwm(data)) {
                int i;
index 00d975e..c7e6d8e 100644 (file)
@@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm,      (1 << 2),       LTC4215_STATUS);
 
 /* Power (virtual) */
 LTC4215_POWER(power1_input);
-LTC4215_ALARM(power1_alarm,    (1 << 3),       LTC4215_STATUS);
 
 /* Input Voltage */
 LTC4215_VOLTAGE(in1_input,                     LTC4215_ADIN);
@@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm,        (1 << 1),       LTC4215_STATUS);
 
 /* Output Voltage */
 LTC4215_VOLTAGE(in2_input,                     LTC4215_SOURCE);
+LTC4215_ALARM(in2_min_alarm,   (1 << 3),       LTC4215_STATUS);
 
 /* Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
@@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = {
        &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 
        &sensor_dev_attr_power1_input.dev_attr.attr,
-       &sensor_dev_attr_power1_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
 
        NULL,
 };
index 80f70d3..c714927 100644 (file)
@@ -999,7 +999,7 @@ static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
 
        /* Initialize struct members */
        snprintf(mrst->adap.name, sizeof(mrst->adap.name),
-               "MRST/Medfield I2C at %lx", start);
+               "Intel MID I2C at %lx", start);
        mrst->adap.owner = THIS_MODULE;
        mrst->adap.algo = &intel_mid_i2c_algorithm;
        mrst->adap.dev.parent = &dev->dev;
index 41665d2..c131d58 100644 (file)
@@ -273,8 +273,6 @@ static int intel_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
 
-       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
-               lapic_timer_reliable_states = 0xFFFFFFFF;
 
        if (boot_cpu_data.x86 != 6)     /* family 6 */
                return -ENODEV;
@@ -286,8 +284,6 @@ static int intel_idle_probe(void)
        case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
        case 0x2E:      /* Nehalem-EX Xeon */
        case 0x2F:      /* Westmere-EX Xeon */
-               lapic_timer_reliable_states = (1 << 1);  /* C1 */
-
        case 0x25:      /* Westmere */
        case 0x2C:      /* Westmere */
                cpuidle_state_table = nehalem_cstates;
@@ -295,7 +291,6 @@ static int intel_idle_probe(void)
 
        case 0x1C:      /* 28 - Atom Processor */
        case 0x26:      /* 38 - Lincroft Atom Processor */
-               lapic_timer_reliable_states = (1 << 1); /* C1 */
                cpuidle_state_table = atom_cstates;
                break;
 
@@ -303,10 +298,6 @@ static int intel_idle_probe(void)
        case 0x2D:      /* SNB Xeon */
                cpuidle_state_table = snb_cstates;
                break;
-#ifdef FUTURE_USE
-       case 0x17:      /* 23 - Core 2 Duo */
-               lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
-#endif
 
        default:
                pr_debug(PREFIX "does not run on family %d model %d\n",
@@ -314,6 +305,9 @@ static int intel_idle_probe(void)
                return -ENODEV;
        }
 
+       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
+               lapic_timer_reliable_states = 0xFFFFFFFF;
+
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
index b342248..c426992 100644 (file)
@@ -893,68 +893,81 @@ out:
        return ret ? ret : in_len;
 }
 
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+       struct ib_uverbs_wc tmp;
+
+       tmp.wr_id               = wc->wr_id;
+       tmp.status              = wc->status;
+       tmp.opcode              = wc->opcode;
+       tmp.vendor_err          = wc->vendor_err;
+       tmp.byte_len            = wc->byte_len;
+       tmp.ex.imm_data         = (__u32 __force) wc->ex.imm_data;
+       tmp.qp_num              = wc->qp->qp_num;
+       tmp.src_qp              = wc->src_qp;
+       tmp.wc_flags            = wc->wc_flags;
+       tmp.pkey_index          = wc->pkey_index;
+       tmp.slid                = wc->slid;
+       tmp.sl                  = wc->sl;
+       tmp.dlid_path_bits      = wc->dlid_path_bits;
+       tmp.port_num            = wc->port_num;
+       tmp.reserved            = 0;
+
+       if (copy_to_user(dest, &tmp, sizeof tmp))
+               return -EFAULT;
+
+       return 0;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
 {
        struct ib_uverbs_poll_cq       cmd;
-       struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_uverbs_poll_cq_resp  resp;
+       u8 __user                     *header_ptr;
+       u8 __user                     *data_ptr;
        struct ib_cq                  *cq;
-       struct ib_wc                  *wc;
-       int                            ret = 0;
-       int                            i;
-       int                            rsize;
+       struct ib_wc                   wc;
+       int                            ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
-       if (!wc)
-               return -ENOMEM;
-
-       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
-       resp = kmalloc(rsize, GFP_KERNEL);
-       if (!resp) {
-               ret = -ENOMEM;
-               goto out_wc;
-       }
-
        cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-       if (!cq) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!cq)
+               return -EINVAL;
 
-       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+       /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+       header_ptr = (void __user *)(unsigned long) cmd.response;
+       data_ptr = header_ptr + sizeof resp;
 
-       put_cq_read(cq);
+       memset(&resp, 0, sizeof resp);
+       while (resp.count < cmd.ne) {
+               ret = ib_poll_cq(cq, 1, &wc);
+               if (ret < 0)
+                       goto out_put;
+               if (!ret)
+                       break;
+
+               ret = copy_wc_to_user(data_ptr, &wc);
+               if (ret)
+                       goto out_put;
 
-       for (i = 0; i < resp->count; i++) {
-               resp->wc[i].wr_id          = wc[i].wr_id;
-               resp->wc[i].status         = wc[i].status;
-               resp->wc[i].opcode         = wc[i].opcode;
-               resp->wc[i].vendor_err     = wc[i].vendor_err;
-               resp->wc[i].byte_len       = wc[i].byte_len;
-               resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
-               resp->wc[i].qp_num         = wc[i].qp->qp_num;
-               resp->wc[i].src_qp         = wc[i].src_qp;
-               resp->wc[i].wc_flags       = wc[i].wc_flags;
-               resp->wc[i].pkey_index     = wc[i].pkey_index;
-               resp->wc[i].slid           = wc[i].slid;
-               resp->wc[i].sl             = wc[i].sl;
-               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
-               resp->wc[i].port_num       = wc[i].port_num;
+               data_ptr += sizeof(struct ib_uverbs_wc);
+               ++resp.count;
        }
 
-       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+       if (copy_to_user(header_ptr, &resp, sizeof resp)) {
                ret = -EFAULT;
+               goto out_put;
+       }
 
-out:
-       kfree(resp);
+       ret = in_len;
 
-out_wc:
-       kfree(wc);
-       return ret ? ret : in_len;
+out_put:
+       put_cq_read(cq);
+       return ret;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
index e3f7fc6..68f09a8 100644 (file)
@@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
-static int evdev_handle_get_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
        int error;
 
-       memset(&ke, 0, sizeof(ke));
-
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       /* legacy case */
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+       if (put_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       return 0;
+}
 
-               if (put_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
+       int error;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       if (copy_to_user(p, &ke, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_to_user(p, &ke, size))
-                       return -EFAULT;
-       }
        return 0;
 }
 
-static int evdev_handle_set_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
-
-       memset(&ke, 0, sizeof(ke));
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
 
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       if (get_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               if (get_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+       return input_set_keycode(dev, &ke);
+}
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
-
-               if (ke.len > sizeof(ke.scancode))
-                       return -EINVAL;
-       }
+       if (ke.len > sizeof(ke.scancode))
+               return -EINVAL;
 
        return input_set_keycode(dev, &ke);
 }
@@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return evdev_grab(evdev, client);
                else
                        return evdev_ungrab(evdev, client);
+
+       case EVIOCGKEYCODE:
+               return evdev_handle_get_keycode(dev, p);
+
+       case EVIOCSKEYCODE:
+               return evdev_handle_set_keycode(dev, p);
+
+       case EVIOCGKEYCODE_V2:
+               return evdev_handle_get_keycode_v2(dev, p);
+
+       case EVIOCSKEYCODE_V2:
+               return evdev_handle_set_keycode_v2(dev, p);
        }
 
        size = _IOC_SIZE(cmd);
@@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
-
-       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
-               return evdev_handle_get_keycode(dev, p, size);
-
-       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
-               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 4852b44..435b0af 100644 (file)
@@ -1436,6 +1436,8 @@ static struct wacom_features wacom_features_0xD2 =
        { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+static const struct wacom_features wacom_features_0xD4 =
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD8 =
        { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xDA =
@@ -1510,6 +1512,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
+       { USB_DEVICE_WACOM(0xD4) },
        { USB_DEVICE_WACOM(0xD8) },
        { USB_DEVICE_WACOM(0xDA) },
        { USB_DEVICE_WACOM(0xDB) },
index 84c46a1..e71c5fa 100644 (file)
@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err)
        bio_put(bio);
 }
 
-static void submit_flushes(mddev_t *mddev)
+static void md_submit_flush_data(struct work_struct *ws);
+
+static void submit_flushes(struct work_struct *ws)
 {
+       mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        mdk_rdev_t *rdev;
 
+       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
+       atomic_set(&mddev->flush_pending, 1);
        rcu_read_lock();
        list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
                if (rdev->raid_disk >= 0 &&
@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev)
                        rdev_dec_pending(rdev, mddev);
                }
        rcu_read_unlock();
+       if (atomic_dec_and_test(&mddev->flush_pending))
+               queue_work(md_wq, &mddev->flush_work);
 }
 
 static void md_submit_flush_data(struct work_struct *ws)
@@ -404,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws)
        mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        struct bio *bio = mddev->flush_bio;
 
-       atomic_set(&mddev->flush_pending, 1);
-
        if (bio->bi_size == 0)
                /* an empty barrier - all done */
                bio_endio(bio, 0);
@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws)
                if (mddev->pers->make_request(mddev, bio))
                        generic_make_request(bio);
        }
-       if (atomic_dec_and_test(&mddev->flush_pending)) {
-               mddev->flush_bio = NULL;
-               wake_up(&mddev->sb_wait);
-       }
+
+       mddev->flush_bio = NULL;
+       wake_up(&mddev->sb_wait);
 }
 
 void md_flush_request(mddev_t *mddev, struct bio *bio)
@@ -429,13 +433,8 @@ void md_flush_request(mddev_t *mddev, struct bio *bio)
        mddev->flush_bio = bio;
        spin_unlock_irq(&mddev->write_lock);
 
-       atomic_set(&mddev->flush_pending, 1);
-       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
-
-       submit_flushes(mddev);
-
-       if (atomic_dec_and_test(&mddev->flush_pending))
-               queue_work(md_wq, &mddev->flush_work);
+       INIT_WORK(&mddev->flush_work, submit_flushes);
+       queue_work(md_wq, &mddev->flush_work);
 }
 EXPORT_SYMBOL(md_flush_request);
 
@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                                PTR_ERR(rdev));
                        return PTR_ERR(rdev);
                }
-               /* set save_raid_disk if appropriate */
+               /* set saved_raid_disk if appropriate */
                if (!mddev->persistent) {
                        if (info->state & (1<<MD_DISK_SYNC)  &&
                            info->raid_disk < mddev->raid_disks)
@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                } else
                        super_types[mddev->major_version].
                                validate_super(mddev, rdev);
-               rdev->saved_raid_disk = rdev->raid_disk;
+               if (test_bit(In_sync, &rdev->flags))
+                       rdev->saved_raid_disk = rdev->raid_disk;
+               else
+                       rdev->saved_raid_disk = -1;
 
                clear_bit(In_sync, &rdev->flags); /* just to be sure */
                if (info->state & (1<<MD_DISK_WRITEMOSTLY))
@@ -6042,9 +6044,8 @@ static int md_thread(void * arg)
                         || kthread_should_stop(),
                         thread->timeout);
 
-               clear_bit(THREAD_WAKEUP, &thread->flags);
-
-               thread->run(thread->mddev);
+               if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
+                       thread->run(thread->mddev);
        }
 
        return 0;
index c67aa54..0641674 100644 (file)
@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev)
        return 0;
 
 out_free_conf:
+       md_unregister_thread(mddev->thread);
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
-       md_unregister_thread(mddev->thread);
 out:
        return -EIO;
 }
index 5bf4985..05e832f 100644 (file)
@@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
@@ -412,13 +412,6 @@ static int __init rtrack_init(void)
        rt->vdev.release = video_device_release_empty;
        video_set_drvdata(&rt->vdev, rt);
 
-       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(&rt->v4l2_dev);
-               release_region(rt->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
-
        /* Set up the I/O locking */
 
        mutex_init(&rt->lock);
@@ -430,6 +423,13 @@ static int __init rtrack_init(void)
        sleep_delay(2000000);   /* make sure it's totally down  */
        outb(0xc0, rt->io);             /* steady volume, mute card     */
 
+       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(&rt->v4l2_dev);
+               release_region(rt->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
+
        return 0;
 }
 
index c223113..dd8a6ab 100644 (file)
@@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations aztech_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
@@ -375,6 +375,8 @@ static int __init aztech_init(void)
        az->vdev.ioctl_ops = &aztech_ioctl_ops;
        az->vdev.release = video_device_release_empty;
        video_set_drvdata(&az->vdev, az);
+       /* mute card - prevents noisy bootups */
+       outb(0, az->io);
 
        if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -383,8 +385,6 @@ static int __init aztech_init(void)
        }
 
        v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
-       /* mute card - prevents noisy bootups */
-       outb(0, az->io);
        return 0;
 }
 
index b701ea6..bc9ad08 100644 (file)
@@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
        unsigned char readbuf[RDS_BUFFER];
        int i = 0;
 
+       mutex_lock(&dev->lock);
        if (dev->rdsstat == 0) {
-               mutex_lock(&dev->lock);
                dev->rdsstat = 1;
                outb(0x80, dev->io);        /* Select RDS fifo */
-               mutex_unlock(&dev->lock);
                init_timer(&dev->readtimer);
                dev->readtimer.function = cadet_handler;
                dev->readtimer.data = (unsigned long)dev;
@@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
                add_timer(&dev->readtimer);
        }
        if (dev->rdsin == dev->rdsout) {
+               mutex_unlock(&dev->lock);
                if (file->f_flags & O_NONBLOCK)
                        return -EWOULDBLOCK;
                interruptible_sleep_on(&dev->read_queue);
+               mutex_lock(&dev->lock);
        }
        while (i < count && dev->rdsin != dev->rdsout)
                readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+       mutex_unlock(&dev->lock);
 
        if (copy_to_user(data, readbuf, i))
                return -EFAULT;
@@ -525,9 +527,11 @@ static int cadet_open(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users++;
        if (1 == dev->users)
                init_waitqueue_head(&dev->read_queue);
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -535,11 +539,13 @@ static int cadet_release(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users--;
        if (0 == dev->users) {
                del_timer_sync(&dev->readtimer);
                dev->rdsstat = 0;
        }
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {
        .open           = cadet_open,
        .release        = cadet_release,
        .read           = cadet_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = cadet_poll,
 };
 
index 7903967..28fa85b 100644 (file)
@@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
 
 static const struct v4l2_file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
@@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev
        card->vdev.release = video_device_release_empty;
        video_set_drvdata(&card->vdev, card);
 
+       gemtek_pci_mute(card);
+
        if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
                goto err_video;
 
-       gemtek_pci_mute(card);
-
        v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
                pdev->revision, card->iobase, card->iobase + card->length - 1);
 
index 73985f6..2599364 100644 (file)
@@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)
 
 static const struct v4l2_file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -577,12 +577,6 @@ static int __init gemtek_init(void)
        gt->vdev.release = video_device_release_empty;
        video_set_drvdata(&gt->vdev, gt);
 
-       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(gt->io, 1);
-               return -EBUSY;
-       }
-
        /* Set defaults */
        gt->lastfreq = GEMTEK_LOWFREQ;
        gt->bu2614data = 0;
@@ -590,6 +584,12 @@ static int __init gemtek_init(void)
        if (initmute)
                gemtek_mute(gt);
 
+       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(gt->io, 1);
+               return -EBUSY;
+       }
+
        return 0;
 }
 
index 08f1051..6af61bf 100644 (file)
@@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maestro_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
@@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       if (!radio_power_on(dev)) {
+               retval = -EIO;
+               goto errfr1;
+       }
+
        retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                v4l2_err(v4l2_dev, "can't register video device!\n");
                goto errfr1;
        }
 
-       if (!radio_power_on(dev)) {
-               retval = -EIO;
-               goto errunr;
-       }
-
        v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
 
        return 0;
-errunr:
-       video_unregister_device(&dev->vdev);
 errfr1:
        v4l2_device_unregister(v4l2_dev);
 errfr:
index 255d40d..6459a22 100644 (file)
@@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
index 4ff8854..3fb76e3 100644 (file)
@@ -33,6 +33,7 @@ struct pcm20 {
        unsigned long freq;
        int muted;
        struct snd_miro_aci *aci;
+       struct mutex lock;
 };
 
 static struct pcm20 pcm20_card = {
@@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
 
 static const struct v4l2_file_operations pcm20_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -229,7 +230,7 @@ static int __init pcm20_init(void)
                return -ENODEV;
        }
        strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
-
+       mutex_init(&dev->lock);
 
        res = v4l2_device_register(NULL, v4l2_dev);
        if (res < 0) {
@@ -242,6 +243,7 @@ static int __init pcm20_init(void)
        dev->vdev.fops = &pcm20_fops;
        dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
+       dev->vdev.lock = &dev->lock;
        video_set_drvdata(&dev->vdev, dev);
 
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
index a79296a..8d6ea59 100644 (file)
@@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
@@ -315,6 +315,10 @@ static int __init rtrack2_init(void)
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       /* mute card - prevents noisy bootups */
+       outb(1, dev->io);
+       dev->muted = 1;
+
        mutex_init(&dev->lock);
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -324,10 +328,6 @@ static int __init rtrack2_init(void)
 
        v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
 
-       /* mute card - prevents noisy bootups */
-       outb(1, dev->io);
-       dev->muted = 1;
-
        return 0;
 }
 
index 985359d..b5a5f89 100644 (file)
@@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmi_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
@@ -382,6 +382,9 @@ static int __init fmi_init(void)
 
        mutex_init(&fmi->lock);
 
+       /* mute card - prevents noisy bootups */
+       fmi_mute(fmi);
+
        if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmi->io, 2);
@@ -391,8 +394,6 @@ static int __init fmi_init(void)
        }
 
        v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
-       /* mute card - prevents noisy bootups */
-       fmi_mute(fmi);
        return 0;
 }
 
index 52c7bbb..dc3f04c 100644 (file)
@@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
@@ -424,6 +424,10 @@ static int __init fmr2_init(void)
        fmr2->vdev.release = video_device_release_empty;
        video_set_drvdata(&fmr2->vdev, fmr2);
 
+       /* mute card - prevents noisy bootups */
+       fmr2_mute(fmr2->io);
+       fmr2_product_info(fmr2);
+
        if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmr2->io, 2);
@@ -431,11 +435,6 @@ static int __init fmr2_init(void)
        }
 
        v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
-       /* mute card - prevents noisy bootups */
-       mutex_lock(&fmr2->lock);
-       fmr2_mute(fmr2->io);
-       fmr2_product_info(fmr2);
-       mutex_unlock(&fmr2->lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
        return 0;
 }
index 03829e6..726d367 100644 (file)
@@ -53,7 +53,8 @@ struct radio_si4713_device {
 /* radio_si4713_fops - file operations interface */
 static const struct v4l2_file_operations radio_si4713_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       /* Note: locking is done at the subdev level in the i2c driver. */
+       .unlocked_ioctl = video_ioctl2,
 };
 
 /* Video4Linux Interface */
index 789d2ec..0e71d81 100644 (file)
@@ -142,7 +142,6 @@ struct tea5764_device {
        struct video_device             *videodev;
        struct tea5764_regs             regs;
        struct mutex                    mutex;
-       int                             users;
 };
 
 /* I2C code related */
@@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int tea5764_open(struct file *file)
-{
-       /* Currently we support only one device */
-       struct tea5764_device *radio = video_drvdata(file);
-
-       mutex_lock(&radio->mutex);
-       /* Only exclusive access */
-       if (radio->users) {
-               mutex_unlock(&radio->mutex);
-               return -EBUSY;
-       }
-       radio->users++;
-       mutex_unlock(&radio->mutex);
-       file->private_data = radio;
-       return 0;
-}
-
-static int tea5764_close(struct file *file)
-{
-       struct tea5764_device *radio = video_drvdata(file);
-
-       if (!radio)
-               return -ENODEV;
-       mutex_lock(&radio->mutex);
-       radio->users--;
-       mutex_unlock(&radio->mutex);
-       return 0;
-}
-
 /* File system interface */
 static const struct v4l2_file_operations tea5764_fops = {
        .owner          = THIS_MODULE,
-       .open           = tea5764_open,
-       .release        = tea5764_close,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
@@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        int ret;
 
        PDEBUG("probe");
-       radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+       radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
        if (!radio)
                return -ENOMEM;
 
@@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, radio);
        video_set_drvdata(radio->videodev, radio);
-
-       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
-       if (ret < 0) {
-               PWARN("Could not register video device!");
-               goto errrel;
-       }
+       radio->videodev->lock = &radio->mutex;
 
        /* initialize and power off the chip */
        tea5764_i2c_read(radio);
@@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        tea5764_mute(radio, 1);
        tea5764_power_down(radio);
 
+       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (ret < 0) {
+               PWARN("Could not register video device!");
+               goto errrel;
+       }
+
        PINFO("registered.");
        return 0;
 errrel:
index fc1c860..a326639 100644 (file)
@@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations terratec_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
@@ -389,6 +389,9 @@ static int __init terratec_init(void)
 
        mutex_init(&tt->lock);
 
+       /* mute card - prevents noisy bootups */
+       tt_write_vol(tt, 0);
+
        if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&tt->v4l2_dev);
                release_region(tt->io, 2);
@@ -396,9 +399,6 @@ static int __init terratec_init(void)
        }
 
        v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
-
-       /* mute card - prevents noisy bootups */
-       tt_write_vol(tt, 0);
        return 0;
 }
 
index b8bb3ef..a185610 100644 (file)
@@ -34,6 +34,7 @@ struct timbradio {
        struct v4l2_subdev      *sd_dsp;
        struct video_device     video_dev;
        struct v4l2_device      v4l2_dev;
+       struct mutex            lock;
 };
 
 
@@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
 
 static const struct v4l2_file_operations timbradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int __devinit timbradio_probe(struct platform_device *pdev)
@@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        }
 
        tr->pdata = *pdata;
+       mutex_init(&tr->lock);
 
        strlcpy(tr->video_dev.name, "Timberdale Radio",
                sizeof(tr->video_dev.name));
@@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
        tr->video_dev.release = video_device_release_empty;
        tr->video_dev.minor = -1;
+       tr->video_dev.lock = &tr->lock;
 
        strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
        err = v4l2_device_register(NULL, &tr->v4l2_dev);
index 9d6dcf8..22fa9cc 100644 (file)
@@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations trust_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops trust_ioctl_ops = {
@@ -396,14 +396,6 @@ static int __init trust_init(void)
        tr->vdev.release = video_device_release_empty;
        video_set_drvdata(&tr->vdev, tr);
 
-       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(tr->io, 2);
-               return -EINVAL;
-       }
-
-       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
-
        write_i2c(tr, 2, TDA7318_ADDR, 0x80);   /* speaker att. LF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xa0);   /* speaker att. RF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xc0);   /* speaker att. LR = 0 dB */
@@ -418,6 +410,14 @@ static int __init trust_init(void)
        /* mute card - prevents noisy bootups */
        tr_setmute(tr, 1);
 
+       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(tr->io, 2);
+               return -EINVAL;
+       }
+
+       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
+
        return 0;
 }
 
index b1f6305..8dbbf08 100644 (file)
@@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)
 
 static const struct v4l2_file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
@@ -344,18 +344,18 @@ static int __init typhoon_init(void)
 
        strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
        dev->io = io;
-       dev->curfreq = dev->mutefreq = mutefreq;
 
        if (dev->io == -1) {
                v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");
                return -EINVAL;
        }
 
-       if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+       if (mutefreq < 87000 || mutefreq > 108500) {
                v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");
                v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
                return -EINVAL;
        }
+       dev->curfreq = dev->mutefreq = mutefreq << 4;
 
        mutex_init(&dev->lock);
        if (!request_region(dev->io, 8, "typhoon")) {
@@ -378,17 +378,17 @@ static int __init typhoon_init(void)
        dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
+
+       /* mute card - prevents noisy bootups */
+       typhoon_mute(dev);
+
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&dev->v4l2_dev);
                release_region(dev->io, 8);
                return -EINVAL;
        }
        v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
-       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
-       dev->mutefreq <<= 4;
-
-       /* mute card - prevents noisy bootups */
-       typhoon_mute(dev);
+       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);
 
        return 0;
 }
index f31eab9..af99c5b 100644 (file)
@@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 static const struct v4l2_file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
@@ -424,20 +424,6 @@ static int __init zoltrix_init(void)
                return res;
        }
 
-       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
-       zol->vdev.v4l2_dev = v4l2_dev;
-       zol->vdev.fops = &zoltrix_fops;
-       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
-       zol->vdev.release = video_device_release_empty;
-       video_set_drvdata(&zol->vdev, zol);
-
-       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(zol->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
-
        mutex_init(&zol->lock);
 
        /* mute card - prevents noisy bootups */
@@ -452,6 +438,20 @@ static int __init zoltrix_init(void)
        zol->curvol = 0;
        zol->stereo = 1;
 
+       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
+       zol->vdev.v4l2_dev = v4l2_dev;
+       zol->vdev.fops = &zoltrix_fops;
+       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
+       zol->vdev.release = video_device_release_empty;
+       video_set_drvdata(&zol->vdev, zol);
+
+       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(zol->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
+
        return 0;
 }
 
index 31e7a12..f989f28 100644 (file)
@@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)
 static const struct v4l2_file_operations ar_fops = {
        .owner          = THIS_MODULE,
        .read           = ar_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops ar_ioctl_ops = {
index 935e0c9..c119350 100644 (file)
@@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 6e4b196..24fc009 100644 (file)
@@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 260c666..0dfff50 100644 (file)
@@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {
        .read = cafe_v4l_read,
        .poll = cafe_v4l_poll,
        .mmap = cafe_v4l_mmap,
-       .ioctl = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
index 8f55692..82d195b 100644 (file)
@@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
 static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
                     unsigned int cmd, void *arg)
 {
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_cx18_lock(cxsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_cx18_unlock(cxsc);
+       return ret;
 }
 
 
index 9045f1e..ab461e2 100644 (file)
@@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .read = cx18_v4l2_read,
        .open = cx18_v4l2_open,
        /* FIXME change to video_ioctl2 if serialization lock can be removed */
-       .ioctl = cx18_v4l2_ioctl,
+       .unlocked_ioctl = cx18_v4l2_ioctl,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
 };
index a5cfc76..bb16409 100644 (file)
@@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {
        .owner = THIS_MODULE,
        .open =    et61x251_open,
        .release = et61x251_release,
-       .ioctl =   et61x251_ioctl,
+       .unlocked_ioctl =   et61x251_ioctl,
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
index 2be23bc..48d2c24 100644 (file)
@@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = meye_poll,
 };
 
@@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        msleep(1);
        mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
 
-       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
-                                 video_nr) < 0) {
-               v4l2_err(v4l2_dev, "video_register_device failed\n");
-               goto outvideoreg;
-       }
-
        mutex_init(&meye.lock);
        init_waitqueue_head(&meye.proc_list);
        meye.brightness = 32 << 10;
@@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
 
+       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+                                 video_nr) < 0) {
+               v4l2_err(v4l2_dev, "video_register_device failed\n");
+               goto outvideoreg;
+       }
+
        v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
               MEYE_DRIVER_VERSION);
        v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
index 7129b50..7551907 100644 (file)
@@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations pms_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = pms_read,
 };
 
index 4e5a8cf..07cf0c6 100644 (file)
@@ -75,6 +75,7 @@ struct sh_vou_device {
        int pix_idx;
        struct videobuf_buffer *active;
        enum sh_vou_status status;
+       struct mutex fop_lock;
 };
 
 struct sh_vou_file {
@@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        vb->state = VIDEOBUF_NEEDS_INIT;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
                            unsigned int *size)
 {
@@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_prepare(struct videobuf_queue *vq,
                              struct videobuf_buffer *vb,
                              enum v4l2_field field)
@@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */
+/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
 static void sh_vou_buf_queue(struct videobuf_queue *vq,
                             struct videobuf_buffer *vb)
 {
@@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)
                                       V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer), vdev,
-                                      NULL);
+                                      &vou_dev->fop_lock);
 
        return 0;
 }
@@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {
        .owner          = THIS_MODULE,
        .open           = sh_vou_open,
        .release        = sh_vou_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = sh_vou_mmap,
        .poll           = sh_vou_poll,
 };
@@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&vou_dev->queue);
        spin_lock_init(&vou_dev->lock);
+       mutex_init(&vou_dev->fop_lock);
        atomic_set(&vou_dev->use_count, 0);
        vou_dev->pdata = vou_pdata;
        vou_dev->status = SH_VOU_IDLE;
@@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
                vdev->tvnorms |= V4L2_STD_PAL;
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
        vdev->release = video_device_release;
+       vdev->lock = &vou_dev->fop_lock;
 
        vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
index 28e19da..f49fbfb 100644 (file)
@@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open = sn9c102_open,
        .release = sn9c102_release,
-       .ioctl = sn9c102_ioctl,
+       .unlocked_ioctl = sn9c102_ioctl,
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
index f169f77..59f8a9a 100644 (file)
@@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
        }
 }
 
-struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
        __u32 v4l2_id, struct uvc_control_mapping **mapping)
 {
        struct uvc_control *ctrl = NULL;
@@ -944,6 +944,52 @@ done:
        return ret;
 }
 
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls that can be mapped directly, and handle the others
+ * manually.
+ */
+int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 index = query_menu->index;
+       u32 id = query_menu->id;
+       int ret;
+
+       memset(query_menu, 0, sizeof(*query_menu));
+       query_menu->id = id;
+       query_menu->index = index;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (query_menu->index >= mapping->menu_count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       menu_info = &mapping->menu_info[query_menu->index];
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
 
 /* --------------------------------------------------------------------------
  * Control transactions
index ed6d544..f14581b 100644 (file)
@@ -89,6 +89,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
        queue->type = type;
 }
 
+/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int __uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       unsigned int i;
+
+       for (i = 0; i < queue->count; ++i) {
+               if (queue->buffer[i].vma_use_count != 0)
+                       return -EBUSY;
+       }
+
+       if (queue->count) {
+               vfree(queue->mem);
+               queue->count = 0;
+       }
+
+       return 0;
+}
+
+int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = __uvc_free_buffers(queue);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
 /*
  * Allocate the video buffers.
  *
@@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
 
        mutex_lock(&queue->mutex);
 
-       if ((ret = uvc_free_buffers(queue)) < 0)
+       if ((ret = __uvc_free_buffers(queue)) < 0)
                goto done;
 
        /* Bail out if no buffers should be allocated. */
@@ -151,28 +184,6 @@ done:
        return ret;
 }
 
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
- */
-int uvc_free_buffers(struct uvc_video_queue *queue)
-{
-       unsigned int i;
-
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
-
-       if (queue->count) {
-               vfree(queue->mem);
-               queue->count = 0;
-       }
-
-       return 0;
-}
-
 /*
  * Check if buffers have been allocated.
  */
@@ -368,6 +379,82 @@ done:
        return ret;
 }
 
+/*
+ * VMA operations.
+ */
+static void uvc_vm_open(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count++;
+}
+
+static void uvc_vm_close(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count--;
+}
+
+static const struct vm_operations_struct uvc_vm_ops = {
+       .open           = uvc_vm_open,
+       .close          = uvc_vm_close,
+};
+
+/*
+ * Memory-map a video buffer.
+ *
+ * This function implements video buffers memory mapping and is intended to be
+ * used by the device mmap handler.
+ */
+int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+{
+       struct uvc_buffer *uninitialized_var(buffer);
+       struct page *page;
+       unsigned long addr, start, size;
+       unsigned int i;
+       int ret = 0;
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+
+       mutex_lock(&queue->mutex);
+
+       for (i = 0; i < queue->count; ++i) {
+               buffer = &queue->buffer[i];
+               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+
+       if (i == queue->count || size != queue->buf_size) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /*
+        * VM_IO marks the area as being an mmaped region for I/O to a
+        * device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
+       while (size > 0) {
+               page = vmalloc_to_page((void *)addr);
+               if ((ret = vm_insert_page(vma, start, page)) < 0)
+                       goto done;
+
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &uvc_vm_ops;
+       vma->vm_private_data = buffer;
+       uvc_vm_open(vma);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
 /*
  * Poll the video queue.
  *
index 6d15de9..8cf61e8 100644 (file)
@@ -100,40 +100,6 @@ done:
  * V4L2 interface
  */
 
-/*
- * Mapping V4L2 controls to UVC controls can be straighforward if done well.
- * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
- * must be grouped (for instance the Red Balance, Blue Balance and Do White
- * Balance V4L2 controls use the White Balance Component UVC control) or
- * otherwise translated. The approach we take here is to use a translation
- * table for the controls that can be mapped directly, and handle the others
- * manually.
- */
-static int uvc_v4l2_query_menu(struct uvc_video_chain *chain,
-       struct v4l2_querymenu *query_menu)
-{
-       struct uvc_menu_info *menu_info;
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 index = query_menu->index;
-       u32 id = query_menu->id;
-
-       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
-               return -EINVAL;
-
-       if (query_menu->index >= mapping->menu_count)
-               return -EINVAL;
-
-       memset(query_menu, 0, sizeof(*query_menu));
-       query_menu->id = id;
-       query_menu->index = index;
-
-       menu_info = &mapping->menu_info[query_menu->index];
-       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
-       return 0;
-}
-
 /*
  * Find the frame interval closest to the requested frame interval for the
  * given frame format and size. This should be done by the device as part of
@@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
         * developers test their webcams with the Linux driver as well as with
         * the Windows driver).
         */
+       mutex_lock(&stream->mutex);
        if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
                probe->dwMaxVideoFrameSize =
                        stream->ctrl.dwMaxVideoFrameSize;
 
        /* Probe the device. */
        ret = uvc_probe_video(stream, probe);
+       mutex_unlock(&stream->mutex);
        if (ret < 0)
                goto done;
 
@@ -289,14 +257,21 @@ done:
 static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        struct v4l2_format *fmt)
 {
-       struct uvc_format *format = stream->cur_format;
-       struct uvc_frame *frame = stream->cur_frame;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret = 0;
 
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (format == NULL || frame == NULL)
-               return -EINVAL;
+       mutex_lock(&stream->mutex);
+       format = stream->cur_format;
+       frame = stream->cur_frame;
+
+       if (format == NULL || frame == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
 
        fmt->fmt.pix.pixelformat = format->fcc;
        fmt->fmt.pix.width = frame->wWidth;
@@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        fmt->fmt.pix.colorspace = format->colorspace;
        fmt->fmt.pix.priv = 0;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_set_format(struct uvc_streaming *stream,
@@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_allocated(&stream->queue))
-               return -EBUSY;
-
        ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
        if (ret < 0)
                return ret;
 
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_allocated(&stream->queue)) {
+               ret = -EBUSY;
+               goto done;
+       }
+
        memcpy(&stream->ctrl, &probe, sizeof probe);
        stream->cur_format = format;
        stream->cur_frame = frame;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
@@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
+       mutex_lock(&stream->mutex);
        numerator = stream->ctrl.dwFrameInterval;
+       mutex_unlock(&stream->mutex);
+
        denominator = 10000000;
        uvc_simplify_fraction(&numerator, &denominator, 8, 333);
 
@@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
 static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
                struct v4l2_streamparm *parm)
 {
-       struct uvc_frame *frame = stream->cur_frame;
        struct uvc_streaming_control probe;
        struct v4l2_fract timeperframe;
        uint32_t interval;
@@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_streaming(&stream->queue))
-               return -EBUSY;
-
        if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                timeperframe = parm->parm.capture.timeperframe;
        else
                timeperframe = parm->parm.output.timeperframe;
 
-       memcpy(&probe, &stream->ctrl, sizeof probe);
        interval = uvc_fraction_to_interval(timeperframe.numerator,
                timeperframe.denominator);
-
        uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
                timeperframe.numerator, timeperframe.denominator, interval);
-       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_streaming(&stream->queue)) {
+               mutex_unlock(&stream->mutex);
+               return -EBUSY;
+       }
+
+       memcpy(&probe, &stream->ctrl, sizeof probe);
+       probe.dwFrameInterval =
+               uvc_try_frame_interval(stream->cur_frame, interval);
 
        /* Probe the device with the new settings. */
        ret = uvc_probe_video(stream, &probe);
-       if (ret < 0)
+       if (ret < 0) {
+               mutex_unlock(&stream->mutex);
                return ret;
+       }
 
        memcpy(&stream->ctrl, &probe, sizeof probe);
+       mutex_unlock(&stream->mutex);
 
        /* Return the actual frame period. */
        timeperframe.numerator = probe.dwFrameInterval;
@@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)
        if (uvc_has_privileges(handle)) {
                uvc_video_enable(stream, 0);
 
-               mutex_lock(&stream->queue.mutex);
                if (uvc_free_buffers(&stream->queue) < 0)
                        uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
                                        "free buffers.\n");
-               mutex_unlock(&stream->queue.mutex);
        }
 
        /* Release the file handle. */
@@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_QUERYMENU:
-               return uvc_v4l2_query_menu(chain, arg);
+               return uvc_query_v4l2_menu(chain, arg);
 
        case VIDIOC_G_EXT_CTRLS:
        {
@@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_CROPCAP:
        {
                struct v4l2_cropcap *ccap = arg;
-               struct uvc_frame *frame = stream->cur_frame;
 
                if (ccap->type != stream->type)
                        return -EINVAL;
 
                ccap->bounds.left = 0;
                ccap->bounds.top = 0;
-               ccap->bounds.width = frame->wWidth;
-               ccap->bounds.height = frame->wHeight;
+
+               mutex_lock(&stream->mutex);
+               ccap->bounds.width = stream->cur_frame->wWidth;
+               ccap->bounds.height = stream->cur_frame->wHeight;
+               mutex_unlock(&stream->mutex);
 
                ccap->defrect = ccap->bounds;
 
@@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_REQBUFS:
        {
                struct v4l2_requestbuffers *rb = arg;
-               unsigned int bufsize =
-                       stream->ctrl.dwMaxVideoFrameSize;
 
                if (rb->type != stream->type ||
                    rb->memory != V4L2_MEMORY_MMAP)
@@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
-               ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize);
+               mutex_lock(&stream->mutex);
+               ret = uvc_alloc_buffers(&stream->queue, rb->count,
+                                       stream->ctrl.dwMaxVideoFrameSize);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
 
@@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
+               mutex_lock(&stream->mutex);
                ret = uvc_video_enable(stream, 1);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
                break;
@@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
        return -EINVAL;
 }
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
-}
-
-static const struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
-
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct uvc_fh *handle = file->private_data;
        struct uvc_streaming *stream = handle->stream;
-       struct uvc_video_queue *queue = &stream->queue;
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
 
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
-
-       mutex_lock(&queue->mutex);
-
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || size != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return uvc_queue_mmap(&stream->queue, vma);
 }
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
@@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
-       .ioctl          = uvc_v4l2_ioctl,
+       .unlocked_ioctl = uvc_v4l2_ioctl,
        .read           = uvc_v4l2_read,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
index 5555f01..5673d67 100644 (file)
@@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        unsigned int i;
        int ret;
 
-       mutex_lock(&stream->mutex);
-
        /* Perform probing. The device should adjust the requested values
         * according to its capabilities. However, some devices, namely the
         * first generation UVC Logitech webcams, don't implement the Video
@@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        }
 
 done:
-       mutex_unlock(&stream->mutex);
        return ret;
 }
 
index d97cf6d..45f01e7 100644 (file)
@@ -436,7 +436,9 @@ struct uvc_streaming {
        struct uvc_streaming_control ctrl;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
-
+       /* Protect access to ctrl, cur_format, cur_frame and hardware video
+        * probe control.
+        */
        struct mutex mutex;
 
        unsigned int frozen : 1;
@@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
 extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
 extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
                struct uvc_buffer *buf);
+extern int uvc_queue_mmap(struct uvc_video_queue *queue,
+               struct vm_area_struct *vma);
 extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
                struct file *file, poll_table *wait);
 extern int uvc_queue_allocated(struct uvc_video_queue *queue);
@@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
 /* Controls */
-extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
-               __u32 v4l2_id, struct uvc_control_mapping **mapping);
 extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
                struct v4l2_queryctrl *v4l2_ctrl);
+extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+               struct v4l2_querymenu *query_menu);
 
 extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                const struct uvc_control_mapping *mapping);
index 03f7f46..359e232 100644 (file)
@@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->read(filp, buf, sz, off);
        if (vdev->lock)
@@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->write(filp, buf, sz, off);
        if (vdev->lock)
@@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = DEFAULT_POLLMASK;
+       int ret = POLLERR | POLLHUP;
 
        if (!vdev->fops->poll)
-               return ret;
+               return DEFAULT_POLLMASK;
        if (vdev->lock)
                mutex_lock(vdev->lock);
        if (video_is_registered(vdev))
@@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int ret = -ENODEV;
 
        if (vdev->fops->unlocked_ioctl) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                if (vdev->lock)
                        mutex_unlock(vdev->lock);
        } else if (vdev->fops->ioctl) {
-               /* TODO: convert all drivers to unlocked_ioctl */
+               /* This code path is a replacement for the BKL. It is a major
+                * hack but it will have to do for those drivers that are not
+                * yet converted to use unlocked_ioctl.
+                *
+                * There are two options: if the driver implements struct
+                * v4l2_device, then the lock defined there is used to
+                * serialize the ioctls. Otherwise the v4l2 core lock defined
+                * below is used. This lock is really bad since it serializes
+                * completely independent devices.
+                *
+                * Both variants suffer from the same problem: if the driver
+                * sleeps, then it blocks all ioctls since the lock is still
+                * held. This is very common for VIDIOC_DQBUF since that
+                * normally waits for a frame to arrive. As a result any other
+                * ioctl calls will proceed very, very slowly since each call
+                * will have to wait for the VIDIOC_QBUF to finish. Things that
+                * should take 0.01s may now take 10-20 seconds.
+                *
+                * The workaround is to *not* take the lock for VIDIOC_DQBUF.
+                * This actually works OK for videobuf-based drivers, since
+                * videobuf will take its own internal lock.
+                */
                static DEFINE_MUTEX(v4l2_ioctl_mutex);
+               struct mutex *m = vdev->v4l2_dev ?
+                       &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
 
-               mutex_lock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->ioctl(filp, cmd, arg);
-               mutex_unlock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF)
+                       mutex_unlock(m);
        } else
                ret = -ENOTTY;
 
@@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 
        if (!vdev->fops->mmap)
                return ret;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->mmap(filp, vm);
        if (vdev->lock)
@@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&videodev_lock);
        vdev = video_devdata(filp);
        /* return ENODEV if the video device has already been removed. */
-       if (vdev == NULL) {
+       if (vdev == NULL || !video_is_registered(vdev)) {
                mutex_unlock(&videodev_lock);
                return -ENODEV;
        }
@@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
        if (vdev->fops->open) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+                       ret = -ERESTARTSYS;
+                       goto err;
+               }
                if (video_is_registered(vdev))
                        ret = vdev->fops->open(filp);
                else
@@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 
+err:
        /* decrease the refcount in case of an error */
        if (ret)
                video_put(vdev);
@@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)
        if (!vdev || !video_is_registered(vdev))
                return;
 
+       mutex_lock(&videodev_lock);
+       /* This must be in a critical section to prevent a race with v4l2_open.
+        * Once this bit has been cleared video_get may never be called again.
+        */
        clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
+       mutex_unlock(&videodev_lock);
        device_unregister(&vdev->dev);
 }
 EXPORT_SYMBOL(video_unregister_device);
index 0b08f96..7fe6f92 100644 (file)
@@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
+       mutex_init(&v4l2_dev->ioctl_lock);
        v4l2_dev->dev = dev;
        if (dev == NULL) {
                /* If dev == NULL, then name must be filled in by the caller */
index 635420d..019ee20 100644 (file)
@@ -815,7 +815,7 @@ out:
 
 static const struct v4l2_file_operations w9966_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = w9966_v4l_read,
 };
 
index dd90880..d8ae634 100644 (file)
@@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
-static int __init pxa2xx_flash_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
        struct flash_platform_data *flash = pdev->dev.platform_data;
        struct pxa2xx_flash_info *info;
index cd41c58..15682ec 100644 (file)
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define CONFIG_MTD_NAND_OMAP_HWECC
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
index c6e8631..2e2b762 100644 (file)
@@ -381,11 +381,11 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
        __b44_set_flow_ctrl(bp, pause_enab);
 }
 
-#ifdef SSB_DRIVER_MIPS
-extern char *nvram_get(char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 static void b44_wap54g10_workaround(struct b44 *bp)
 {
-       const char *str;
+       char buf[20];
        u32 val;
        int err;
 
@@ -394,10 +394,9 @@ static void b44_wap54g10_workaround(struct b44 *bp)
         * see https://dev.openwrt.org/ticket/146
         * check and reset bit "isolate"
         */
-       str = nvram_get("boardnum");
-       if (!str)
+       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
                return;
-       if (simple_strtoul(str, NULL, 0) == 2) {
+       if (simple_strtoul(buf, NULL, 0) == 2) {
                err = __b44_readphy(bp, 0, MII_BMCR, &val);
                if (err)
                        goto error;
index 36eca1c..e4465d2 100644 (file)
@@ -1235,7 +1235,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 
                i = 0;
                netdev_for_each_mc_addr(ha, netdev)
-                       memcpy(req->mac[i].byte, ha->addr, ETH_ALEN);
+                       memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
        } else {
                req->promiscuous = 1;
        }
index 863e73a..d255428 100644 (file)
@@ -20,8 +20,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.60.00-4"
-#define DRV_MODULE_RELDATE      "2010/11/01"
+#define DRV_MODULE_VERSION      "1.60.01-0"
+#define DRV_MODULE_RELDATE      "2010/11/12"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
index 94d5f59..0af361e 100644 (file)
@@ -1782,15 +1782,15 @@ exit_lbl:
 }
 #endif
 
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
-                                    struct eth_tx_parse_bd_e2 *pbd,
-                                    u32 xmit_type)
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
+                                       u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
-               ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+       *parsing_data |= (skb_shinfo(skb)->gso_size <<
+                             ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
+                             ETH_TX_PARSE_BD_E2_LSO_MSS;
        if ((xmit_type & XMIT_GSO_V6) &&
            (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
-               pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+               *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
 }
 
 /**
@@ -1835,15 +1835,15 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
  * @return header len
  */
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
-       struct eth_tx_parse_bd_e2 *pbd,
-       u32 xmit_type)
+       u32 *parsing_data, u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+       *parsing_data |= ((tcp_hdrlen(skb)/4) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-       pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
-                                         skb->data) / 2) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+       *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
        return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
 }
@@ -1912,6 +1912,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
        struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
        struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
+       u32 pbd_e2_parsing_data = 0;
        u16 pkt_prod, bd_prod;
        int nbd, fp_index;
        dma_addr_t mapping;
@@ -2033,8 +2034,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
                /* Set PBD in checksum offload case */
                if (xmit_type & XMIT_CSUM)
-                       hlen = bnx2x_set_pbd_csum_e2(bp,
-                                                    skb, pbd_e2, xmit_type);
+                       hlen = bnx2x_set_pbd_csum_e2(bp, skb,
+                                                    &pbd_e2_parsing_data,
+                                                    xmit_type);
        } else {
                pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
                memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
@@ -2076,10 +2078,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
                                                 hlen, bd_prod, ++nbd);
                if (CHIP_IS_E2(bp))
-                       bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+                       bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
+                                            xmit_type);
                else
                        bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
        }
+
+       /* Set the PBD's parsing_data field if not zero
+        * (for the chips newer than 57711).
+        */
+       if (pbd_e2_parsing_data)
+               pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data);
+
        tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
 
        /* Handle fragmented skb */
index a306b0e..66df29f 100644 (file)
@@ -838,7 +838,7 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
 /****************************************************************************
 * SRC initializations
 ****************************************************************************/
-
+#ifdef BCM_CNIC
 /* called during init func stage */
 static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                              dma_addr_t t2_mapping, int src_cid_count)
@@ -862,5 +862,5 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                    U64_HI((u64)t2_mapping +
                           (src_cid_count-1) * sizeof(struct src_ent)));
 }
-
+#endif
 #endif /* BNX2X_INIT_OPS_H */
index 71a1697..d0ea760 100644 (file)
@@ -171,7 +171,7 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link
 /*----------------------------- Global variables ----------------------------*/
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-cpumask_var_t netpoll_block_tx;
+atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
 static const char * const version =
@@ -1576,7 +1576,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        /* If this is the first slave, then we need to set the master's hardware
         * address to be the same as the slave's. */
-       if (bond->slave_cnt == 0)
+       if (is_zero_ether_addr(bond->dev->dev_addr))
                memcpy(bond->dev->dev_addr, slave_dev->dev_addr,
                       slave_dev->addr_len);
 
@@ -5299,13 +5299,6 @@ static int __init bonding_init(void)
        if (res)
                goto out;
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
-               res = -ENOMEM;
-               goto out;
-       }
-#endif
-
        res = register_pernet_subsys(&bond_net_ops);
        if (res)
                goto out;
@@ -5334,9 +5327,6 @@ err:
        rtnl_link_unregister(&bond_link_ops);
 err_link:
        unregister_pernet_subsys(&bond_net_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
-#endif
        goto out;
 
 }
@@ -5353,7 +5343,10 @@ static void __exit bonding_exit(void)
        unregister_pernet_subsys(&bond_net_ops);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
+       /*
+        * Make sure we don't have an imbalance on our netpoll blocking
+        */
+       WARN_ON(atomic_read(&netpoll_block_tx));
 #endif
 }
 
index 4eedb12..c2f0813 100644 (file)
 
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-extern cpumask_var_t netpoll_block_tx;
+extern atomic_t netpoll_block_tx;
 
 static inline void block_netpoll_tx(void)
 {
-       preempt_disable();
-       BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
-                                       netpoll_block_tx));
+       atomic_inc(&netpoll_block_tx);
 }
 
 static inline void unblock_netpoll_tx(void)
 {
-       BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
-                                          netpoll_block_tx));
-       preempt_enable();
+       atomic_dec(&netpoll_block_tx);
 }
 
 static inline int is_netpoll_tx_blocked(struct net_device *dev)
 {
        if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
-               return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
+               return atomic_read(&netpoll_block_tx);
        return 0;
 }
 #else
index 1cd90da..32b1c6f 100644 (file)
@@ -5,7 +5,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/version.h>
 #include <linux/init.h>
index 19f9c06..8051116 100644 (file)
@@ -6,7 +6,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/spinlock.h>
 #include <linux/sched.h>
index bb813d9..e97521c 100644 (file)
@@ -2408,7 +2408,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
                if (index < NEXACT_MAC)
                        ret++;
                else if (hash)
-                       *hash |= (1 << hash_mac_addr(addr[i]));
+                       *hash |= (1ULL << hash_mac_addr(addr[i]));
        }
        return ret;
 }
index d887a76..6bf464a 100644 (file)
@@ -2269,6 +2269,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
 {
        struct sge *s = &adapter->sge;
        int q10g, n10g, qidx, pidx, qs;
+       size_t iqe_size;
 
        /*
         * We should not be called till we know how many Queue Sets we can
@@ -2312,6 +2313,13 @@ static void __devinit cfg_queues(struct adapter *adapter)
        }
        s->ethqsets = qidx;
 
+       /*
+        * The Ingress Queue Entry Size for our various Response Queues needs
+        * to be big enough to accommodate the largest message we can receive
+        * from the chip/firmware; which is 64 bytes ...
+        */
+       iqe_size = 64;
+
        /*
         * Set up default Queue Set parameters ...  Start off with the
         * shortest interrupt holdoff timer.
@@ -2320,7 +2328,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
                struct sge_eth_rxq *rxq = &s->ethrxq[qs];
                struct sge_eth_txq *txq = &s->ethtxq[qs];
 
-               init_rspq(&rxq->rspq, 0, 0, 1024, L1_CACHE_BYTES);
+               init_rspq(&rxq->rspq, 0, 0, 1024, iqe_size);
                rxq->fl.size = 72;
                txq->q.size = 1024;
        }
@@ -2329,8 +2337,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * The firmware event queue is used for link state changes and
         * notifications of TX DMA completions.
         */
-       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512,
-                 L1_CACHE_BYTES);
+       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512, iqe_size);
 
        /*
         * The forwarded interrupt queue is used when we're in MSI interrupt
@@ -2346,7 +2353,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * any time ...
         */
        init_rspq(&s->intrq, SGE_TIMER_RSTRT_CNTR, 0, MSIX_ENTRIES + 1,
-                 L1_CACHE_BYTES);
+                 iqe_size);
 }
 
 /*
index 75b099c..1f37ee6 100644 (file)
@@ -261,6 +261,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
 
 }
 
+static int ehea_set_flags(struct net_device *dev, u32 data)
+{
+       return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
+                                       | ETH_FLAG_TXVLAN
+                                       | ETH_FLAG_RXVLAN);
+}
+
 const struct ethtool_ops ehea_ethtool_ops = {
        .get_settings = ehea_get_settings,
        .get_drvinfo = ehea_get_drvinfo,
@@ -273,6 +280,8 @@ const struct ethtool_ops ehea_ethtool_ops = {
        .get_ethtool_stats = ehea_get_ethtool_stats,
        .get_rx_csum = ehea_get_rx_csum,
        .set_settings = ehea_set_settings,
+       .get_flags = ethtool_op_get_flags,
+       .set_flags = ehea_set_flags,
        .nway_reset = ehea_nway_reset,          /* Restart autonegotiation */
 };
 
index 3d0af08..b95f087 100644 (file)
@@ -683,7 +683,7 @@ static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
        int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
                              pr->port->vgrp);
 
-       if (use_lro) {
+       if (skb->dev->features & NETIF_F_LRO) {
                if (vlan_extracted)
                        lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
                                                     pr->port->vgrp,
@@ -787,7 +787,7 @@ static int ehea_proc_rwqes(struct net_device *dev,
                }
                cqe = ehea_poll_rq1(qp, &wqe_index);
        }
-       if (use_lro)
+       if (dev->features & NETIF_F_LRO)
                lro_flush_all(&pr->lro_mgr);
 
        pr->rx_packets += processed;
@@ -3278,6 +3278,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                      | NETIF_F_LLTX;
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
+       if (use_lro)
+               dev->features |= NETIF_F_LRO;
+
        INIT_WORK(&port->reset_task, ehea_reset_port);
 
        ret = register_netdev(dev);
index a466ef9..aa28b27 100644 (file)
@@ -1962,7 +1962,8 @@ static void enic_poll_controller(struct net_device *netdev)
        case VNIC_DEV_INTR_MODE_MSIX:
                for (i = 0; i < enic->rq_count; i++) {
                        intr = enic_msix_rq_intr(enic, i);
-                       enic_isr_msix_rq(enic->msix_entry[intr].vector, enic);
+                       enic_isr_msix_rq(enic->msix_entry[intr].vector,
+                               &enic->napi[i]);
                }
                intr = enic_msix_wq_intr(enic, i);
                enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
index ab9f675..fe337bd 100644 (file)
@@ -104,6 +104,8 @@ static void ri_tasklet(unsigned long dev)
                        rcu_read_unlock();
                        dev_kfree_skb(skb);
                        stats->tx_dropped++;
+                       if (skb_queue_len(&dp->tq) != 0)
+                               goto resched;
                        break;
                }
                rcu_read_unlock();
index fbad4d8..eee0b29 100644 (file)
@@ -4771,6 +4771,9 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
                adapter->rx_ring[i] = NULL;
        }
 
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
+
        ixgbe_free_q_vectors(adapter);
        ixgbe_reset_interrupt_capability(adapter);
 }
index cb3d13e..35fda5a 100644 (file)
@@ -64,7 +64,7 @@ config BCM63XX_PHY
 config ICPLUS_PHY
        tristate "Drivers for ICPlus PHYs"
        ---help---
-         Currently supports the IP175C PHY.
+         Currently supports the IP175C and IP1001 PHYs.
 
 config REALTEK_PHY
        tristate "Drivers for Realtek PHYs"
index c1d2d25..9a09e24 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
 MODULE_AUTHOR("Michael Barkowski");
 MODULE_LICENSE("GPL");
 
@@ -89,6 +89,33 @@ static int ip175c_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int ip1001_config_init(struct phy_device *phydev)
+{
+       int err, value;
+
+       /* Software Reset PHY */
+       value = phy_read(phydev, MII_BMCR);
+       value |= BMCR_RESET;
+       err = phy_write(phydev, MII_BMCR, value);
+       if (err < 0)
+               return err;
+
+       do {
+               value = phy_read(phydev, MII_BMCR);
+       } while (value & BMCR_RESET);
+
+       /* Additional delay (2ns) used to adjust RX clock phase
+        * at GMII/ RGMII interface */
+       value = phy_read(phydev, 16);
+       value |= 0x3;
+
+       err = phy_write(phydev, 16, value);
+       if (err < 0)
+               return err;
+
+       return err;
+}
+
 static int ip175c_read_status(struct phy_device *phydev)
 {
        if (phydev->addr == 4) /* WAN port */
@@ -121,21 +148,43 @@ static struct phy_driver ip175c_driver = {
        .driver         = { .owner = THIS_MODULE,},
 };
 
-static int __init ip175c_init(void)
+static struct phy_driver ip1001_driver = {
+       .phy_id         = 0x02430d90,
+       .name           = "ICPlus IP1001",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                         SUPPORTED_Asym_Pause,
+       .config_init    = &ip1001_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init icplus_init(void)
 {
+       int ret = 0;
+
+       ret = phy_driver_register(&ip1001_driver);
+       if (ret < 0)
+               return -ENODEV;
+
        return phy_driver_register(&ip175c_driver);
 }
 
-static void __exit ip175c_exit(void)
+static void __exit icplus_exit(void)
 {
+       phy_driver_unregister(&ip1001_driver);
        phy_driver_unregister(&ip175c_driver);
 }
 
-module_init(ip175c_init);
-module_exit(ip175c_exit);
+module_init(icplus_init);
+module_exit(icplus_exit);
 
 static struct mdio_device_id __maybe_unused icplus_tbl[] = {
        { 0x02430d80, 0x0ffffff0 },
+       { 0x02430d90, 0x0ffffff0 },
        { }
 };
 
index d72fb05..78c0e3c 100644 (file)
@@ -948,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 
 abort:
        kfree_skb(skb);
-       return 0;
+       return 1;
 }
 
 /************************************************************************
index 2282139..9787dff 100644 (file)
@@ -2083,6 +2083,7 @@ struct ql_adapter {
        u32 mailbox_in;
        u32 mailbox_out;
        struct mbox_params idc_mbc;
+       struct mutex    mpi_mutex;
 
        int tx_ring_size;
        int rx_ring_size;
index 528eaef..2555b1d 100644 (file)
@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
        INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log);
        init_completion(&qdev->ide_completion);
+       mutex_init(&qdev->mpi_mutex);
 
        if (!cards_found) {
                dev_info(&pdev->dev, "%s\n", DRV_STRING);
index 0e7c7c7..a2e919b 100644 (file)
@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
        int status;
        unsigned long count;
 
+       mutex_lock(&qdev->mpi_mutex);
 
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
@@ -603,6 +604,7 @@ done:
 end:
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
+       mutex_unlock(&qdev->mpi_mutex);
        return status;
 }
 
@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev)
 static int ql_set_port_cfg(struct ql_adapter *qdev)
 {
        int status;
-       rtnl_lock();
        status = ql_mb_set_port_cfg(qdev);
-       rtnl_unlock();
        if (status)
                return status;
        status = ql_idc_wait(qdev);
@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work)
            container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
        int status;
 
-       rtnl_lock();
        status = ql_mb_get_port_cfg(qdev);
-       rtnl_unlock();
        if (status) {
                netif_err(qdev, drv, qdev->ndev,
                          "Bug: Failed to get port config data.\n");
@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work)
        u32 aen;
        int timeout;
 
-       rtnl_lock();
        aen = mbcp->mbox_out[1] >> 16;
        timeout = (mbcp->mbox_out[1] >> 8) & 0xf;
 
@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work)
                }
                break;
        }
-       rtnl_unlock();
 }
 
 void ql_mpi_work(struct work_struct *work)
@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work)
        struct mbox_params *mbcp = &mbc;
        int err = 0;
 
-       rtnl_lock();
+       mutex_lock(&qdev->mpi_mutex);
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
 
@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work)
 
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
-       rtnl_unlock();
+       mutex_unlock(&qdev->mpi_mutex);
        ql_enable_completion_interrupt(qdev, 0);
 }
 
index 7d33ef4..53b13de 100644 (file)
@@ -744,26 +744,36 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
        mdio_write(ioaddr, MII_BMCR, val & 0xffff);
 }
 
-static void rtl8169_check_link_status(struct net_device *dev,
+static void __rtl8169_check_link_status(struct net_device *dev,
                                      struct rtl8169_private *tp,
-                                     void __iomem *ioaddr)
+                                     void __iomem *ioaddr,
+                                     bool pm)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&tp->lock, flags);
        if (tp->link_ok(ioaddr)) {
                /* This is to cancel a scheduled suspend if there's one. */
-               pm_request_resume(&tp->pci_dev->dev);
+               if (pm)
+                       pm_request_resume(&tp->pci_dev->dev);
                netif_carrier_on(dev);
                netif_info(tp, ifup, dev, "link up\n");
        } else {
                netif_carrier_off(dev);
                netif_info(tp, ifdown, dev, "link down\n");
-               pm_schedule_suspend(&tp->pci_dev->dev, 100);
+               if (pm)
+                       pm_schedule_suspend(&tp->pci_dev->dev, 100);
        }
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static void rtl8169_check_link_status(struct net_device *dev,
+                                     struct rtl8169_private *tp,
+                                     void __iomem *ioaddr)
+{
+       __rtl8169_check_link_status(dev, tp, ioaddr, false);
+}
+
 #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
 
 static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
@@ -4600,7 +4610,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
                }
 
                if (status & LinkChg)
-                       rtl8169_check_link_status(dev, tp, ioaddr);
+                       __rtl8169_check_link_status(dev, tp, ioaddr, true);
 
                /* We need to see the lastest version of tp->intr_mask to
                 * avoid ignoring an MSI interrupt and having to wait for
@@ -4890,11 +4900,7 @@ static int rtl8169_runtime_idle(struct device *device)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       if (!tp->TxDescArray)
-               return 0;
-
-       rtl8169_check_link_status(dev, tp, tp->mmio_addr);
-       return -EBUSY;
+       return tp->TxDescArray ? -EBUSY : 0;
 }
 
 static const struct dev_pm_ops rtl8169_pm_ops = {
index 05df20e..fb83cdd 100644 (file)
@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
 
 static void efx_remove_channels(struct efx_nic *efx);
 static void efx_remove_port(struct efx_nic *efx);
+static void efx_init_napi(struct efx_nic *efx);
 static void efx_fini_napi(struct efx_nic *efx);
+static void efx_fini_napi_channel(struct efx_channel *channel);
 static void efx_fini_struct(struct efx_nic *efx);
 static void efx_start_all(struct efx_nic *efx);
 static void efx_stop_all(struct efx_nic *efx);
@@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel)
 
        /* Disable interrupts and wait for ISRs to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        if (channel->irq)
                synchronize_irq(channel->irq);
 
@@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel)
        efx_channel_processed(channel);
 
        napi_enable(&channel->napi_str);
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 }
 
@@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
 
                *channel = *old_channel;
 
+               channel->napi_dev = NULL;
                memset(&channel->eventq, 0, sizeof(channel->eventq));
 
                rx_queue = &channel->rx_queue;
@@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
        if (rc)
                goto rollback;
 
+       efx_init_napi(efx);
+
        /* Destroy old channels */
-       for (i = 0; i < efx->n_channels; i++)
+       for (i = 0; i < efx->n_channels; i++) {
+               efx_fini_napi_channel(other_channel[i]);
                efx_remove_channel(other_channel[i]);
+       }
 out:
        /* Free unused channel structures */
        for (i = 0; i < efx->n_channels; i++)
@@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx)
                efx_start_channel(channel);
        }
 
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 
        /* Switch to event based MCDI completions after enabling interrupts.
@@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx)
 
        /* Disable interrupts and wait for ISR to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        efx_for_each_channel(channel, efx) {
                if (channel->irq)
                        synchronize_irq(channel->irq);
@@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
  *
  **************************************************************************/
 
-static int efx_init_napi(struct efx_nic *efx)
+static void efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
@@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx)
                netif_napi_add(channel->napi_dev, &channel->napi_str,
                               efx_poll, napi_weight);
        }
-       return 0;
+}
+
+static void efx_fini_napi_channel(struct efx_channel *channel)
+{
+       if (channel->napi_dev)
+               netif_napi_del(&channel->napi_str);
+       channel->napi_dev = NULL;
 }
 
 static void efx_fini_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
-       efx_for_each_channel(channel, efx) {
-               if (channel->napi_dev)
-                       netif_napi_del(&channel->napi_str);
-               channel->napi_dev = NULL;
-       }
+       efx_for_each_channel(channel, efx)
+               efx_fini_napi_channel(channel);
 }
 
 /**************************************************************************
@@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        if (rc)
                goto fail1;
 
-       rc = efx_init_napi(efx);
-       if (rc)
-               goto fail2;
+       efx_init_napi(efx);
 
        rc = efx->type->init(efx);
        if (rc) {
@@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        efx->type->fini(efx);
  fail3:
        efx_fini_napi(efx);
- fail2:
        efx_remove_all(efx);
  fail1:
        return rc;
index 0a7e26d..b137c88 100644 (file)
@@ -621,6 +621,7 @@ struct efx_filter_state;
  * @pci_dev: The PCI device
  * @type: Controller type attributes
  * @legacy_irq: IRQ number
+ * @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)?
  * @workqueue: Workqueue for port reconfigures and the HW monitor.
  *     Work items do not hold and must not acquire RTNL.
  * @workqueue_name: Name of workqueue
@@ -709,6 +710,7 @@ struct efx_nic {
        struct pci_dev *pci_dev;
        const struct efx_nic_type *type;
        int legacy_irq;
+       bool legacy_irq_enabled;
        struct workqueue_struct *workqueue;
        char workqueue_name[16];
        struct work_struct reset_work;
index 41c36b9..67cb0c9 100644 (file)
@@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
        u32 queues;
        int syserr;
 
+       /* Could this be ours?  If interrupts are disabled then the
+        * channel state may not be valid.
+        */
+       if (!efx->legacy_irq_enabled)
+               return result;
+
        /* Read the ISR which also ACKs the interrupts */
        efx_readd(efx, &reg, FR_BZ_INT_ISR0);
        queues = EFX_EXTRACT_DWORD(reg, 0, 31);
index 06bc603..2114837 100644 (file)
@@ -1509,6 +1509,8 @@ static int stmmac_probe(struct net_device *dev)
                pr_warning("\tno valid MAC address;"
                        "please, use ifconfig or nwhwconfig!\n");
 
+       spin_lock_init(&priv->lock);
+
        ret = register_netdev(dev);
        if (ret) {
                pr_err("%s: ERROR %i registering the device\n",
@@ -1520,8 +1522,6 @@ static int stmmac_probe(struct net_device *dev)
            dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
            (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
 
-       spin_lock_init(&priv->lock);
-
        return ret;
 }
 
index a9f7d5d..7064e03 100644 (file)
@@ -688,9 +688,6 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
 
        DMFE_DBUG(0, "dmfe_start_xmit", 0);
 
-       /* Resource flag check */
-       netif_stop_queue(dev);
-
        /* Too large packet check */
        if (skb->len > MAX_PACKET_SIZE) {
                pr_err("big packet = %d\n", (u16)skb->len);
@@ -698,6 +695,9 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /* Resource flag check */
+       netif_stop_queue(dev);
+
        spin_lock_irqsave(&db->lock, flags);
 
        /* No Tx resource check, it never happen nromally */
index 62e9e8d..812edf8 100644 (file)
@@ -958,10 +958,6 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,
                                /* Packet is complete. Inject into stack. */
                                /* We have IP packet here */
                                odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP);
-                               /* don't check it */
-                               odev->skb_rx_buf->ip_summed =
-                                       CHECKSUM_UNNECESSARY;
-
                                skb_reset_mac_header(odev->skb_rx_buf);
 
                                /* Ship it off to the kernel */
index ea476cb..e305274 100644 (file)
@@ -293,6 +293,7 @@ static inline void sca_tx_done(port_t *port)
        struct net_device *dev = port->netdev;
        card_t* card = port->card;
        u8 stat;
+       unsigned count = 0;
 
        spin_lock(&port->lock);
 
@@ -316,10 +317,12 @@ static inline void sca_tx_done(port_t *port)
                        dev->stats.tx_bytes += readw(&desc->len);
                }
                writeb(0, &desc->stat); /* Free descriptor */
+               count++;
                port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
        }
 
-       netif_wake_queue(dev);
+       if (count)
+               netif_wake_queue(dev);
        spin_unlock(&port->lock);
 }
 
index 8251946..42ed923 100644 (file)
@@ -1917,7 +1917,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                sc->bmisscount = 0;
        }
 
-       if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+       if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
                int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
@@ -1949,8 +1950,9 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                /* NB: hw still stops DMA, so proceed */
        }
 
-       /* refresh the beacon for AP mode */
-       if (sc->opmode == NL80211_IFTYPE_AP)
+       /* refresh the beacon for AP or MESH mode */
+       if (sc->opmode == NL80211_IFTYPE_AP ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT)
                ath5k_beacon_update(sc->hw, vif);
 
        ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
@@ -2851,7 +2853,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
 
        /* Assign the vap/adhoc to a beacon xmit slot. */
        if ((avf->opmode == NL80211_IFTYPE_AP) ||
-           (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+           (avf->opmode == NL80211_IFTYPE_ADHOC) ||
+           (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
                int slot;
 
                WARN_ON(list_empty(&sc->bcbuf));
@@ -2870,7 +2873,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
                sc->bslot[avf->bslot] = vif;
                if (avf->opmode == NL80211_IFTYPE_AP)
                        sc->num_ap_vifs++;
-               else
+               else if (avf->opmode == NL80211_IFTYPE_ADHOC)
                        sc->num_adhoc_vifs++;
        }
 
index c418235..a7b82f0 100644 (file)
@@ -55,6 +55,8 @@
 #define SUB_NUM_CTL_MODES_AT_5G_40 2    /* excluding HT40, EXT-OFDM */
 #define SUB_NUM_CTL_MODES_AT_2G_40 3    /* excluding HT40, EXT-OFDM, EXT-CCK */
 
+#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+
 static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
@@ -290,20 +292,21 @@ static const struct ar9300_eeprom ar9300_default = {
                }
         },
        .ctlPowerData_2G = {
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
         },
        .modalHeader5G = {
                /* 4 idle,t1,t2,b (4 bits per setting) */
@@ -568,56 +571,56 @@ static const struct ar9300_eeprom ar9300_default = {
        .ctlPowerData_5G = {
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 0}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 0}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
                        }
                },
         }
@@ -1827,9 +1830,9 @@ static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
        struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
 
        if (is2GHz)
-               return ctl_2g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
        else
-               return ctl_5g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
 }
 
 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
@@ -1847,12 +1850,12 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
 
        if (is2GHz) {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
-                   ctl_2g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_2g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
        } else {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
-                   ctl_5g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_5g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
        }
 
        return AR9300_MAX_RATE_POWER;
index 3c533bb..655b303 100644 (file)
@@ -261,17 +261,12 @@ struct cal_tgt_pow_ht {
        u8 tPow2x[14];
 } __packed;
 
-struct cal_ctl_edge_pwr {
-       u8 tPower:6,
-          flag:2;
-} __packed;
-
 struct cal_ctl_data_2g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
 } __packed;
 
 struct cal_ctl_data_5g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
 } __packed;
 
 struct ar9300_eeprom {
index 170d44a..0963071 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
+#include <linux/pm_qos_params.h>
 
 #include "debug.h"
 #include "common.h"
@@ -328,7 +329,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_setup(struct ath_softc *sc, int haltype);
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
                     struct ath_txq *txq, bool retry_tx);
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
@@ -646,6 +647,8 @@ struct ath_softc {
        struct ath_descdma txsdma;
 
        struct ath_ant_comb ant_comb;
+
+       struct pm_qos_request_list pm_qos_req;
 };
 
 struct ath_wiphy {
@@ -675,7 +678,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 }
 
 extern struct ieee80211_ops ath9k_ops;
-extern struct pm_qos_request_list ath9k_pm_qos_req;
 extern int modparam_nohwcrypt;
 extern int led_blink;
 
index 1266333..2bbf94d 100644 (file)
@@ -240,16 +240,16 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
        for (i = 0; (i < num_band_edges) &&
                     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
                if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
-                       twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+                       twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
                        break;
                } else if ((i > 0) &&
                           (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
                                                      is2GHz))) {
                        if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
                                               is2GHz) < freq &&
-                           pRdEdgesPower[i - 1].flag) {
+                           CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
                                twiceMaxEdgePower =
-                                       pRdEdgesPower[i - 1].tPower;
+                                       CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
                        }
                        break;
                }
index dacb45e..dd59f09 100644 (file)
 
 #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
 
+#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
+#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
+
+#define LNA_CTL_BUF_MODE       BIT(0)
+#define LNA_CTL_ISEL_LO                BIT(1)
+#define LNA_CTL_ISEL_HI                BIT(2)
+#define LNA_CTL_BUF_IN         BIT(3)
+#define LNA_CTL_FEM_BAND       BIT(4)
+#define LNA_CTL_LOCAL_BIAS     BIT(5)
+#define LNA_CTL_FORCE_XPA      BIT(6)
+#define LNA_CTL_USE_ANT1       BIT(7)
+
 enum eeprom_param {
        EEP_NFTHRESH_5,
        EEP_NFTHRESH_2,
@@ -378,10 +390,7 @@ struct modal_eep_header {
        u8 xatten2Margin[AR5416_MAX_CHAINS];
        u8 ob_ch1;
        u8 db_ch1;
-       u8 useAnt1:1,
-           force_xpaon:1,
-           local_bias:1,
-           femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
+       u8 lna_ctl;
        u8 miscBits;
        u16 xpaBiasLvlFreq[3];
        u8 futureModal[6];
@@ -535,18 +544,10 @@ struct cal_target_power_ht {
        u8 tPow2x[8];
 } __packed;
 
-
-#ifdef __BIG_ENDIAN_BITFIELD
-struct cal_ctl_edges {
-       u8 bChannel;
-       u8 flag:2, tPower:6;
-} __packed;
-#else
 struct cal_ctl_edges {
        u8 bChannel;
-       u8 tPower:6, flag:2;
+       u8 ctl;
 } __packed;
-#endif
 
 struct cal_data_op_loop_ar9287 {
        u8 pwrPdg[2][5];
index 76b4d65..a3ccb1b 100644 (file)
@@ -451,9 +451,10 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
                ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
                                          AR_AN_TOP2_LOCALBIAS,
                                          AR_AN_TOP2_LOCALBIAS_S,
-                                         pModal->local_bias);
+                                         !!(pModal->lna_ctl &
+                                            LNA_CTL_LOCAL_BIAS));
                REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
-                             pModal->force_xpaon);
+                             !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
        }
 
        REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
@@ -1062,15 +1063,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
 
-       scaledPower = max((u16)0, scaledPower);
-
        if (IS_CHAN_2GHZ(chan)) {
                numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
                        SUB_NUM_CTL_MODES_AT_2G_40;
@@ -1428,9 +1433,9 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 
        num_ant_config = 1;
 
-       if (pBase->version >= 0x0E0D)
-               if (pModal->useAnt1)
-                       num_ant_config += 1;
+       if (pBase->version >= 0x0E0D &&
+           (pModal->lna_ctl & LNA_CTL_USE_ANT1))
+               num_ant_config += 1;
 
        return num_ant_config;
 }
index dfb6560..0de3c3d 100644 (file)
@@ -1024,6 +1024,13 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
        struct hif_device_usb *hif_dev =
                (struct hif_device_usb *) usb_get_intfdata(interface);
 
+       /*
+        * The device has to be set to FULLSLEEP mode in case no
+        * interface is up.
+        */
+       if (!(hif_dev->flags & HIF_USB_START))
+               ath9k_htc_suspend(hif_dev->htc_handle);
+
        ath9k_hif_usb_dealloc_urbs(hif_dev);
 
        return 0;
index 75ecf6a..c3b561d 100644 (file)
@@ -455,6 +455,8 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
@@ -464,6 +466,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
                           u16 devid, char *product);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
+void ath9k_htc_suspend(struct htc_target *htc_handle);
 int ath9k_htc_resume(struct htc_target *htc_handle);
 #endif
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
index 7c8a38d..8776f49 100644 (file)
@@ -891,6 +891,12 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 }
 
 #ifdef CONFIG_PM
+
+void ath9k_htc_suspend(struct htc_target *htc_handle)
+{
+       ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
+}
+
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
        int ret;
index 9a3be8d..51977ca 100644 (file)
@@ -63,8 +63,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
        return mode;
 }
 
-static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
-                              enum ath9k_power_mode mode)
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode)
 {
        bool ret;
 
index 6ebc68b..c7fbe25 100644 (file)
@@ -2044,7 +2044,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
                val = REG_READ(ah, AR7010_GPIO_IN);
                return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
        } else if (AR_SREV_9300_20_OR_LATER(ah))
-               return MS_REG_READ(AR9300, gpio) != 0;
+               return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
+                       AR_GPIO_BIT(gpio)) != 0;
        else if (AR_SREV_9271(ah))
                return MS_REG_READ(AR9271, gpio) != 0;
        else if (AR_SREV_9287_11_OR_LATER(ah))
index 92bc5c5..14b8ab3 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/pm_qos_params.h>
 
 #include "ath9k.h"
 
@@ -180,8 +179,6 @@ static const struct ath_ops ath9k_common_ops = {
        .write = ath9k_iowrite32,
 };
 
-struct pm_qos_request_list ath9k_pm_qos_req;
-
 /**************************/
 /*     Initialization     */
 /**************************/
@@ -664,6 +661,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
        hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_WDS) |
                BIT(NL80211_IFTYPE_STATION) |
@@ -759,7 +758,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
 
-       pm_qos_add_request(&ath9k_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
+       pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
                           PM_QOS_DEFAULT_VALUE);
 
        return 0;
@@ -830,7 +829,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
        }
 
        ieee80211_unregister_hw(hw);
-       pm_qos_remove_request(&ath9k_pm_qos_req);
+       pm_qos_remove_request(&sc->pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 8c13479..c996963 100644 (file)
@@ -703,8 +703,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
                        rs->rs_phyerr = phyerr;
                } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
-               else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
-                        rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+               else if (ads.ds_rxstatus8 & AR_MichaelErr)
                        rs->rs_status |= ATH9K_RXERR_MIC;
                else if (ads.ds_rxstatus8 & AR_KeyMiss)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
index 25d3ef4..c0c3464 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/nl80211.h>
-#include <linux/pm_qos_params.h>
 #include "ath9k.h"
 #include "btcoex.h"
 
@@ -245,11 +244,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
         * the relevant bits of the h/w.
         */
        ath9k_hw_set_interrupts(ah, 0);
-       ath_drain_all_txq(sc, false);
+       stopped = ath_drain_all_txq(sc, false);
 
        spin_lock_bh(&sc->rx.pcu_lock);
 
-       stopped = ath_stoprecv(sc);
+       if (!ath_stoprecv(sc))
+               stopped = false;
 
        /* XXX: do not flush receive queue here. We don't want
         * to flush data frames already in queue because of
@@ -1244,7 +1244,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
                        ath9k_btcoex_timer_resume(sc);
        }
 
-       pm_qos_update_request(&ath9k_pm_qos_req, 55);
+       pm_qos_update_request(&sc->pm_qos_req, 55);
 
 mutex_unlock:
        mutex_unlock(&sc->mutex);
@@ -1423,7 +1423,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        sc->sc_flags |= SC_OP_INVALID;
 
-       pm_qos_update_request(&ath9k_pm_qos_req, PM_QOS_DEFAULT_VALUE);
+       pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
 
        mutex_unlock(&sc->mutex);
 
@@ -1520,7 +1520,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
-       int i;
 
        ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
@@ -1534,21 +1533,24 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+               /* Disable SWBA interrupt */
+               sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
                ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
                ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
                ath9k_ps_restore(sc);
+               tasklet_kill(&sc->bcon_tasklet);
        }
 
        ath_beacon_return(sc, avp);
        sc->sc_flags &= ~SC_OP_BEACONS;
 
-       for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-               if (sc->beacon.bslot[i] == vif) {
-                       printk(KERN_DEBUG "%s: vif had allocated beacon "
-                              "slot\n", __func__);
-                       sc->beacon.bslot[i] = NULL;
-                       sc->beacon.bslot_aphy[i] = NULL;
-               }
+       if (sc->nbcnvifs) {
+               /* Re-enable SWBA interrupt */
+               sc->sc_ah->imask |= ATH9K_INT_SWBA;
+               ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+               ath9k_ps_restore(sc);
        }
 
        sc->nvifs--;
index 1a62e35..fdc2ec5 100644 (file)
@@ -838,6 +838,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
                            struct ath_rx_status *rx_stats,
                            bool *decrypt_error)
 {
+#define is_mc_or_valid_tkip_keyix ((is_mc ||                   \
+               (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
+
        struct ath_hw *ah = common->ah;
        __le16 fc;
        u8 rx_status_len = ah->caps.rx_status_len;
@@ -879,15 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
                if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
                        *decrypt_error = true;
                } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+                       bool is_mc;
                        /*
                         * The MIC error bit is only valid if the frame
                         * is not a control frame or fragment, and it was
                         * decrypted using a valid TKIP key.
                         */
+                       is_mc = !!is_multicast_ether_addr(hdr->addr1);
+
                        if (!ieee80211_is_ctl(fc) &&
                            !ieee80211_has_morefrags(fc) &&
                            !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-                           test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+                           is_mc_or_valid_tkip_keyix)
                                rxs->flag |= RX_FLAG_MMIC_ERROR;
                        else
                                rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
index dddf579..2c6a22f 100644 (file)
@@ -984,11 +984,13 @@ enum {
 #define AR9287_GPIO_IN_VAL_S                     11
 #define AR9271_GPIO_IN_VAL                       0xFFFF0000
 #define AR9271_GPIO_IN_VAL_S                     16
-#define AR9300_GPIO_IN_VAL                       0x0001FFFF
-#define AR9300_GPIO_IN_VAL_S                     0
 #define AR7010_GPIO_IN_VAL                       0x0000FFFF
 #define AR7010_GPIO_IN_VAL_S                     0
 
+#define AR_GPIO_IN                              0x404c
+#define AR9300_GPIO_IN_VAL                       0x0001FFFF
+#define AR9300_GPIO_IN_VAL_S                     0
+
 #define AR_GPIO_OE_OUT                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
 #define AR_GPIO_OE_OUT_DRV                       0x3
 #define AR_GPIO_OE_OUT_DRV_NO                    0x0
index f2ade24..aff0478 100644 (file)
@@ -1120,7 +1120,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        }
 }
 
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -1128,7 +1128,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
        int i, npend = 0;
 
        if (sc->sc_flags & SC_OP_INVALID)
-               return;
+               return true;
 
        /* Stop beacon queue */
        ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1142,25 +1142,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       if (npend) {
-               int r;
-
-               ath_print(common, ATH_DBG_FATAL,
-                         "Failed to stop TX DMA. Resetting hardware!\n");
-
-               spin_lock_bh(&sc->sc_resetlock);
-               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
-               if (r)
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unable to reset hardware; reset status %d\n",
-                                 r);
-               spin_unlock_bh(&sc->sc_resetlock);
-       }
+       if (npend)
+               ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n");
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i))
                        ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
        }
+
+       return !npend;
 }
 
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
index ae6c006..546b4e4 100644 (file)
@@ -291,7 +291,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 
                if (SUPP(CARL9170FW_WLANTX_CAB)) {
                        ar->hw->wiphy->interface_modes |=
-                               BIT(NL80211_IFTYPE_AP);
+                               BIT(NL80211_IFTYPE_AP) |
+                               BIT(NL80211_IFTYPE_P2P_GO);
                }
        }
 
index a314c2c..dc7b30b 100644 (file)
@@ -1631,7 +1631,8 @@ void *carl9170_alloc(size_t priv_size)
         * supports these modes. The code which will add the
         * additional interface_modes is in fw.c.
         */
-       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                    BIT(NL80211_IFTYPE_P2P_CLIENT);
 
        hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
index b575c86..7e6506a 100644 (file)
@@ -810,7 +810,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
 
        mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
                              AR9170_TX_MAC_BACKOFF);
-       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
+       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &
                               AR9170_TX_MAC_QOS);
 
        no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
index e5685dc..b4de0ca 100644 (file)
@@ -1170,7 +1170,6 @@ static void if_sdio_remove(struct sdio_func *func)
        lbs_deb_sdio("call remove card\n");
        lbs_stop_card(card->priv);
        lbs_remove_card(card->priv);
-       card->priv->surpriseremoved = 1;
 
        flush_workqueue(card->workqueue);
        destroy_workqueue(card->workqueue);
index 79bcb4e..ecd4d04 100644 (file)
@@ -1055,7 +1055,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
        lbs_stop_card(priv);
        lbs_remove_card(priv); /* will call free_netdev */
 
-       priv->surpriseremoved = 1;
        free_irq(spi->irq, card);
        if_spi_terminate_spi_thread(card);
        if (card->pdata->teardown)
index 46b88b1..fcd1bbf 100644 (file)
@@ -915,8 +915,6 @@ void lbs_remove_card(struct lbs_private *priv)
 
        lbs_free_adapter(priv);
        lbs_cfg_free(priv);
-
-       priv->dev = NULL;
        free_netdev(dev);
 
        lbs_deb_leave(LBS_DEB_MAIN);
index e8e2d0f..f3d396e 100644 (file)
@@ -1392,10 +1392,9 @@ static void orinoco_process_scan_results(struct work_struct *work)
                                orinoco_add_hostscan_results(priv, buf, len);
 
                        kfree(buf);
-               } else if (priv->scan_request) {
+               } else {
                        /* Either abort or complete the scan */
-                       cfg80211_scan_done(priv->scan_request, (len < 0));
-                       priv->scan_request = NULL;
+                       orinoco_scan_done(priv, (len < 0));
                }
 
                spin_lock_irqsave(&priv->scan_lock, flags);
@@ -1684,6 +1683,8 @@ static int __orinoco_down(struct orinoco_private *priv)
                hermes_write_regn(hw, EVACK, 0xffff);
        }
 
+       orinoco_scan_done(priv, true);
+
        /* firmware will have to reassociate */
        netif_carrier_off(dev);
        priv->last_linkstatus = 0xffff;
@@ -1762,10 +1763,7 @@ void orinoco_reset(struct work_struct *work)
        orinoco_unlock(priv, &flags);
 
        /* Scanning support: Notify scan cancellation */
-       if (priv->scan_request) {
-               cfg80211_scan_done(priv->scan_request, 1);
-               priv->scan_request = NULL;
-       }
+       orinoco_scan_done(priv, true);
 
        if (priv->hard_reset) {
                err = (*priv->hard_reset)(priv);
@@ -1813,6 +1811,12 @@ static int __orinoco_commit(struct orinoco_private *priv)
        struct net_device *dev = priv->ndev;
        int err = 0;
 
+       /* If we've called commit, we are reconfiguring or bringing the
+        * interface up. Maintaining countermeasures across this would
+        * be confusing, so note that we've disabled them. The port will
+        * be enabled later in orinoco_commit or __orinoco_up. */
+       priv->tkip_cm_active = 0;
+
        err = orinoco_hw_program_rids(priv);
 
        /* FIXME: what about netif_tx_lock */
index 71b3d68..32954c4 100644 (file)
@@ -151,20 +151,20 @@ orinoco_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 4300d9d..86cb54c 100644 (file)
@@ -229,3 +229,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
                priv->scan_request = NULL;
        }
 }
+
+void orinoco_scan_done(struct orinoco_private *priv, bool abort)
+{
+       if (priv->scan_request) {
+               cfg80211_scan_done(priv->scan_request, abort);
+               priv->scan_request = NULL;
+       }
+}
index 2dc4e04..27281fb 100644 (file)
@@ -16,5 +16,6 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
 void orinoco_add_hostscan_results(struct orinoco_private *dev,
                                  unsigned char *buf,
                                  size_t len);
+void orinoco_scan_done(struct orinoco_private *priv, bool abort);
 
 #endif /* _ORINOCO_SCAN_H_ */
index fb859a5..db34c28 100644 (file)
@@ -214,21 +214,21 @@ spectrum_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
        hw->eeprom_pda = true;
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 93505f9..e5afabe 100644 (file)
@@ -911,10 +911,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
                 */
                if (param->value) {
                        priv->tkip_cm_active = 1;
-                       ret = hermes_enable_port(hw, 0);
+                       ret = hermes_disable_port(hw, 0);
                } else {
                        priv->tkip_cm_active = 0;
-                       ret = hermes_disable_port(hw, 0);
+                       ret = hermes_enable_port(hw, 0);
                }
                break;
 
index 458bb57..cdbeec9 100644 (file)
@@ -66,8 +66,8 @@ struct netfront_cb {
 
 #define GRANT_INVALID_REF      0
 
-#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
-#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
+#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
 #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
 
 struct netfront_info {
index 003170e..69546e9 100644 (file)
@@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)
        }
 }
 
-static bool pci_bus_resource_better(struct resource *res1, bool pos1,
-                                   struct resource *res2, bool pos2)
-{
-       /* If exactly one is positive decode, always prefer that one */
-       if (pos1 != pos2)
-               return pos1 ? true : false;
-
-       /* Prefer the one that contains the highest address */
-       if (res1->end != res2->end)
-               return (res1->end > res2->end) ? true : false;
-
-       /* Otherwise, prefer the one with highest "center of gravity" */
-       if (res1->start != res2->start)
-               return (res1->start > res2->start) ? true : false;
-
-       /* Otherwise, choose one arbitrarily (but consistently) */
-       return (res1 > res2) ? true : false;
-}
-
-static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
-{
-       struct pci_bus_resource *bus_res;
-
-       /*
-        * This relies on the fact that pci_bus.resource[] refers to P2P or
-        * CardBus bridge base/limit registers, which are always positively
-        * decoded.  The pci_bus.resources list contains host bridge or
-        * subtractively decoded resources.
-        */
-       list_for_each_entry(bus_res, &bus->resources, list) {
-               if (bus_res->res == res)
-                       return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
-                               false : true;
-       }
-       return true;
-}
-
-/*
- * Find the next-best bus resource after the cursor "res".  If the cursor is
- * NULL, return the best resource.  "Best" means that we prefer positive
- * decode regions over subtractive decode, then those at higher addresses.
- */
-static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
-                                                  unsigned int type,
-                                                  struct resource *res)
-{
-       bool res_pos, r_pos, prev_pos = false;
-       struct resource *r, *prev = NULL;
-       int i;
-
-       res_pos = pci_bus_resource_positive(bus, res);
-       pci_bus_for_each_resource(bus, r, i) {
-               if (!r)
-                       continue;
-
-               if ((r->flags & IORESOURCE_TYPE_BITS) != type)
-                       continue;
-
-               r_pos = pci_bus_resource_positive(bus, r);
-               if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) {
-                       if (!prev || pci_bus_resource_better(r, r_pos,
-                                                            prev, prev_pos)) {
-                               prev = r;
-                               prev_pos = r_pos;
-                       }
-               }
-       }
-
-       return prev;
-}
-
 /**
  * pci_bus_alloc_resource - allocate a resource from a parent bus
  * @bus: PCI bus
@@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                                          resource_size_t),
                void *alignf_data)
 {
-       int ret = -ENOMEM;
+       int i, ret = -ENOMEM;
        struct resource *r;
        resource_size_t max = -1;
-       unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
 
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
@@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
        if (!(res->flags & IORESOURCE_MEM_64))
                max = PCIBIOS_MAX_MEM_32;
 
-       /* Look for space at highest addresses first */
-       r = pci_bus_find_resource_prev(bus, type, NULL);
-       for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
+       pci_bus_for_each_resource(bus, r, i) {
+               if (!r)
+                       continue;
+
                /* type_mask must match */
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
index 6f9350c..313c0bd 100644 (file)
@@ -2329,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
 {
        u32 cfg;
 
+       if (!pci_find_capability(dev, PCI_CAP_ID_HT))
+               return;
+
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
index 2d73dfc..57313f4 100644 (file)
@@ -180,7 +180,7 @@ struct pnp_protocol pnpacpi_protocol = {
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
-static char *pnpacpi_get_id(struct acpi_device *device)
+static char *__init pnpacpi_get_id(struct acpi_device *device)
 {
        struct acpi_hardware_id *id;
 
index 51237fb..6d20b04 100644 (file)
@@ -231,8 +231,7 @@ static int tps6586x_dvm_voltages[] = {
 };
 
 #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits,       \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)    \
-{                                                                      \
+                          ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_##_ops,                   \
@@ -248,18 +247,26 @@ static int tps6586x_dvm_voltages[] = {
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
        .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,                  \
-}
+       .voltages       = tps6586x_##vdata##_voltages,
+
+#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
+       .go_reg = TPS6586X_##goreg,                                     \
+       .go_bit = (gobit),
 
 #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1)                        \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, 0, 0)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+}
 
 #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+       TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
+}
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
@@ -267,11 +274,11 @@ static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
        TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
        TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6),
+       TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
        TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7),
+       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
        TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1),
+       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
 
        TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
        TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
@@ -290,6 +297,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        uint8_t val1, val2;
        int ret;
 
+       if (ri->enable_reg[0] == ri->enable_reg[1] &&
+           ri->enable_bit[0] == ri->enable_bit[1])
+                       return 0;
+
        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
        if (ret)
                return ret;
@@ -298,14 +309,14 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        if (ret)
                return ret;
 
-       if (!(val2 & ri->enable_bit[1]))
+       if (!(val2 & (1 << ri->enable_bit[1])))
                return 0;
 
        /*
         * The regulator is on, but it's enabled with the bit we don't
         * want to use, so we switch the enable bits
         */
-       if (!(val1 & ri->enable_bit[0])) {
+       if (!(val1 & (1 << ri->enable_bit[0]))) {
                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
                                        1 << ri->enable_bit[0]);
                if (ret)
index d37c733..0bcd580 100644 (file)
@@ -156,6 +156,8 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
                if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
                      a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
                        return 0;
+               if (p_status & ZFCP_STATUS_COMMON_NOESC)
+                       return need;
                if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
                        need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
                /* fall through */
@@ -188,6 +190,9 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
                                &zfcp_sdev->status);
                erp_action = &zfcp_sdev->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
+               erp_action->sdev = sdev;
                if (!(atomic_read(&zfcp_sdev->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -200,6 +205,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_port(port);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
                erp_action = &port->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
                if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
                break;
@@ -209,6 +216,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_adapter(adapter);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
                erp_action = &adapter->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -218,10 +226,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                return NULL;
        }
 
-       memset(erp_action, 0, sizeof(struct zfcp_erp_action));
        erp_action->adapter = adapter;
-       erp_action->port = port;
-       erp_action->sdev = sdev;
        erp_action->action = need;
        erp_action->status = act_status;
 
index be03174..2eb7dd5 100644 (file)
@@ -851,7 +851,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-       req->data = zfcp_sdev;
+       req->data = sdev;
        req->handler = zfcp_fsf_abort_fcp_command_handler;
        req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
        req->qtcb->header.port_handle = zfcp_sdev->port->handle;
@@ -2069,8 +2069,6 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
        struct fcp_resp_with_ext *fcp_rsp;
        unsigned long flags;
 
-       zfcp_fsf_fcp_handler_common(req);
-
        read_lock_irqsave(&req->adapter->abort_lock, flags);
 
        scpnt = req->data;
@@ -2079,6 +2077,8 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
                return;
        }
 
+       zfcp_fsf_fcp_handler_common(req);
+
        if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
                set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
                goto skip_fsfstatus;
@@ -2170,12 +2170,13 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct zfcp_qdio *qdio = adapter->qdio;
        struct fsf_qtcb_bottom_io *io;
+       unsigned long flags;
 
        if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return -EBUSY;
 
-       spin_lock(&qdio->req_q_lock);
+       spin_lock_irqsave(&qdio->req_q_lock, flags);
        if (atomic_read(&qdio->req_q_free) <= 0) {
                atomic_inc(&qdio->req_q_full);
                goto out;
@@ -2239,7 +2240,7 @@ failed_scsi_cmnd:
        zfcp_fsf_req_free(req);
        scsi_cmnd->host_scribble = NULL;
 out:
-       spin_unlock(&qdio->req_q_lock);
+       spin_unlock_irqrestore(&qdio->req_q_lock, flags);
        return retval;
 }
 
index 6bd2dbc..63529ed 100644 (file)
@@ -76,8 +76,8 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
        scpnt->scsi_done(scpnt);
 }
 
-static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
-                                 void (*done) (struct scsi_cmnd *))
+static
+int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
 {
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -87,7 +87,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        /* reset the status for this request */
        scpnt->result = 0;
        scpnt->host_scribble = NULL;
-       scpnt->scsi_done = done;
 
        scsi_result = fc_remote_port_chkready(rport);
        if (unlikely(scsi_result)) {
@@ -127,8 +126,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        return ret;
 }
 
-static DEF_SCSI_QCMD(zfcp_scsi_queuecommand)
-
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
        struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
index b2fb2b2..a6dea08 100644 (file)
@@ -90,11 +90,7 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
-#define PCI_DEVICE_ID_HP_CISSF 0x333f
-       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x333F},
-       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
-       {PCI_VENDOR_ID_COMPAQ,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
+       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
 };
@@ -113,8 +109,6 @@ static struct board_type products[] = {
        {0x3249103C, "Smart Array P812", &SA5_access},
        {0x324a103C, "Smart Array P712m", &SA5_access},
        {0x324b103C, "Smart Array P711m", &SA5_access},
-       {0x3233103C, "StorageWorks P1210m", &SA5_access},
-       {0x333F103C, "StorageWorks P1210m", &SA5_access},
        {0x3250103C, "Smart Array", &SA5_access},
        {0x3250113C, "Smart Array", &SA5_access},
        {0x3250123C, "Smart Array", &SA5_access},
index 0433ea6..b37c8a3 100644 (file)
@@ -951,8 +951,8 @@ static int _osd_req_finalize_cdb_cont(struct osd_request *or, const u8 *cap_key)
        /* create a bio for continuation segment */
        bio = bio_map_kern(req_q, or->cdb_cont.buff, or->cdb_cont.total_bytes,
                           GFP_KERNEL);
-       if (unlikely(!bio))
-               return -ENOMEM;
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
 
        bio->bi_rw |= REQ_WRITE;
 
index 5e76a62..300d59f 100644 (file)
@@ -62,6 +62,7 @@
 static unsigned int pmcraid_debug_log;
 static unsigned int pmcraid_disable_aen;
 static unsigned int pmcraid_log_level = IOASC_LOG_LEVEL_MUST;
+static unsigned int pmcraid_enable_msix;
 
 /*
  * Data structures to support multiple adapters by the LLD.
@@ -4691,7 +4692,8 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)
        int rc;
        struct pci_dev *pdev = pinstance->pdev;
 
-       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+       if ((pmcraid_enable_msix) &&
+               (pci_find_capability(pdev, PCI_CAP_ID_MSIX))) {
                int num_hrrq = PMCRAID_NUM_MSIX_VECTORS;
                struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS];
                int i;
index 1134279..4db210d 100644 (file)
@@ -42,7 +42,7 @@
  */
 #define PMCRAID_DRIVER_NAME            "PMC MaxRAID"
 #define PMCRAID_DEVFILE                        "pmcsas"
-#define PMCRAID_DRIVER_VERSION         "2.0.3"
+#define PMCRAID_DRIVER_VERSION         "1.0.3"
 #define PMCRAID_DRIVER_DATE            __DATE__
 
 #define PMCRAID_FW_VERSION_1           0x002
@@ -333,11 +333,9 @@ struct pmcraid_config_table_entry {
        __u8  lun[PMCRAID_LUN_LEN];
 } __attribute__((packed, aligned(4)));
 
-/* extended configuration table sizes are of 64 bytes in size */
-#define PMCRAID_CFGTE_EXT_SIZE 32
+/* extended configuration table sizes are also of 32 bytes in size */
 struct pmcraid_config_table_entry_ext {
        struct pmcraid_config_table_entry cfgte;
-       __u8  cfgte_ext[PMCRAID_CFGTE_EXT_SIZE];
 };
 
 /* resource types (config_table_entry.resource_type values) */
index 3a22eff..9ce539d 100644 (file)
@@ -2409,7 +2409,6 @@ struct qla_hw_data {
                uint32_t        enable_target_reset     :1;
                uint32_t        enable_lip_full_login   :1;
                uint32_t        enable_led_scheme       :1;
-               uint32_t        inta_enabled            :1;
                uint32_t        msi_enabled             :1;
                uint32_t        msix_enabled            :1;
                uint32_t        disable_serdes          :1;
index 5f94430..4c1ba62 100644 (file)
@@ -1061,6 +1061,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
                fcp_cmnd->additional_cdb_len |= 2;
 
        int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
+       host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun));
        memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
        cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
        cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
index 1f06ddd..7f77898 100644 (file)
@@ -2491,14 +2491,15 @@ skip_msix:
 skip_msi:
 
        ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
-           IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
+           ha->flags.msi_enabled ? 0 : IRQF_SHARED,
+           QLA2XXX_DRIVER_NAME, rsp);
        if (ret) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to reserve interrupt %d already in use.\n",
                    ha->pdev->irq);
                goto fail;
        }
-       ha->flags.inta_enabled = 1;
+
 clear_risc_ints:
 
        /*
index 8d9edfb..ae2acac 100644 (file)
@@ -2749,6 +2749,7 @@ sufficient_dsds:
                        goto queuing_error_fcp_cmnd;
 
                int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+               host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
                /* build FCP_CMND IU */
                memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
index 1644eab..2c0876c 100644 (file)
@@ -829,7 +829,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *vha = shost_priv(cmd->device->host);
        srb_t *sp;
-       int ret;
+       int ret = SUCCESS;
        unsigned int id, lun;
        unsigned long flags;
        int wait = 0;
@@ -2064,6 +2064,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
                ha->gid_list_info_size = 8;
                ha->optrom_size = OPTROM_SIZE_82XX;
+               ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
                ha->isp_ops = &qla82xx_isp_ops;
                ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
index 8edbccb..cf0075a 100644 (file)
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.04-k0"
+#define QLA2XXX_VERSION      "8.03.05-k0"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
-#define QLA_DRIVER_PATCH_VER   4
+#define QLA_DRIVER_PATCH_VER   5
 #define QLA_DRIVER_BETA_VER    0
index 824b8fc..30ac116 100644 (file)
@@ -615,7 +615,7 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
        return rtn;
 }
 
-static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
 {
        if (!scmd->device->host->hostt->eh_abort_handler)
                return FAILED;
@@ -623,31 +623,9 @@ static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
        return scmd->device->host->hostt->eh_abort_handler(scmd);
 }
 
-/**
- * scsi_try_to_abort_cmd - Ask host to abort a running command.
- * @scmd:      SCSI cmd to abort from Lower Level.
- *
- * Notes:
- *    This function will not return until the user's completion function
- *    has been called.  there is no timeout on this operation.  if the
- *    author of the low-level driver wishes this operation to be timed,
- *    they can provide this facility themselves.  helper functions in
- *    scsi_error.c can be supplied to make this easier to do.
- */
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
-{
-       /*
-        * scsi_done was called just after the command timed out and before
-        * we had a chance to process it. (db)
-        */
-       if (scmd->serial_number == 0)
-               return SUCCESS;
-       return __scsi_try_to_abort_cmd(scmd);
-}
-
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-       if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+       if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
                if (scsi_try_bus_device_reset(scmd) != SUCCESS)
                        if (scsi_try_target_reset(scmd) != SUCCESS)
                                if (scsi_try_bus_reset(scmd) != SUCCESS)
index eafeeda..5b6bbae 100644 (file)
@@ -1403,11 +1403,6 @@ static void scsi_softirq_done(struct request *rq)
 
        INIT_LIST_HEAD(&cmd->eh_entry);
 
-       /*
-        * Set the serial numbers back to zero
-        */
-       cmd->serial_number = 0;
-
        atomic_inc(&cmd->device->iodone_cnt);
        if (cmd->result)
                atomic_inc(&cmd->device->ioerr_cnt);
index 3374618..25a8bc5 100644 (file)
@@ -90,7 +90,8 @@ static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
 
 static void kgdboc_restore_input(void)
 {
-       schedule_work(&kgdboc_restore_input_work);
+       if (likely(system_state == SYSTEM_RUNNING))
+               schedule_work(&kgdboc_restore_input_work);
 }
 
 static int kgdboc_register_kbd(char **cptr)
index 9043931..0838c79 100644 (file)
@@ -413,6 +413,11 @@ static void poll_transfer(struct dw_spi *dws)
 {
        while (dws->write(dws))
                dws->read(dws);
+       /*
+        * There is a possibility that the last word of a transaction
+        * will be lost if data is not ready. Re-read to solve this issue.
+        */
+       dws->read(dws);
 
        transfer_complete(dws);
 }
index 05bf5a2..989e16e 100644 (file)
@@ -951,7 +951,9 @@ static int usbatm_atm_init(struct usbatm_data *instance)
         * condition: callbacks we register can be executed at once, before we have
         * initialized the struct atm_dev.  To protect against this, all callbacks
         * abort if atm_dev->dev_data is NULL. */
-       atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
+       atm_dev = atm_dev_register(instance->driver_name,
+                                  &instance->usb_intf->dev, &usbatm_atm_devops,
+                                  -1, NULL);
        if (!atm_dev) {
                usb_err(instance, "%s: failed to register ATM device!\n", __func__);
                return -1;
@@ -966,14 +968,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        /* temp init ATM device, set to 128kbit */
        atm_dev->link_rate = 128 * 1000 / 424;
 
-       ret = sysfs_create_link(&atm_dev->class_dev.kobj,
-                               &instance->usb_intf->dev.kobj, "device");
-       if (ret) {
-               atm_err(instance, "%s: sysfs_create_link failed: %d\n",
-                                       __func__, ret);
-               goto fail_sysfs;
-       }
-
        if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
                atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
                goto fail;
@@ -992,8 +986,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        return 0;
 
  fail:
-       sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
- fail_sysfs:
        instance->atm_dev = NULL;
        atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
        return ret;
@@ -1329,7 +1321,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
 
        /* ATM finalize */
        if (instance->atm_dev) {
-               sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
                atm_dev_deregister(instance->atm_dev);
                instance->atm_dev = NULL;
        }
index 94701ff..159c77a 100644 (file)
@@ -884,6 +884,7 @@ static int log_write(void __user *log_base,
        int r;
        if (!write_length)
                return 0;
+       write_length += write_address % VHOST_PAGE_SIZE;
        write_address /= VHOST_PAGE_SIZE;
        for (;;) {
                u64 base = (u64)(unsigned long)log_base;
@@ -897,7 +898,7 @@ static int log_write(void __user *log_base,
                if (write_length <= VHOST_PAGE_SIZE)
                        break;
                write_length -= VHOST_PAGE_SIZE;
-               write_address += VHOST_PAGE_SIZE;
+               write_address += 1;
        }
        return r;
 }
index 0a4dbdc..de450c1 100644 (file)
@@ -855,6 +855,7 @@ const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
                        abs(cmode->yres - mode->yres);
                if (diff > d) {
                        diff = d;
+                       diff_refresh = abs(cmode->refresh - mode->refresh);
                        best = cmode;
                } else if (diff == d) {
                        d = abs(cmode->refresh - mode->refresh);
index c547cca..51d2e4d 100644 (file)
@@ -696,6 +696,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                                   __btree_submit_bio_done);
 }
 
+#ifdef CONFIG_MIGRATION
 static int btree_migratepage(struct address_space *mapping,
                        struct page *newpage, struct page *page)
 {
@@ -712,12 +713,9 @@ static int btree_migratepage(struct address_space *mapping,
        if (page_has_private(page) &&
            !try_to_release_page(page, GFP_KERNEL))
                return -EAGAIN;
-#ifdef CONFIG_MIGRATION
        return migrate_page(mapping, newpage, page);
-#else
-       return -ENOSYS;
-#endif
 }
+#endif
 
 static int btree_writepage(struct page *page, struct writeback_control *wbc)
 {
@@ -1009,7 +1007,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
        blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       BUG_ON(!root->node);
+       if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+               free_extent_buffer(root->node);
+               return -EIO;
+       }
        root->commit_root = btrfs_root_node(root);
        return 0;
 }
index bcd59c7..227e581 100644 (file)
@@ -429,6 +429,7 @@ err:
 
 static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_trans_handle *trans,
+                            struct btrfs_root *root,
                             int load_cache_only)
 {
        struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -442,9 +443,12 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
-        * to have the normal tree locking.
+        * to have the normal tree locking.  Also if we are currently trying to
+        * allocate blocks for the tree root we can't do the fast caching since
+        * we likely hold important locks.
         */
-       if (!trans->transaction->in_commit) {
+       if (!trans->transaction->in_commit &&
+           (root && root != root->fs_info->tree_root)) {
                spin_lock(&cache->lock);
                if (cache->cached != BTRFS_CACHE_NO) {
                        spin_unlock(&cache->lock);
@@ -2741,6 +2745,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        struct btrfs_root *root = block_group->fs_info->tree_root;
        struct inode *inode = NULL;
        u64 alloc_hint = 0;
+       int dcs = BTRFS_DC_ERROR;
        int num_pages = 0;
        int retries = 0;
        int ret = 0;
@@ -2795,6 +2800,8 @@ again:
 
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED) {
+               /* We're not cached, don't bother trying to write stuff out */
+               dcs = BTRFS_DC_WRITTEN;
                spin_unlock(&block_group->lock);
                goto out_put;
        }
@@ -2821,6 +2828,8 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
                                              num_pages, num_pages,
                                              &alloc_hint);
+       if (!ret)
+               dcs = BTRFS_DC_SETUP;
        btrfs_free_reserved_data_space(inode, num_pages);
 out_put:
        iput(inode);
@@ -2828,10 +2837,7 @@ out_free:
        btrfs_release_path(root, path);
 out:
        spin_lock(&block_group->lock);
-       if (ret)
-               block_group->disk_cache_state = BTRFS_DC_ERROR;
-       else
-               block_group->disk_cache_state = BTRFS_DC_SETUP;
+       block_group->disk_cache_state = dcs;
        spin_unlock(&block_group->lock);
 
        return ret;
@@ -3037,7 +3043,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
-       u64 num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       u64 num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
 
        if (num_devices == 1)
                flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
@@ -4080,7 +4092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && cache->cached == BTRFS_CACHE_NO)
-                       cache_block_group(cache, trans, 1);
+                       cache_block_group(cache, trans, NULL, 1);
 
                byte_in_group = bytenr - cache->key.objectid;
                WARN_ON(byte_in_group > cache->key.offset);
@@ -4930,11 +4942,31 @@ search:
                btrfs_get_block_group(block_group);
                search_start = block_group->key.objectid;
 
+               /*
+                * this can happen if we end up cycling through all the
+                * raid types, but we want to make sure we only allocate
+                * for the proper type.
+                */
+               if (!block_group_bits(block_group, data)) {
+                   u64 extra = BTRFS_BLOCK_GROUP_DUP |
+                               BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_RAID10;
+
+                       /*
+                        * if they asked for extra copies and this block group
+                        * doesn't provide them, bail.  This does allow us to
+                        * fill raid0 from raid1.
+                        */
+                       if ((data & extra) && !(block_group->flags & extra))
+                               goto loop;
+               }
+
 have_block_group:
                if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
                        u64 free_percent;
 
-                       ret = cache_block_group(block_group, trans, 1);
+                       ret = cache_block_group(block_group, trans,
+                                               orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
                                goto have_block_group;
 
@@ -4958,7 +4990,8 @@ have_block_group:
                        if (loop > LOOP_CACHING_NOWAIT ||
                            (loop > LOOP_FIND_IDEAL &&
                             atomic_read(&space_info->caching_threads) < 2)) {
-                               ret = cache_block_group(block_group, trans, 0);
+                               ret = cache_block_group(block_group, trans,
+                                                       orig_root, 0);
                                BUG_ON(ret);
                        }
                        found_uncached_bg = true;
@@ -5515,7 +5548,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        u64 num_bytes = ins->offset;
 
        block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-       cache_block_group(block_group, trans, 0);
+       cache_block_group(block_group, trans, NULL, 0);
        caching_ctl = get_caching_control(block_group);
 
        if (!caching_ctl) {
@@ -6300,9 +6333,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                                           NULL, NULL);
                BUG_ON(ret < 0);
                if (ret > 0) {
-                       ret = btrfs_del_orphan_item(trans, tree_root,
-                                                   root->root_key.objectid);
-                       BUG_ON(ret);
+                       /* if we fail to delete the orphan item this time
+                        * around, it'll get picked up the next time.
+                        *
+                        * The most common failure here is just -ENOENT.
+                        */
+                       btrfs_del_orphan_item(trans, tree_root,
+                                             root->root_key.objectid);
                }
        }
 
@@ -7878,7 +7915,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
 
-       num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
+
        if (num_devices == 1) {
                stripped |= BTRFS_BLOCK_GROUP_DUP;
                stripped = flags & ~stripped;
@@ -8247,7 +8291,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                        break;
                if (ret != 0)
                        goto error;
-
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                cache = kzalloc(sizeof(*cache), GFP_NOFS);
index c1faded..66836d8 100644 (file)
@@ -48,30 +48,34 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
                                         struct page **prepared_pages,
                                         struct iov_iter *i)
 {
-       size_t copied;
+       size_t copied = 0;
        int pg = 0;
        int offset = pos & (PAGE_CACHE_SIZE - 1);
+       int total_copied = 0;
 
        while (write_bytes > 0) {
                size_t count = min_t(size_t,
                                     PAGE_CACHE_SIZE - offset, write_bytes);
                struct page *page = prepared_pages[pg];
-again:
-               if (unlikely(iov_iter_fault_in_readable(i, count)))
-                       return -EFAULT;
-
-               /* Copy data from userspace to the current page */
-               copied = iov_iter_copy_from_user(page, i, offset, count);
+               /*
+                * Copy data from userspace to the current page
+                *
+                * Disable pagefault to avoid recursive lock since
+                * the pages are already locked
+                */
+               pagefault_disable();
+               copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
+               pagefault_enable();
 
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
                iov_iter_advance(i, copied);
                write_bytes -= copied;
+               total_copied += copied;
 
+               /* Return to btrfs_file_aio_write to fault page */
                if (unlikely(copied == 0)) {
-                       count = min_t(size_t, PAGE_CACHE_SIZE - offset,
-                                     iov_iter_single_seg_count(i));
-                       goto again;
+                       break;
                }
 
                if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
@@ -81,7 +85,7 @@ again:
                        offset = 0;
                }
        }
-       return 0;
+       return total_copied;
 }
 
 /*
@@ -854,6 +858,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        unsigned long last_index;
        int will_write;
        int buffered = 0;
+       int copied = 0;
+       int dirty_pages = 0;
 
        will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
@@ -970,7 +976,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                WARN_ON(num_pages > nrptrs);
                memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-               ret = btrfs_delalloc_reserve_space(inode, write_bytes);
+               /*
+                * Fault pages before locking them in prepare_pages
+                * to avoid recursive lock
+                */
+               if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = btrfs_delalloc_reserve_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                if (ret)
                        goto out;
 
@@ -978,37 +994,49 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                                    pos, first_index, last_index,
                                    write_bytes);
                if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
+                       btrfs_delalloc_release_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                        goto out;
                }
 
-               ret = btrfs_copy_from_user(pos, num_pages,
+               copied = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, &i);
-               if (ret == 0) {
+               dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >>
+                                       PAGE_CACHE_SHIFT;
+
+               if (num_pages > dirty_pages) {
+                       if (copied > 0)
+                               atomic_inc(
+                                       &BTRFS_I(inode)->outstanding_extents);
+                       btrfs_delalloc_release_space(inode,
+                                       (num_pages - dirty_pages) <<
+                                       PAGE_CACHE_SHIFT);
+               }
+
+               if (copied > 0) {
                        dirty_and_release_pages(NULL, root, file, pages,
-                                               num_pages, pos, write_bytes);
+                                               dirty_pages, pos, copied);
                }
 
                btrfs_drop_pages(pages, num_pages);
-               if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
-                       goto out;
-               }
 
-               if (will_write) {
-                       filemap_fdatawrite_range(inode->i_mapping, pos,
-                                                pos + write_bytes - 1);
-               } else {
-                       balance_dirty_pages_ratelimited_nr(inode->i_mapping,
-                                                          num_pages);
-                       if (num_pages <
-                           (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
-                               btrfs_btree_balance_dirty(root, 1);
-                       btrfs_throttle(root);
+               if (copied > 0) {
+                       if (will_write) {
+                               filemap_fdatawrite_range(inode->i_mapping, pos,
+                                                        pos + copied - 1);
+                       } else {
+                               balance_dirty_pages_ratelimited_nr(
+                                                       inode->i_mapping,
+                                                       dirty_pages);
+                               if (dirty_pages <
+                               (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+                                       btrfs_btree_balance_dirty(root, 1);
+                               btrfs_throttle(root);
+                       }
                }
 
-               pos += write_bytes;
-               num_written += write_bytes;
+               pos += copied;
+               num_written += copied;
 
                cond_resched();
        }
index 22ee0dc..60d6842 100644 (file)
@@ -290,7 +290,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                       (unsigned long long)BTRFS_I(inode)->generation,
                       (unsigned long long)generation,
                       (unsigned long long)block_group->key.objectid);
-               goto out;
+               goto free_cache;
        }
 
        if (!num_entries)
@@ -524,6 +524,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                return 0;
        }
 
+       node = rb_first(&block_group->free_space_offset);
+       if (!node) {
+               iput(inode);
+               return 0;
+       }
+
        last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
@@ -543,10 +549,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
         */
        first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
 
-       node = rb_first(&block_group->free_space_offset);
-       if (!node)
-               goto out_free;
-
        /*
         * Lock all pages first so we can lock the extent safely.
         *
index 8039390..72f31ec 100644 (file)
@@ -495,7 +495,7 @@ again:
                add_async_extent(async_cow, start, num_bytes,
                                 total_compressed, pages, nr_pages_ret);
 
-               if (start + num_bytes < end && start + num_bytes < actual_end) {
+               if (start + num_bytes < end) {
                        start += num_bytes;
                        pages = NULL;
                        cond_resched();
@@ -5712,9 +5712,9 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
 
        if (err) {
                printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu "
-                     "disk_bytenr %lu len %u err no %d\n",
-                     dip->inode->i_ino, bio->bi_rw, bio->bi_sector,
-                     bio->bi_size, err);
+                     "sector %#Lx len %u err no %d\n",
+                     dip->inode->i_ino, bio->bi_rw,
+                     (unsigned long long)bio->bi_sector, bio->bi_size, err);
                dip->errors = 1;
 
                /*
@@ -5934,8 +5934,7 @@ free_ordered:
         */
        if (write) {
                struct btrfs_ordered_extent *ordered;
-               ordered = btrfs_lookup_ordered_extent(inode,
-                                                     dip->logical_offset);
+               ordered = btrfs_lookup_ordered_extent(inode, file_offset);
                if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) &&
                    !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags))
                        btrfs_free_reserved_extent(root, ordered->start,
index f1c9bb4..f87552a 100644 (file)
@@ -947,23 +947,42 @@ out:
 
 static noinline int btrfs_ioctl_snap_create(struct file *file,
                                            void __user *arg, int subvol,
-                                           int async)
+                                           int v2)
 {
        struct btrfs_ioctl_vol_args *vol_args = NULL;
-       struct btrfs_ioctl_async_vol_args *async_vol_args = NULL;
+       struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
        char *name;
        u64 fd;
-       u64 transid = 0;
        int ret;
 
-       if (async) {
-               async_vol_args = memdup_user(arg, sizeof(*async_vol_args));
-               if (IS_ERR(async_vol_args))
-                       return PTR_ERR(async_vol_args);
+       if (v2) {
+               u64 transid = 0;
+               u64 *ptr = NULL;
 
-               name = async_vol_args->name;
-               fd = async_vol_args->fd;
-               async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0';
+               vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
+               if (IS_ERR(vol_args_v2))
+                       return PTR_ERR(vol_args_v2);
+
+               if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               name = vol_args_v2->name;
+               fd = vol_args_v2->fd;
+               vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
+
+               if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
+                       ptr = &transid;
+
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, ptr);
+
+               if (ret == 0 && ptr &&
+                   copy_to_user(arg +
+                                offsetof(struct btrfs_ioctl_vol_args_v2,
+                                         transid), ptr, sizeof(*ptr)))
+                       ret = -EFAULT;
        } else {
                vol_args = memdup_user(arg, sizeof(*vol_args));
                if (IS_ERR(vol_args))
@@ -971,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
                name = vol_args->name;
                fd = vol_args->fd;
                vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
-       }
-
-       ret = btrfs_ioctl_snap_create_transid(file, name, fd,
-                                             subvol, &transid);
 
-       if (!ret && async) {
-               if (copy_to_user(arg +
-                               offsetof(struct btrfs_ioctl_async_vol_args,
-                               transid), &transid, sizeof(transid)))
-                       return -EFAULT;
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, NULL);
        }
-
+out:
        kfree(vol_args);
-       kfree(async_vol_args);
+       kfree(vol_args_v2);
 
        return ret;
 }
@@ -2246,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_getversion(file, argp);
        case BTRFS_IOC_SNAP_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 0, 0);
-       case BTRFS_IOC_SNAP_CREATE_ASYNC:
+       case BTRFS_IOC_SNAP_CREATE_V2:
                return btrfs_ioctl_snap_create(file, argp, 0, 1);
        case BTRFS_IOC_SUBVOL_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 1, 0);
index 17c99eb..c344d12 100644 (file)
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args {
        char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
-#define BTRFS_SNAPSHOT_NAME_MAX 4079
-struct btrfs_ioctl_async_vol_args {
+#define BTRFS_SUBVOL_CREATE_ASYNC      (1ULL << 0)
+
+#define BTRFS_SUBVOL_NAME_MAX 4039
+struct btrfs_ioctl_vol_args_v2 {
        __s64 fd;
        __u64 transid;
-       char name[BTRFS_SNAPSHOT_NAME_MAX + 1];
+       __u64 flags;
+       __u64 unused[4];
+       char name[BTRFS_SUBVOL_NAME_MAX + 1];
 };
 
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args {
                                    struct btrfs_ioctl_space_args)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
-#define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \
-                                  struct btrfs_ioctl_async_vol_args)
+#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
+                                  struct btrfs_ioctl_vol_args_v2)
 #endif
index 79cba5f..f8be250 100644 (file)
@@ -56,8 +56,12 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       if (ret)
+       if (ret < 0)
                goto out;
+       if (ret) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        ret = btrfs_del_item(trans, root, path);
 
index dbb51ea..883c6fa 100644 (file)
@@ -685,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                mutex_unlock(&root->d_inode->i_mutex);
 
                if (IS_ERR(new_root)) {
+                       dput(root);
                        deactivate_locked_super(s);
                        error = PTR_ERR(new_root);
-                       dput(root);
                        goto error_free_subvol_name;
                }
                if (!new_root->d_inode) {
index cc04dc1..6b98845 100644 (file)
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path,
 
                device->fs_devices = fs_devices;
                fs_devices->num_devices++;
-       } else if (strcmp(device->name, path)) {
+       } else if (!device->name || strcmp(device->name, path)) {
                name = kstrdup(path, GFP_NOFS);
                if (!name)
                        return -ENOMEM;
                kfree(device->name);
                device->name = name;
+               if (device->missing) {
+                       fs_devices->missing_devices--;
+                       device->missing = 0;
+               }
        }
 
        if (found_transid > fs_devices->latest_trans) {
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 
        device->fs_devices->num_devices--;
 
+       if (device->missing)
+               root->fs_info->fs_devices->missing_devices--;
+
        next_device = list_entry(root->fs_info->fs_devices->devices.next,
                                 struct btrfs_device, dev_list);
        if (device->bdev == root->fs_info->sb->s_bdev)
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
        device->devid = devid;
        device->work.func = pending_bios_fn;
        device->fs_devices = fs_devices;
+       device->missing = 1;
        fs_devices->num_devices++;
+       fs_devices->missing_devices++;
        spin_lock_init(&device->io_lock);
        INIT_LIST_HEAD(&device->dev_alloc_list);
        memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root,
                        device = add_missing_dev(root, devid, dev_uuid);
                        if (!device)
                                return -ENOMEM;
+               } else if (!device->missing) {
+                       /*
+                        * this happens when a device that was properly setup
+                        * in the device info lists suddenly goes bad.
+                        * device->bdev is NULL, and so we have to set
+                        * device->missing to one here
+                        */
+                       root->fs_info->fs_devices->missing_devices++;
+                       device->missing = 1;
                }
        }
 
index 2b638b6..2740db4 100644 (file)
@@ -44,6 +44,7 @@ struct btrfs_device {
 
        int writeable;
        int in_fs_metadata;
+       int missing;
 
        spinlock_t io_lock;
 
@@ -93,6 +94,7 @@ struct btrfs_fs_devices {
        u64 num_devices;
        u64 open_devices;
        u64 rw_devices;
+       u64 missing_devices;
        u64 total_rw_bytes;
        struct block_device *latest_bdev;
 
index 7d447af..158c700 100644 (file)
@@ -114,8 +114,8 @@ static int __dcache_readdir(struct file *filp,
        spin_lock(&dcache_lock);
 
        /* start at beginning? */
-       if (filp->f_pos == 2 || (last &&
-                                filp->f_pos < ceph_dentry(last)->offset)) {
+       if (filp->f_pos == 2 || last == NULL ||
+           filp->f_pos < ceph_dentry(last)->offset) {
                if (list_empty(&parent->d_subdirs))
                        goto out_unlock;
                p = parent->d_subdirs.prev;
index a6ce54e..52e8fd7 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x98
+#define CEPH_IOCTL_MAGIC 0x97
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
index 40abde9..476b329 100644 (file)
  * Implement fcntl and flock locking functions.
  */
 static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
-                            u64 pid, u64 pid_ns,
-                            int cmd, u64 start, u64 length, u8 wait)
+                            int cmd, u8 wait, struct file_lock *fl)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        int err;
+       u64 length = 0;
 
        req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_inode = igrab(inode);
 
+       /* mds requires start and length rather than start and end */
+       if (LLONG_MAX == fl->fl_end)
+               length = 0;
+       else
+               length = fl->fl_end - fl->fl_start + 1;
+
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
             "length: %llu, wait: %d, type`: %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd);
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type);
+
 
        req->r_args.filelock_change.rule = lock_type;
        req->r_args.filelock_change.type = cmd;
-       req->r_args.filelock_change.pid = cpu_to_le64(pid);
+       req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
        /* This should be adjusted, but I'm not sure if
           namespaces actually get id numbers*/
        req->r_args.filelock_change.pid_namespace =
-               cpu_to_le64((u64)pid_ns);
-       req->r_args.filelock_change.start = cpu_to_le64(start);
+               cpu_to_le64((u64)(unsigned long)fl->fl_nspid);
+       req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
        req->r_args.filelock_change.length = cpu_to_le64(length);
        req->r_args.filelock_change.wait = wait;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
+
+       if ( operation == CEPH_MDS_OP_GETFILELOCK){
+               fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
+               if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_RDLCK;
+               else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_WRLCK;
+               else
+                       fl->fl_type = F_UNLCK;
+
+               fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
+               length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
+                                                le64_to_cpu(req->r_reply_info.filelock_reply->length);
+               if (length >= 1)
+                       fl->fl_end = length -1;
+               else
+                       fl->fl_end = 0;
+
+       }
        ceph_mdsc_put_request(req);
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
-            "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd, err);
+            "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type,
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type, err);
        return err;
 }
 
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
  */
 int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 0;
@@ -76,29 +103,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
 
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
-
-       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                               (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl);
        if (!err) {
-               dout("mds locked, locking locally");
-               err = posix_lock_file(file, fl, NULL);
-               if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
-                       /* undo! This should only happen if the kernel detects
-                        * local deadlock. */
-                       ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                         (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
-                       dout("got %d on posix_lock_file, undid lock", err);
+               if ( op != CEPH_MDS_OP_GETFILELOCK ){
+                       dout("mds locked, locking locally");
+                       err = posix_lock_file(file, fl, NULL);
+                       if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
+                               /* undo! This should only happen if the kernel detects
+                                * local deadlock. */
+                               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
+                                                 CEPH_LOCK_UNLOCK, 0, fl);
+                               dout("got %d on posix_lock_file, undid lock", err);
+                       }
                }
+
        } else {
                dout("mds returned error code %d", err);
        }
@@ -107,7 +125,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 
 int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 1;
@@ -127,26 +144,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                lock_cmd = CEPH_LOCK_EXCL;
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
-       /* mds requires start and length rather than start and end */
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
-                               file, (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+                               file, lock_cmd, wait, fl);
        if (!err) {
                err = flock_lock_file_wait(file, fl);
                if (err) {
                        ceph_lock_message(CEPH_LOCK_FLOCK,
                                          CEPH_MDS_OP_SETFILELOCK,
-                                         file, (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
+                                         file, CEPH_LOCK_UNLOCK, 0, fl);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
                }
        } else {
index 098b185..38800ea 100644 (file)
@@ -201,6 +201,38 @@ out_bad:
        return err;
 }
 
+/*
+ * parse fcntl F_GETLK results
+ */
+static int parse_reply_info_filelock(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (*p + sizeof(*info->filelock_reply) > end)
+               goto bad;
+
+       info->filelock_reply = *p;
+       *p += sizeof(*info->filelock_reply);
+
+       if (unlikely(*p != end))
+               goto bad;
+       return 0;
+
+bad:
+       return -EIO;
+}
+
+/*
+ * parse extra results
+ */
+static int parse_reply_info_extra(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+               return parse_reply_info_filelock(p, end, info);
+       else
+               return parse_reply_info_dir(p, end, info);
+}
+
 /*
  * parse entire mds reply
  */
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg,
                        goto out_bad;
        }
 
-       /* dir content */
+       /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
-               err = parse_reply_info_dir(&p, p+len, info);
+               err = parse_reply_info_extra(&p, p+len, info);
                if (err < 0)
                        goto out_bad;
        }
@@ -2074,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        mutex_lock(&session->s_mutex);
        if (err < 0) {
-               pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds);
+               pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
                ceph_msg_dump(msg);
                goto out_err;
        }
@@ -2094,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        mutex_lock(&req->r_fill_mutex);
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
-               if (result == 0 && rinfo->dir_nr)
+               if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
+                   rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
        }
index 9341fd4..aabe563 100644 (file)
@@ -42,26 +42,37 @@ struct ceph_mds_reply_info_in {
 };
 
 /*
- * parsed info about an mds reply, including information about the
- * target inode and/or its parent directory and dentry, and directory
- * contents (for readdir results).
+ * parsed info about an mds reply, including information about
+ * either: 1) the target inode and/or its parent directory and dentry,
+ * and directory contents (for readdir results), or
+ * 2) the file range lock info (for fcntl F_GETLK results).
  */
 struct ceph_mds_reply_info_parsed {
        struct ceph_mds_reply_head    *head;
 
+       /* trace */
        struct ceph_mds_reply_info_in diri, targeti;
        struct ceph_mds_reply_dirfrag *dirfrag;
        char                          *dname;
        u32                           dname_len;
        struct ceph_mds_reply_lease   *dlease;
 
-       struct ceph_mds_reply_dirfrag *dir_dir;
-       int                           dir_nr;
-       char                          **dir_dname;
-       u32                           *dir_dname_len;
-       struct ceph_mds_reply_lease   **dir_dlease;
-       struct ceph_mds_reply_info_in *dir_in;
-       u8                            dir_complete, dir_end;
+       /* extra */
+       union {
+               /* for fcntl F_GETLK results */
+               struct ceph_filelock *filelock_reply;
+
+               /* for readdir results */
+               struct {
+                       struct ceph_mds_reply_dirfrag *dir_dir;
+                       int                           dir_nr;
+                       char                          **dir_dname;
+                       u32                           *dir_dname_len;
+                       struct ceph_mds_reply_lease   **dir_dlease;
+                       struct ceph_mds_reply_info_in *dir_in;
+                       u8                            dir_complete, dir_end;
+               };
+       };
 
        /* encoded blob describing snapshot contexts for certain
           operations (e.g., open) */
index adefa60..43b19dd 100644 (file)
@@ -6,7 +6,9 @@ obj-$(CONFIG_CIFS) += cifs.o
 cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
          link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
          md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
-         readdir.o ioctl.o sess.o export.o cifsacl.o
+         readdir.o ioctl.o sess.o export.o
+
+cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
 
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
index ee68d10..46af99a 100644 (file)
@@ -337,6 +337,15 @@ A partial list of the supported mount options follows:
   wsize                default write size (default 57344)
                maximum wsize currently allowed by CIFS is 57344 (fourteen
                4096 byte pages)
+  actimeo=n    attribute cache timeout in seconds (default 1 second).
+               After this timeout, the cifs client requests fresh attribute
+               information from the server. This option allows to tune the
+               attribute cache timeout to suit the workload needs. Shorter
+               timeouts mean better the cache coherency, but increased number
+               of calls to the server. Longer timeouts mean reduced number
+               of calls to the server at the expense of less stricter cache
+               coherency checks (i.e. incorrect attribute cache for a short
+               period of time).
   rw           mount the network share read-write (note that the
                server may still consider the share read-only)
   ro           mount network share read-only
index e9a393c..7852cd6 100644 (file)
@@ -48,6 +48,7 @@ struct cifs_sb_info {
        struct nls_table *local_nls;
        unsigned int rsize;
        unsigned int wsize;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        atomic_t active;
        uid_t   mnt_uid;
        gid_t   mnt_gid;
index c6ebea0..a437ec3 100644 (file)
@@ -30,8 +30,6 @@
 #include "cifs_debug.h"
 
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
        {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
@@ -774,4 +772,3 @@ int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
 
        return rc;
 }
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
index 6c8096c..c4ae7d0 100644 (file)
@@ -74,11 +74,7 @@ struct cifs_wksid {
        char sidname[SIDNAMELENGTH];
 } __attribute__((packed));
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 extern int match_sid(struct cifs_sid *);
 extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
 
-#endif /*  CONFIG_CIFS_EXPERIMENTAL */
-
 #endif /* _CIFSACL_H */
index 76c8a90..3936aa7 100644 (file)
@@ -463,6 +463,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        seq_printf(s, ",rsize=%d", cifs_sb->rsize);
        seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+       /* convert actimeo and display it in seconds */
+               seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
 
        return 0;
 }
@@ -935,7 +937,6 @@ init_cifs(void)
        GlobalCurrentXid = 0;
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
-       memset(Local_System_Name, 0, 15);
        spin_lock_init(&cifs_tcp_ses_lock);
        spin_lock_init(&cifs_file_list_lock);
        spin_lock_init(&GlobalMid_Lock);
index b577bf0..7136c0c 100644 (file)
 
 #define CIFS_MIN_RCV_POOL 4
 
+/*
+ * default attribute cache timeout (jiffies)
+ */
+#define CIFS_DEF_ACTIMEO (1 * HZ)
+
+/*
+ * max attribute cache timeout (jiffies) - 2^30
+ */
+#define CIFS_MAX_ACTIMEO (1 << 30)
+
 /*
  * MAX_REQ is the maximum number of requests that WE will send
  * on one socket concurrently. It also matches the most common
@@ -746,8 +756,6 @@ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above & list operations */
                                          /* on midQ entries */
-GLOBAL_EXTERN char Local_System_Name[15];
-
 /*
  *  Global counters, updated atomically
  */
index db961dc..e6d1481 100644 (file)
@@ -54,7 +54,8 @@ do {                                                          \
             __func__, curr_xid, (int)rc);                      \
 } while (0)
 extern char *build_path_from_dentry(struct dentry *);
-extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                                       struct cifsTconInfo *tcon);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
                const char *fullpath, const struct dfs_info3_param *ref,
@@ -79,9 +80,7 @@ extern bool is_valid_oplock_break(struct smb_hdr *smb,
                                  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
-#endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
index 2f2632b..67acfb3 100644 (file)
@@ -2478,95 +2478,6 @@ querySymLinkRetry:
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-/* Initialize NT TRANSACT SMB into small smb request buffer.
-   This assumes that all NT TRANSACTS that we init here have
-   total parm and data under about 400 bytes (to fit in small cifs
-   buffer size), which is the case so far, it easily fits. NB:
-       Setup words themselves and ByteCount
-       MaxSetupCount (size of returned setup area) and
-       MaxParameterCount (returned parms size) must be set by caller */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
-                  const int parm_len, struct cifsTconInfo *tcon,
-                  void **ret_buf)
-{
-       int rc;
-       __u32 temp_offset;
-       struct smb_com_ntransact_req *pSMB;
-
-       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
-                               (void **)&pSMB);
-       if (rc)
-               return rc;
-       *ret_buf = (void *)pSMB;
-       pSMB->Reserved = 0;
-       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
-       pSMB->TotalDataCount  = 0;
-       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->DataCount  = pSMB->TotalDataCount;
-       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
-                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
-       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
-       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
-       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
-       pSMB->SubCommand = cpu_to_le16(sub_command);
-       return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  __u32 *pparmlen, __u32 *pdatalen)
-{
-       char *end_of_smb;
-       __u32 data_count, data_offset, parm_count, parm_offset;
-       struct smb_com_ntransact_rsp *pSMBr;
-
-       *pdatalen = 0;
-       *pparmlen = 0;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
-       /* ByteCount was converted from little endian in SendReceive */
-       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
-                       (char *)&pSMBr->ByteCount;
-
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
-       parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
-       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
-       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
-       /* should we also check that parm and data areas do not overlap? */
-       if (*ppparm > end_of_smb) {
-               cFYI(1, "parms start after end of smb");
-               return -EINVAL;
-       } else if (parm_count + *ppparm > end_of_smb) {
-               cFYI(1, "parm end after end of smb");
-               return -EINVAL;
-       } else if (*ppdata > end_of_smb) {
-               cFYI(1, "data starts after end of smb");
-               return -EINVAL;
-       } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
-                       *ppdata, data_count, (data_count + *ppdata),
-                       end_of_smb, pSMBr);
-               return -EINVAL;
-       } else if (parm_count + data_count > pSMBr->ByteCount) {
-               cFYI(1, "parm count and data count larger than SMB");
-               return -EINVAL;
-       }
-       *pdatalen = data_count;
-       *pparmlen = parm_count;
-       return 0;
-}
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -3056,7 +2967,97 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+                  const int parm_len, struct cifsTconInfo *tcon,
+                  void **ret_buf)
+{
+       int rc;
+       __u32 temp_offset;
+       struct smb_com_ntransact_req *pSMB;
+
+       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+                               (void **)&pSMB);
+       if (rc)
+               return rc;
+       *ret_buf = (void *)pSMB;
+       pSMB->Reserved = 0;
+       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+       pSMB->TotalDataCount  = 0;
+       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->DataCount  = pSMB->TotalDataCount;
+       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
+       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+       pSMB->SubCommand = cpu_to_le16(sub_command);
+       return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+                  __u32 *pparmlen, __u32 *pdatalen)
+{
+       char *end_of_smb;
+       __u32 data_count, data_offset, parm_count, parm_offset;
+       struct smb_com_ntransact_rsp *pSMBr;
+
+       *pdatalen = 0;
+       *pparmlen = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+       /* ByteCount was converted from little endian in SendReceive */
+       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+                       (char *)&pSMBr->ByteCount;
+
+       data_offset = le32_to_cpu(pSMBr->DataOffset);
+       data_count = le32_to_cpu(pSMBr->DataCount);
+       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+       parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+       /* should we also check that parm and data areas do not overlap? */
+       if (*ppparm > end_of_smb) {
+               cFYI(1, "parms start after end of smb");
+               return -EINVAL;
+       } else if (parm_count + *ppparm > end_of_smb) {
+               cFYI(1, "parm end after end of smb");
+               return -EINVAL;
+       } else if (*ppdata > end_of_smb) {
+               cFYI(1, "data starts after end of smb");
+               return -EINVAL;
+       } else if (data_count + *ppdata > end_of_smb) {
+               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
+                       *ppdata, data_count, (data_count + *ppdata),
+                       end_of_smb, pSMBr);
+               return -EINVAL;
+       } else if (parm_count + data_count > pSMBr->ByteCount) {
+               cFYI(1, "parm count and data count larger than SMB");
+               return -EINVAL;
+       }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
+       return 0;
+}
+
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3214,7 +3215,7 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 32fa4d9..cc1a860 100644 (file)
@@ -105,6 +105,7 @@ struct smb_vol {
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
        unsigned short int port;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        char *prepath;
        struct sockaddr_storage srcaddr; /* allow binding to a local IP */
        struct nls_table *local_nls;
@@ -806,23 +807,20 @@ cifs_parse_mount_options(char *options, const char *devname,
        short int override_gid = -1;
        bool uid_specified = false;
        bool gid_specified = false;
+       char *nodename = utsname()->nodename;
 
        separator[0] = ',';
        separator[1] = 0;
 
-       if (Local_System_Name[0] != 0)
-               memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
-       else {
-               char *nodename = utsname()->nodename;
-               int n = strnlen(nodename, 15);
-               memset(vol->source_rfc1001_name, 0x20, 15);
-               for (i = 0; i < n; i++) {
-                       /* does not have to be perfect mapping since field is
-                       informational, only used for servers that do not support
-                       port 445 and it can be overridden at mount time */
-                       vol->source_rfc1001_name[i] = toupper(nodename[i]);
-               }
-       }
+       /*
+        * does not have to be perfect mapping since field is
+        * informational, only used for servers that do not support
+        * port 445 and it can be overridden at mount time
+        */
+       memset(vol->source_rfc1001_name, 0x20, 15);
+       for (i = 0; i < strnlen(nodename, 15); i++)
+               vol->source_rfc1001_name[i] = toupper(nodename[i]);
+
        vol->source_rfc1001_name[15] = 0;
        /* null target name indicates to use *SMBSERVR default called name
           if we end up sending RFC1001 session initialize */
@@ -840,6 +838,8 @@ cifs_parse_mount_options(char *options, const char *devname,
        /* default to using server inode numbers where available */
        vol->server_ino = 1;
 
+       vol->actimeo = CIFS_DEF_ACTIMEO;
+
        if (!options)
                return 1;
 
@@ -1214,6 +1214,16 @@ cifs_parse_mount_options(char *options, const char *devname,
                                        printk(KERN_WARNING "CIFS: server net"
                                        "biosname longer than 15 truncated.\n");
                        }
+               } else if (strnicmp(data, "actimeo", 7) == 0) {
+                       if (value && *value) {
+                               vol->actimeo = HZ * simple_strtoul(value,
+                                                                  &value, 0);
+                               if (vol->actimeo > CIFS_MAX_ACTIMEO) {
+                                       cERROR(1, "CIFS: attribute cache"
+                                                       "timeout too large");
+                                       return 1;
+                               }
+                       }
                } else if (strnicmp(data, "credentials", 4) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "version", 3) == 0) {
@@ -2571,6 +2581,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
        cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
                cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
 
+       cifs_sb->actimeo = pvolume_info->actimeo;
+
        if (pvolume_info->noperm)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
        if (pvolume_info->setuids)
@@ -2821,13 +2833,13 @@ remote_path_check:
        /* check if a whole path (including prepath) is not remote */
        if (!rc && cifs_sb->prepathlen && tcon) {
                /* build_path_to_root works only when we have a valid tcon */
-               full_path = cifs_build_path_to_root(cifs_sb);
+               full_path = cifs_build_path_to_root(cifs_sb, tcon);
                if (full_path == NULL) {
                        rc = -ENOMEM;
                        goto mount_fail_check;
                }
                rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
-               if (rc != -EREMOTE) {
+               if (rc != 0 && rc != -EREMOTE) {
                        kfree(full_path);
                        goto mount_fail_check;
                }
index b857ce5..5a28660 100644 (file)
@@ -1108,7 +1108,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
        return total_written;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
 {
@@ -1142,7 +1141,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
        spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
-#endif
 
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
index 28cb6e7..589f3e3 100644 (file)
@@ -686,7 +686,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        cFYI(1, "cifs_sfu_type failed: %d", tmprc);
        }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
@@ -697,7 +697,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        goto cgii_exit;
                }
        }
-#endif
+#endif /* CONFIG_CIFS_ACL */
 
        /* fill in remaining high mode bits e.g. SUID, VTX */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
@@ -728,12 +728,12 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                               struct cifsTconInfo *tcon)
 {
        int pplen = cifs_sb->prepathlen;
        int dfsplen;
        char *full_path = NULL;
-       struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
        /* if no prefix path, simply set path to the root of share to "" */
        if (pplen == 0) {
@@ -875,7 +875,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
        char *full_path;
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-       full_path = cifs_build_path_to_root(cifs_sb);
+       full_path = cifs_build_path_to_root(cifs_sb, tcon);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -1653,6 +1653,7 @@ static bool
 cifs_inode_needs_reval(struct inode *inode)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
        if (cifs_i->clientCanCacheRead)
                return false;
@@ -1663,12 +1664,12 @@ cifs_inode_needs_reval(struct inode *inode)
        if (cifs_i->time == 0)
                return true;
 
-       /* FIXME: the actimeo should be tunable */
-       if (time_after_eq(jiffies, cifs_i->time + HZ))
+       if (!time_in_range(jiffies, cifs_i->time,
+                               cifs_i->time + cifs_sb->actimeo))
                return true;
 
        /* hardlinked files w/ noserverino get "special" treatment */
-       if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
            S_ISREG(inode->i_mode) && inode->i_nlink != 1)
                return true;
 
@@ -2121,7 +2122,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        if (attrs->ia_valid & ATTR_MODE) {
                rc = 0;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        rc = mode_to_cifs_acl(inode, full_path, mode);
                        if (rc) {
@@ -2130,7 +2131,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                                goto cifs_setattr_exit;
                        }
                } else
-#endif
+#endif /* CONFIG_CIFS_ACL */
                if (((mode & S_IWUGO) == 0) &&
                    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
 
index 32d300e..a73eb9f 100644 (file)
@@ -759,18 +759,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
                     ino, fattr.cf_dtype);
 
-       /*
-        * we can not return filldir errors to the caller since they are
-        * "normal" when the stat blocksize is too small - we return remapped
-        * error instead
-        *
-        * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
-        * case already. Why should we be clobbering other errors from it?
-        */
-       if (rc) {
-               cFYI(1, "filldir rc = %d", rc);
-               rc = -EOVERFLOW;
-       }
        dput(tmp_dentry);
        return rc;
 }
index d68c378..c62efcb 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -275,6 +275,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        INIT_LIST_HEAD(&vma->anon_vma_chain);
+
+       err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (err)
+               goto err;
+
        err = insert_vm_struct(mm, vma);
        if (err)
                goto err;
index 6a5edea..94ce3d7 100644 (file)
@@ -910,6 +910,7 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
 #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+#define EXT4_MOUNT_MBLK_IO_SUBMIT      0x4000000 /* multi-block io submits */
 #define EXT4_MOUNT_DELALLOC            0x8000000 /* Delalloc support */
 #define EXT4_MOUNT_DATA_ERR_ABORT      0x10000000 /* Abort on file data write */
 #define EXT4_MOUNT_BLOCK_VALIDITY      0x20000000 /* Block validity checking */
index bdbe699..e659597 100644 (file)
@@ -2125,9 +2125,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
                         */
                        if (unlikely(journal_data && PageChecked(page)))
                                err = __ext4_journalled_writepage(page, len);
-                       else
+                       else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
                                err = ext4_bio_write_page(&io_submit, page,
                                                          len, mpd->wbc);
+                       else
+                               err = block_write_full_page(page,
+                                       noalloc_get_block_write, mpd->wbc);
 
                        if (!err)
                                mpd->pages_written++;
index 92203b8..dc40e75 100644 (file)
@@ -872,7 +872,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
        if (namelen > EXT4_NAME_LEN)
                return NULL;
        if ((namelen <= 2) && (name[0] == '.') &&
-           (name[1] == '.' || name[1] == '0')) {
+           (name[1] == '.' || name[1] == '\0')) {
                /*
                 * "." or ".." will only be in the first block
                 * NFS may look up ".."; "." should be handled by the VFS
index e32195d..fb15c9c 100644 (file)
@@ -1026,6 +1026,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
            !(def_mount_opts & EXT4_DEFM_NODELALLOC))
                seq_puts(seq, ",nodelalloc");
 
+       if (test_opt(sb, MBLK_IO_SUBMIT))
+               seq_puts(seq, ",mblk_io_submit");
        if (sbi->s_stripe)
                seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
        /*
@@ -1239,8 +1241,8 @@ enum {
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
        Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
-       Opt_stripe, Opt_delalloc, Opt_nodelalloc,
-       Opt_block_validity, Opt_noblock_validity,
+       Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
+       Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
        Opt_inode_readahead_blks, Opt_journal_ioprio,
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard,
@@ -1304,6 +1306,8 @@ static const match_table_t tokens = {
        {Opt_resize, "resize"},
        {Opt_delalloc, "delalloc"},
        {Opt_nodelalloc, "nodelalloc"},
+       {Opt_mblk_io_submit, "mblk_io_submit"},
+       {Opt_nomblk_io_submit, "nomblk_io_submit"},
        {Opt_block_validity, "block_validity"},
        {Opt_noblock_validity, "noblock_validity"},
        {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
@@ -1725,6 +1729,12 @@ set_qf_format:
                case Opt_nodelalloc:
                        clear_opt(sbi->s_mount_opt, DELALLOC);
                        break;
+               case Opt_mblk_io_submit:
+                       set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
+               case Opt_nomblk_io_submit:
+                       clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
                case Opt_stripe:
                        if (match_int(&args[0], &option))
                                return 0;
index 9242d29..8b984a2 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/compat.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -1627,6 +1628,58 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        return 0;
 }
 
+/*
+ * CUSE servers compiled on 32bit broke on 64bit kernels because the
+ * ABI was defined to be 'struct iovec' which is different on 32bit
+ * and 64bit.  Fortunately we can determine which structure the server
+ * used from the size of the reply.
+ */
+static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+                                size_t transferred, unsigned count,
+                                bool is_compat)
+{
+#ifdef CONFIG_COMPAT
+       if (count * sizeof(struct compat_iovec) == transferred) {
+               struct compat_iovec *ciov = src;
+               unsigned i;
+
+               /*
+                * With this interface a 32bit server cannot support
+                * non-compat (i.e. ones coming from 64bit apps) ioctl
+                * requests
+                */
+               if (!is_compat)
+                       return -EINVAL;
+
+               for (i = 0; i < count; i++) {
+                       dst[i].iov_base = compat_ptr(ciov[i].iov_base);
+                       dst[i].iov_len = ciov[i].iov_len;
+               }
+               return 0;
+       }
+#endif
+
+       if (count * sizeof(struct iovec) != transferred)
+               return -EIO;
+
+       memcpy(dst, src, transferred);
+       return 0;
+}
+
+/* Make sure iov_length() won't overflow */
+static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
+{
+       size_t n;
+       u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+       for (n = 0; n < count; n++) {
+               if (iov->iov_len > (size_t) max)
+                       return -ENOMEM;
+               max -= iov->iov_len;
+       }
+       return 0;
+}
+
 /*
  * For ioctls, there is no generic way to determine how much memory
  * needs to be read and/or written.  Furthermore, ioctls are allowed
@@ -1808,18 +1861,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
                        goto out;
 
-               err = -EIO;
-               if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred)
-                       goto out;
-
-               /* okay, copy in iovs and retry */
                vaddr = kmap_atomic(pages[0], KM_USER0);
-               memcpy(page_address(iov_page), vaddr, transferred);
+               err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr,
+                                           transferred, in_iovs + out_iovs,
+                                           (flags & FUSE_IOCTL_COMPAT) != 0);
                kunmap_atomic(vaddr, KM_USER0);
+               if (err)
+                       goto out;
 
                in_iov = page_address(iov_page);
                out_iov = in_iov + in_iovs;
 
+               err = fuse_verify_ioctl_iov(in_iov, in_iovs);
+               if (err)
+                       goto out;
+
+               err = fuse_verify_ioctl_iov(out_iov, out_iovs);
+               if (err)
+                       goto out;
+
                goto retry;
        }
 
index 5362af9..4ff7ca5 100644 (file)
@@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,
        if (!(open_flag & O_CREAT))
                mode = 0;
 
+       /* Must never be set by userspace */
+       open_flag &= ~FMODE_NONOTIFY;
+
        /*
         * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
         * check for O_DSYNC if the need any syncing at all we enforce it's
index f0a384e..996dd89 100644 (file)
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-static int nfs_readdir_clear_array(struct page*, gfp_t);
+static void nfs_readdir_clear_array(struct page*);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
-const struct address_space_operations nfs_dir_addr_space_ops = {
-       .releasepage = nfs_readdir_clear_array,
+const struct address_space_operations nfs_dir_aops = {
+       .freepage = nfs_readdir_clear_array,
 };
 
 #ifdef CONFIG_NFS_V3
@@ -178,6 +178,7 @@ typedef struct {
        struct page     *page;
        unsigned long   page_index;
        u64             *dir_cookie;
+       u64             last_cookie;
        loff_t          current_index;
        decode_dirent_t decode;
 
@@ -213,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
 static
-int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+void nfs_readdir_clear_array(struct page *page)
 {
-       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array *array;
        int i;
 
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       array = kmap_atomic(page, KM_USER0);
        for (i = 0; i < array->size; i++)
                kfree(array->array[i].string.name);
-       nfs_readdir_release_array(page);
-       return 0;
+       kunmap_atomic(array, KM_USER0);
 }
 
 /*
@@ -272,7 +271,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
                goto out;
        array->last_cookie = entry->cookie;
        array->size++;
-       if (entry->eof == 1)
+       if (entry->eof != 0)
                array->eof_index = array->size;
 out:
        nfs_readdir_release_array(page);
@@ -312,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
        for (i = 0; i < array->size; i++) {
                if (array->array[i].cookie == *desc->dir_cookie) {
                        desc->cache_entry_index = i;
-                       status = 0;
-                       goto out;
+                       return 0;
                }
        }
-       if (i == array->eof_index) {
-               desc->eof = 1;
+       if (array->eof_index >= 0) {
                status = -EBADCOOKIE;
+               if (*desc->dir_cookie == array->last_cookie)
+                       desc->eof = 1;
        }
-out:
        return status;
 }
 
@@ -328,10 +326,7 @@ static
 int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 {
        struct nfs_cache_array *array;
-       int status = -EBADCOOKIE;
-
-       if (desc->dir_cookie == NULL)
-               goto out;
+       int status;
 
        array = nfs_readdir_get_array(desc->page);
        if (IS_ERR(array)) {
@@ -344,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
        else
                status = nfs_readdir_search_for_cookie(array, desc);
 
+       if (status == -EAGAIN) {
+               desc->last_cookie = array->last_cookie;
+               desc->page_index++;
+       }
        nfs_readdir_release_array(desc->page);
 out:
        return status;
@@ -490,7 +489,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
 
                count++;
 
-               if (desc->plus == 1)
+               if (desc->plus != 0)
                        nfs_prime_dcache(desc->file->f_path.dentry, entry);
 
                status = nfs_readdir_add_to_array(entry, page);
@@ -498,7 +497,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
-       if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
+       if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
                        array->eof_index = array->size;
@@ -563,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
        unsigned int array_size = ARRAY_SIZE(pages);
 
        entry.prev_cookie = 0;
-       entry.cookie = *desc->dir_cookie;
+       entry.cookie = desc->last_cookie;
        entry.eof = 0;
        entry.fh = nfs_alloc_fhandle();
        entry.fattr = nfs_alloc_fattr();
@@ -636,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
+       if (!desc->page->mapping)
+               nfs_readdir_clear_array(desc->page);
        page_cache_release(desc->page);
        desc->page = NULL;
 }
@@ -660,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
                return PTR_ERR(desc->page);
 
        res = nfs_readdir_search_array(desc);
-       if (res == 0)
-               return 0;
-       cache_page_release(desc);
+       if (res != 0)
+               cache_page_release(desc);
        return res;
 }
 
@@ -672,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
        int res;
 
-       if (desc->page_index == 0)
+       if (desc->page_index == 0) {
                desc->current_index = 0;
-       while (1) {
-               res = find_cache_page(desc);
-               if (res != -EAGAIN)
-                       break;
-               desc->page_index++;
+               desc->last_cookie = 0;
        }
+       do {
+               res = find_cache_page(desc);
+       } while (res == -EAGAIN);
        return res;
 }
 
-static inline unsigned int dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -717,13 +711,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                        break;
                }
                file->f_pos++;
-               desc->cache_entry_index = i;
                if (i < (array->size-1))
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
                        *desc->dir_cookie = array->last_cookie;
        }
-       if (i == array->eof_index)
+       if (array->eof_index >= 0)
                desc->eof = 1;
 
        nfs_readdir_release_array(desc->page);
@@ -764,6 +757,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        }
 
        desc->page_index = 0;
+       desc->last_cookie = *desc->dir_cookie;
        desc->page = page;
 
        status = nfs_readdir_xdr_to_array(desc, page, inode);
@@ -791,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       int res = -ENOMEM;
+       int res;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -816,7 +810,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (res < 0)
                goto out;
 
-       while (desc->eof != 1) {
+       do {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
@@ -844,7 +838,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                res = nfs_do_filldir(desc, dirent, filldir);
                if (res < 0)
                        break;
-       }
+       } while (!desc->eof);
 out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
index 60677f9..7bf029e 100644 (file)
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
+       unsigned int saved_type = fl->fl_type;
 
        /* Try local locking first */
        posix_test_lock(filp, fl);
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
                /* found a conflict */
                goto out;
        }
+       fl->fl_type = saved_type;
 
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
index 314f571..e67e31c 100644 (file)
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
+                       inode->i_data.a_ops = &nfs_dir_aops;
                        if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
index eceafe7..4f981f1 100644 (file)
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
 
 static struct rpc_version mnt_version1 = {
        .number         = 1,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt_procedures),
        .procs          = mnt_procedures,
 };
 
 static struct rpc_version mnt_version3 = {
        .number         = 3,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt3_procedures),
        .procs          = mnt3_procedures,
 };
 
index 6a653ff..4435e5e 100644 (file)
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
        ret = nfs_revalidate_inode(server, inode);
        if (ret < 0)
                return ret;
+       if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        ret = nfs4_read_cached_acl(inode, buf, buflen);
        if (ret != -ENOENT)
                return ret;
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
+       /*
+        * Acl update can result in inode attribute update.
+        * so mark the attribute cache invalid.
+        */
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
+       spin_unlock(&inode->i_lock);
        nfs_access_zap_cache(inode);
        nfs_zap_acl_cache(inode);
        return ret;
index 137b549..b68536c 100644 (file)
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 {
        if (!nfs_lock_request_dontget(req))
                return 0;
-       if (req->wb_page != NULL)
+       if (test_bit(PG_MAPPED, &req->wb_flags))
                radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
        return 1;
 }
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
  */
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-       if (req->wb_page != NULL) {
+       if (test_bit(PG_MAPPED, &req->wb_flags)) {
                struct inode *inode = req->wb_context->path.dentry->d_inode;
                struct nfs_inode *nfsi = NFS_I(inode);
 
index e4b62c6..aedcaa7 100644 (file)
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req)
                        (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 3c04504..4100630 100644 (file)
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->flags |= NFS_MOUNT_VER3;
                        mnt->version = 3;
                        break;
-#ifdef CONFIG_NFS_V4
                case Opt_v4:
                        mnt->flags &= ~NFS_MOUNT_VER3;
                        mnt->version = 4;
                        break;
-#endif
                case Opt_udp:
                        mnt->flags &= ~NFS_MOUNT_TCP;
                        mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw,
                                mnt->flags |= NFS_MOUNT_VER3;
                                mnt->version = 3;
                                break;
-#ifdef CONFIG_NFS_V4
                        case NFS4_VERSION:
                                mnt->flags &= ~NFS_MOUNT_VER3;
                                mnt->version = 4;
                                break;
-#endif
                        default:
                                goto out_invalid_value;
                        }
index 4c14c17..10d648e 100644 (file)
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                if (nfs_have_delegation(inode, FMODE_WRITE))
                        nfsi->change_attr++;
        }
+       set_bit(PG_MAPPED, &req->wb_flags);
        SetPagePrivate(req->wb_page);
        set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        spin_lock(&inode->i_lock);
        set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
+       clear_bit(PG_MAPPED, &req->wb_flags);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
        if (!nfsi->npages) {
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                iput(inode);
        } else
                spin_unlock(&inode->i_lock);
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 2a533a0..7e84a85 100644 (file)
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
        err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
                        &fhp->fh_post_attr);
        fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
-       if (err)
+       if (err) {
                fhp->fh_post_saved = 0;
-       else
+               /* Grab the ctime anyway - set_change_info might use it */
+               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+       } else
                fhp->fh_post_saved = 1;
 }
 
index 4d476ff..60fce3d 100644 (file)
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-       cinfo->atomic = 1;
+       BUG_ON(!fhp->fh_pre_saved);
+       cinfo->atomic = fhp->fh_post_saved;
        cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
-       if (cinfo->change_supported) {
-               cinfo->before_change = fhp->fh_pre_change;
-               cinfo->after_change = fhp->fh_post_change;
-       } else {
-               cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
-               cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
-               cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
-               cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
-       }
+
+       cinfo->before_change = fhp->fh_pre_change;
+       cinfo->after_change = fhp->fh_post_change;
+       cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+       cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+       cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+       cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
index 33ad25d..caf9a6a 100644 (file)
@@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
 int nilfs_init_gcinode(struct inode *inode)
 {
        struct nilfs_inode_info *ii = NILFS_I(inode);
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
        inode->i_mode = S_IFREG;
        mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
@@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)
        ii->i_flags = 0;
        nilfs_bmap_init_gc(ii->i_bmap);
 
-       /*
-        * Add the inode to GC inode list. Garbage Collection
-        * is serialized and no two processes manipulate the
-        * list simultaneously.
-        */
-       igrab(inode);
-       list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
-
        return 0;
 }
 
index e00d945..b185e93 100644 (file)
@@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                                   struct nilfs_argv *argv, void *buf)
 {
        size_t nmembs = argv->v_nmembs;
+       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
        struct inode *inode;
        struct nilfs_vdesc *vdesc;
        struct buffer_head *bh, *n;
@@ -353,6 +354,17 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                        ret = PTR_ERR(inode);
                        goto failed;
                }
+               if (list_empty(&NILFS_I(inode)->i_dirty)) {
+                       /*
+                        * Add the inode to GC inode list. Garbage Collection
+                        * is serialized and no two processes manipulate the
+                        * list simultaneously.
+                        */
+                       igrab(inode);
+                       list_add(&NILFS_I(inode)->i_dirty,
+                                &nilfs->ns_gc_inodes);
+               }
+
                do {
                        ret = nilfs_ioctl_move_inode_block(inode, vdesc,
                                                           &buffers);
index b04f88e..f35794b 100644 (file)
@@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       wait_event(group->fanotify_data.access_waitq, event->response);
+       wait_event(group->fanotify_data.access_waitq, event->response ||
+                               atomic_read(&group->fanotify_data.bypass_perm));
+
+       if (!event->response) /* bypass_perm set */
+               return 0;
 
        /* userspace responded, convert to something usable */
        spin_lock(&event->lock);
index 0632248..8b61220 100644 (file)
@@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
        return client_fd;
 }
 
-static ssize_t fill_event_metadata(struct fsnotify_group *group,
+static int fill_event_metadata(struct fsnotify_group *group,
                                   struct fanotify_event_metadata *metadata,
                                   struct fsnotify_event *event)
 {
+       int ret = 0;
+
        pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
                 group, metadata, event);
 
        metadata->event_len = FAN_EVENT_METADATA_LEN;
+       metadata->metadata_len = FAN_EVENT_METADATA_LEN;
        metadata->vers = FANOTIFY_METADATA_VERSION;
        metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;
        metadata->pid = pid_vnr(event->tgid);
-       metadata->fd = create_fd(group, event);
+       if (unlikely(event->mask & FAN_Q_OVERFLOW))
+               metadata->fd = FAN_NOFD;
+       else {
+               metadata->fd = create_fd(group, event);
+               if (metadata->fd < 0)
+                       ret = metadata->fd;
+       }
 
-       return metadata->fd;
+       return ret;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       if (group->fanotify_data.bypass_perm) {
+       if (atomic_read(&group->fanotify_data.bypass_perm)) {
                mutex_unlock(&group->fanotify_data.access_mutex);
                kmem_cache_free(fanotify_response_event_cache, re);
                event->response = FAN_ALLOW;
@@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       fd = fill_event_metadata(group, &fanotify_event_metadata, event);
-       if (fd < 0)
-               return fd;
+       ret = fill_event_metadata(group, &fanotify_event_metadata, event);
+       if (ret < 0)
+               goto out;
 
+       fd = fanotify_event_metadata.fd;
        ret = prepare_for_access_response(group, event, fd);
        if (ret)
                goto out_close_fd;
 
        ret = -EFAULT;
-       if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN))
+       if (copy_to_user(buf, &fanotify_event_metadata,
+                        fanotify_event_metadata.event_len))
                goto out_kill_access_response;
 
-       return FAN_EVENT_METADATA_LEN;
+       return fanotify_event_metadata.event_len;
 
 out_kill_access_response:
        remove_access_response(group, event, fd);
 out_close_fd:
-       sys_close(fd);
+       if (fd != FAN_NOFD)
+               sys_close(fd);
+out:
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (event->mask & FAN_ALL_PERM_EVENTS) {
+               event->response = FAN_DENY;
+               wake_up(&group->fanotify_data.access_waitq);
+       }
+#endif
        return ret;
 }
 
@@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       group->fanotify_data.bypass_perm = true;
+       atomic_inc(&group->fanotify_data.bypass_perm);
 
        list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
                pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
@@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~mnt->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
-
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
@@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~inode->i_fsnotify_mask)
                fsnotify_recalc_inode_mask(inode);
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 /* fanotify syscalls */
@@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
        group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
-       if (IS_ERR(group))
+       if (IS_ERR(group)) {
+               free_uid(user);
                return PTR_ERR(group);
+       }
 
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
@@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
+       atomic_set(&group->fanotify_data.bypass_perm, 0);
 #endif
        switch (flags & FAN_ALL_CLASS_BITS) {
        case FAN_CLASS_NOTIF:
@@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
-       case FAN_MARK_ADD:
+       case FAN_MARK_ADD:              /* fallthrough */
        case FAN_MARK_REMOVE:
+               if (!mask)
+                       return -EINVAL;
        case FAN_MARK_FLUSH:
                break;
        default:
index 444c305..4cd5d5d 100644 (file)
@@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (ret >= 0)
                return ret;
 
+       fsnotify_put_group(group);
        atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
index d2af0a8..77a5989 100644 (file)
@@ -297,6 +297,7 @@ xfs_rename(
         * it and some incremental backup programs won't work without it.
         */
        xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE);
 
        /*
         * Adjust the link count on src_dp.  This is necessary when
index 551793c..0e98e67 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ACPI_VIDEO_H
 #define __ACPI_VIDEO_H
 
+#include <linux/errno.h> /* for ENODEV */
+
+struct acpi_device;
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
@@ -26,4 +30,3 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type,
 #endif
 
 #endif
-
index 050a7bc..67c91b4 100644 (file)
@@ -219,7 +219,7 @@ static inline int acpi_video_display_switch_support(void)
 
 extern int acpi_blacklisted(void);
 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
-extern int acpi_osi_setup(char *str);
+extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
 int acpi_get_pxm(acpi_handle handle);
index a8e4e83..475f8c4 100644 (file)
@@ -427,8 +427,10 @@ extern rwlock_t vcc_sklist_lock;
 
 #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
 
-struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
-    int number,unsigned long *flags); /* number == -1: pick first available */
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops,
+                                int number, /* -1 == pick first available */
+                                unsigned long *flags);
 struct atm_dev *atm_dev_lookup(int number);
 void atm_dev_deregister(struct atm_dev *dev);
 
index 0f01214..6c6133f 100644 (file)
                                 FAN_ALL_PERM_EVENTS |\
                                 FAN_Q_OVERFLOW)
 
-#define FANOTIFY_METADATA_VERSION      2
+#define FANOTIFY_METADATA_VERSION      3
 
 struct fanotify_event_metadata {
        __u32 event_len;
-       __u32 vers;
+       __u8 vers;
+       __u8 reserved;
+       __u16 metadata_len;
        __aligned_u64 mask;
        __s32 fd;
        __s32 pid;
@@ -96,11 +98,13 @@ struct fanotify_event_metadata {
 struct fanotify_response {
        __s32 fd;
        __u32 response;
-} __attribute__ ((packed));
+};
 
 /* Legit userspace responses to a _PERM event */
 #define FAN_ALLOW      0x01
 #define FAN_DENY       0x02
+/* No fd set in event */
+#define FAN_NOFD       -1
 
 /* Helper functions to deal with fanotify_event_metadata buffers */
 #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
index c9e06cc..090f0ea 100644 (file)
@@ -602,6 +602,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        void (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, gfp_t);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*get_xip_mem)(struct address_space *, pgoff_t, int,
index 5c185fa..b10bcde 100644 (file)
@@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)
        if (S_ISDIR(inode->i_mode))
                mask |= FS_ISDIR;
 
-       /* FMODE_NONOTIFY must never be set from user */
-       file->f_mode &= ~FMODE_NONOTIFY;
-
        fsnotify_parent(path, NULL, mask);
        fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 }
index 0a68f92..7380763 100644 (file)
@@ -166,7 +166,7 @@ struct fsnotify_group {
                        struct mutex access_mutex;
                        struct list_head access_list;
                        wait_queue_head_t access_waitq;
-                       bool bypass_perm; /* protected by access_mutex */
+                       atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                        unsigned int max_marks;
index a8af21d..9777668 100644 (file)
@@ -104,8 +104,10 @@ struct input_keymap_entry {
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
 
-#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
+#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
+#define EVIOCGKEYCODE_V2       _IOR('E', 0x04, struct input_keymap_entry)
+#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+#define EVIOCSKEYCODE_V2       _IOW('E', 0x04, struct input_keymap_entry)
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
index d377ea8..e9bb22c 100644 (file)
@@ -112,7 +112,6 @@ struct resource_list {
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
-extern int resource_alloc_from_bottom;
 
 extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
 extern int request_resource(struct resource *root, struct resource *new);
@@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,
 extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
 extern int insert_resource(struct resource *parent, struct resource *new);
 extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
+extern void arch_remove_reservations(struct resource *avail);
 extern int allocate_resource(struct resource *root, struct resource *new,
                             resource_size_t size, resource_size_t min,
                             resource_size_t max, resource_size_t align,
index 5c51f36..add8a1b 100644 (file)
@@ -29,7 +29,7 @@ struct wm8994_ldo_pdata {
 #define WM8994_CONFIGURE_GPIO 0x8000
 
 #define WM8994_DRC_REGS 5
-#define WM8994_EQ_REGS  19
+#define WM8994_EQ_REGS  20
 
 /**
  * DRC configurations are specified with a label and a set of register
index c66fdb7..29d504d 100644 (file)
@@ -401,6 +401,7 @@ extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
+extern const struct address_space_operations nfs_dir_aops;
 
 static inline struct nfs_open_context *nfs_file_open_context(struct file *filp)
 {
index f8b60e7..d55cee7 100644 (file)
@@ -29,6 +29,7 @@
  */
 enum {
        PG_BUSY = 0,
+       PG_MAPPED,
        PG_CLEAN,
        PG_NEED_COMMIT,
        PG_NEED_RESCHED,
index 3ec2358..d19f1cc 100644 (file)
@@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)
 
 static inline bool pm_runtime_suspended(struct device *dev)
 {
-       return dev->power.runtime_status == RPM_SUSPENDED;
+       return dev->power.runtime_status == RPM_SUSPENDED
+               && !dev->power.disable_depth;
 }
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
index ebb0c80..12b2b18 100644 (file)
@@ -230,6 +230,7 @@ enum
        LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */
        LINUX_MIB_TCPDEFERACCEPTDROP,
        LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
+       LINUX_MIB_TCPTIMEWAITOVERFLOW,          /* TCPTimeWaitOverflow */
        __LINUX_MIB_MAX
 };
 
index 942e387..eba52a1 100644 (file)
@@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
        return 0;
 }
 
-extern char * nvram_get(const char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 /* Get the device MAC address */
 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
 {
-#ifdef CONFIG_BCM47XX
-       char *res = nvram_get("et0macaddr");
-       if (res)
-               memcpy(macaddr, res, 6);
-#endif
+       char buf[20];
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
+               return;
+       nvram_parse_macaddr(buf, macaddr);
 }
+#else
+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+{
+}
+#endif
 
 extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
                                          struct pci_dev *pdev);
index 2fb46bc..ed5cdeb 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef _LINUX_VIDEO_OUTPUT_H
 #define _LINUX_VIDEO_OUTPUT_H
 #include <linux/device.h>
+#include <linux/err.h>
 struct output_device;
 struct output_properties {
        int (*set_state)(struct output_device *);
@@ -34,9 +35,23 @@ struct output_device {
        struct device dev;
 };
 #define to_output_device(obj) container_of(obj, struct output_device, dev)
+#if    defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
 struct output_device *video_output_register(const char *name,
        struct device *dev,
        void *devdata,
        struct output_properties *op);
 void video_output_unregister(struct output_device *dev);
+#else
+static struct output_device *video_output_register(const char *name,
+        struct device *dev,
+        void *devdata,
+        struct output_properties *op)
+{
+       return ERR_PTR(-ENODEV);
+}
+static void video_output_unregister(struct output_device *dev)
+{
+       return;
+}
+#endif
 #endif
index 6648036..b16f307 100644 (file)
@@ -51,6 +51,8 @@ struct v4l2_device {
                        unsigned int notification, void *arg);
        /* The control handler. May be NULL. */
        struct v4l2_ctrl_handler *ctrl_handler;
+       /* BKL replacement mutex. Temporary solution only. */
+       struct mutex ioctl_lock;
 };
 
 /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
index a6338d0..659d968 100644 (file)
@@ -1155,6 +1155,8 @@ extern void sk_common_release(struct sock *sk);
 /* Initialise core socket variables */
 extern void sock_init_data(struct socket *sock, struct sock *sk);
 
+extern void sk_filter_release_rcu(struct rcu_head *rcu);
+
 /**
  *     sk_filter_release - release a socket filter
  *     @fp: filter to remove
@@ -1165,7 +1167,7 @@ extern void sock_init_data(struct socket *sock, struct sock *sk);
 static inline void sk_filter_release(struct sk_filter *fp)
 {
        if (atomic_dec_and_test(&fp->refcnt))
-               kfree(fp);
+               call_rcu_bh(&fp->rcu, sk_filter_release_rcu);
 }
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
index e8cbf43..75271b9 100644 (file)
@@ -24,8 +24,15 @@ typedef unsigned int RING_IDX;
  * A ring contains as many entries as will fit, rounded down to the nearest
  * power of two (so we can mask with (size-1) to loop around).
  */
-#define __RING_SIZE(_s, _sz) \
-    (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+#define __CONST_RING_SIZE(_s, _sz)                             \
+       (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) /   \
+               sizeof(((struct _s##_sring *)0)->ring[0])))
+
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz)                                           \
+       (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
 
 /*
  * Macros to make the correct C datatypes for a new kind of ring.
index baf667b..8c7e483 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "power.h"
 
-#define HIBERNATE_SIG  "LINHIB0001"
+#define HIBERNATE_SIG  "S1SUSPEND"
 
 /*
  *     The swap map is a data structure used for keeping track of each page
index 1b2ea31..c36c3b9 100644 (file)
@@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_all_swap_pages(data->swap);
        if (data->frozen)
                thaw_processes();
-       pm_notifier_call_chain(data->mode == O_WRONLY ?
+       pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
 
index 9fad33e..798e2fa 100644 (file)
@@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);
 
 static DEFINE_RWLOCK(resource_lock);
 
-/*
- * By default, we allocate free space bottom-up.  The architecture can request
- * top-down by clearing this flag.  The user can override the architecture's
- * choice with the "resource_alloc_from_bottom" kernel boot option, but that
- * should only be a debugging tool.
- */
-int resource_alloc_from_bottom = 1;
-
-static __init int setup_alloc_from_bottom(char *s)
-{
-       printk(KERN_INFO
-              "resource: allocating from bottom-up; please report a bug\n");
-       resource_alloc_from_bottom = 1;
-       return 0;
-}
-early_param("resource_alloc_from_bottom", setup_alloc_from_bottom);
-
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct resource *p = v;
@@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)
        return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
 }
 
+void __weak arch_remove_reservations(struct resource *avail)
+{
+}
+
 static resource_size_t simple_align_resource(void *data,
                                             const struct resource *avail,
                                             resource_size_t size,
@@ -396,75 +383,8 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
        return res1->start <= res2->start && res1->end >= res2->end;
 }
 
-/*
- * Find the resource before "child" in the sibling list of "root" children.
- */
-static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
-{
-       struct resource *this;
-
-       for (this = root->child; this; this = this->sibling)
-               if (this->sibling == child)
-                       return this;
-
-       return NULL;
-}
-
 /*
  * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the end of the root resource first.
- */
-static int find_resource_from_top(struct resource *root, struct resource *new,
-                                 resource_size_t size, resource_size_t min,
-                                 resource_size_t max, resource_size_t align,
-                                 resource_size_t (*alignf)(void *,
-                                                  const struct resource *,
-                                                  resource_size_t,
-                                                  resource_size_t),
-                                 void *alignf_data)
-{
-       struct resource *this;
-       struct resource tmp, avail, alloc;
-
-       tmp.start = root->end;
-       tmp.end = root->end;
-
-       this = find_sibling_prev(root, NULL);
-       for (;;) {
-               if (this) {
-                       if (this->end < root->end)
-                               tmp.start = this->end + 1;
-               } else
-                       tmp.start = root->start;
-
-               resource_clip(&tmp, min, max);
-
-               /* Check for overflow after ALIGN() */
-               avail = *new;
-               avail.start = ALIGN(tmp.start, align);
-               avail.end = tmp.end;
-               if (avail.start >= tmp.start) {
-                       alloc.start = alignf(alignf_data, &avail, size, align);
-                       alloc.end = alloc.start + size - 1;
-                       if (resource_contains(&avail, &alloc)) {
-                               new->start = alloc.start;
-                               new->end = alloc.end;
-                               return 0;
-                       }
-               }
-
-               if (!this || this->start == root->start)
-                       break;
-
-               tmp.end = this->start - 1;
-               this = find_sibling_prev(root, this);
-       }
-       return -EBUSY;
-}
-
-/*
- * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the beginning of the root resource first.
  */
 static int find_resource(struct resource *root, struct resource *new,
                         resource_size_t size, resource_size_t min,
@@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,
        struct resource *this = root->child;
        struct resource tmp = *new, avail, alloc;
 
+       tmp.flags = new->flags;
        tmp.start = root->start;
        /*
-        * Skip past an allocated resource that starts at 0, since the
-        * assignment of this->start - 1 to tmp->end below would cause an
-        * underflow.
+        * Skip past an allocated resource that starts at 0, since the assignment
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
                tmp.start = this->end + 1;
                this = this->sibling;
        }
-       for (;;) {
+       for(;;) {
                if (this)
                        tmp.end = this->start - 1;
                else
                        tmp.end = root->end;
 
                resource_clip(&tmp, min, max);
+               arch_remove_reservations(&tmp);
 
                /* Check for overflow after ALIGN() */
                avail = *new;
@@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,
                                return 0;
                        }
                }
-
                if (!this)
                        break;
-
                tmp.start = this->end + 1;
                this = this->sibling;
        }
@@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,
                alignf = simple_align_resource;
 
        write_lock(&resource_lock);
-       if (resource_alloc_from_bottom)
-               err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
-       else
-               err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data);
+       err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
        if (err >= 0 && __request_resource(root, new))
                err = -EBUSY;
        write_unlock(&resource_lock);
index 90db1bd..e785b0f 100644 (file)
@@ -661,7 +661,7 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
 {
        struct worker *worker = kthread_data(task);
 
-       if (likely(!(worker->flags & WORKER_NOT_RUNNING)))
+       if (!(worker->flags & WORKER_NOT_RUNNING))
                atomic_inc(get_gcwq_nr_running(cpu));
 }
 
@@ -687,7 +687,7 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task,
        struct global_cwq *gcwq = get_gcwq(cpu);
        atomic_t *nr_running = get_gcwq_nr_running(cpu);
 
-       if (unlikely(worker->flags & WORKER_NOT_RUNNING))
+       if (worker->flags & WORKER_NOT_RUNNING)
                return NULL;
 
        /* this can only happen on the local cpu */
@@ -3692,7 +3692,8 @@ static int __init init_workqueues(void)
        system_nrt_wq = alloc_workqueue("events_nrt", WQ_NON_REENTRANT, 0);
        system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,
                                            WQ_UNBOUND_MAX_ACTIVE);
-       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq);
+       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
+              !system_unbound_wq);
        return 0;
 }
 early_initcall(init_workqueues);
index ea89840..6b9aee2 100644 (file)
@@ -143,13 +143,18 @@ void __remove_from_page_cache(struct page *page)
 void remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
+       void (*freepage)(struct page *);
 
        BUG_ON(!PageLocked(page));
 
+       freepage = mapping->a_ops->freepage;
        spin_lock_irq(&mapping->tree_lock);
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (freepage)
+               freepage(page);
 }
 EXPORT_SYMBOL(remove_from_page_cache);
 
index b179abb..50a4aa0 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2462,6 +2462,7 @@ int install_special_mapping(struct mm_struct *mm,
                            unsigned long addr, unsigned long len,
                            unsigned long vm_flags, struct page **pages)
 {
+       int ret;
        struct vm_area_struct *vma;
 
        vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
@@ -2479,16 +2480,23 @@ int install_special_mapping(struct mm_struct *mm,
        vma->vm_ops = &special_mapping_vmops;
        vma->vm_private_data = pages;
 
-       if (unlikely(insert_vm_struct(mm, vma))) {
-               kmem_cache_free(vm_area_cachep, vma);
-               return -ENOMEM;
-       }
+       ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (ret)
+               goto out;
+
+       ret = insert_vm_struct(mm, vma);
+       if (ret)
+               goto out;
 
        mm->total_vm += len >> PAGE_SHIFT;
 
        perf_event_mmap(vma);
 
        return 0;
+
+out:
+       kmem_cache_free(vm_area_cachep, vma);
+       return ret;
 }
 
 static DEFINE_MUTEX(mm_all_locks_mutex);
index ba887bf..3c2d5dd 100644 (file)
@@ -390,6 +390,10 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (mapping->a_ops->freepage)
+               mapping->a_ops->freepage(page);
+
        page_cache_release(page);       /* pagecache ref */
        return 1;
 failed:
index d31d7ce..9ca587c 100644 (file)
@@ -494,9 +494,16 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
                spin_unlock_irq(&mapping->tree_lock);
                swapcache_free(swap, page);
        } else {
+               void (*freepage)(struct page *);
+
+               freepage = mapping->a_ops->freepage;
+
                __remove_from_page_cache(page);
                spin_unlock_irq(&mapping->tree_lock);
                mem_cgroup_uncharge_cache_page(page);
+
+               if (freepage != NULL)
+                       freepage(page);
        }
 
        return 1;
index 799c631..f7fa67c 100644 (file)
@@ -143,12 +143,13 @@ static struct class atm_class = {
        .dev_uevent             = atm_uevent,
 };
 
-int atm_register_sysfs(struct atm_dev *adev)
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent)
 {
        struct device *cdev = &adev->class_dev;
        int i, j, err;
 
        cdev->class = &atm_class;
+       cdev->parent = parent;
        dev_set_drvdata(cdev, adev);
 
        dev_set_name(cdev, "%s%d", adev->type, adev->number);
index d29e582..23f45ce 100644 (file)
@@ -74,8 +74,9 @@ struct atm_dev *atm_dev_lookup(int number)
 }
 EXPORT_SYMBOL(atm_dev_lookup);
 
-struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
-                                int number, unsigned long *flags)
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops, int number,
+                                unsigned long *flags)
 {
        struct atm_dev *dev, *inuse;
 
@@ -115,7 +116,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
                goto out_fail;
        }
 
-       if (atm_register_sysfs(dev) < 0) {
+       if (atm_register_sysfs(dev, parent) < 0) {
                pr_err("atm_register_sysfs failed for dev %s\n", type);
                atm_proc_dev_deregister(dev);
                goto out_fail;
index 126fb18..521431e 100644 (file)
@@ -42,6 +42,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev)
 
 #endif /* CONFIG_PROC_FS */
 
-int atm_register_sysfs(struct atm_dev *adev);
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent);
 void atm_unregister_sysfs(struct atm_dev *adev);
 #endif
index d0927d1..66b9e5c 100644 (file)
@@ -882,7 +882,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
        int lm = 0;
 
        if (type != SCO_LINK && type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -908,7 +908,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
        BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        if (!status) {
                struct sco_conn *conn;
@@ -927,7 +927,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
        BT_DBG("hcon %p reason %d", hcon, reason);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        sco_conn_del(hcon, bt_err(reason));
 
index c1ee800..ae21a0d 100644 (file)
@@ -589,23 +589,16 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
 EXPORT_SYMBOL(sk_chk_filter);
 
 /**
- *     sk_filter_rcu_release - Release a socket filter by rcu_head
+ *     sk_filter_release_rcu - Release a socket filter by rcu_head
  *     @rcu: rcu_head that contains the sk_filter to free
  */
-static void sk_filter_rcu_release(struct rcu_head *rcu)
+void sk_filter_release_rcu(struct rcu_head *rcu)
 {
        struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
-       sk_filter_release(fp);
-}
-
-static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp)
-{
-       unsigned int size = sk_filter_len(fp);
-
-       atomic_sub(size, &sk->sk_omem_alloc);
-       call_rcu_bh(&fp->rcu, sk_filter_rcu_release);
+       kfree(fp);
 }
+EXPORT_SYMBOL(sk_filter_release_rcu);
 
 /**
  *     sk_attach_filter - attach a socket filter
@@ -649,7 +642,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
        rcu_assign_pointer(sk->sk_filter, fp);
 
        if (old_fp)
-               sk_filter_delayed_uncharge(sk, old_fp);
+               sk_filter_uncharge(sk, old_fp);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sk_attach_filter);
@@ -663,7 +656,7 @@ int sk_detach_filter(struct sock *sk)
                                           sock_owned_by_user(sk));
        if (filter) {
                rcu_assign_pointer(sk->sk_filter, NULL);
-               sk_filter_delayed_uncharge(sk, filter);
+               sk_filter_uncharge(sk, filter);
                ret = 0;
        }
        return ret;
index 0ae6c22..c19bb4e 100644 (file)
@@ -96,11 +96,13 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
        struct phy_device *phydev;
        unsigned int type;
 
-       skb_push(skb, ETH_HLEN);
+       if (skb_headroom(skb) < ETH_HLEN)
+               return false;
+       __skb_push(skb, ETH_HLEN);
 
        type = classify(skb);
 
-       skb_pull(skb, ETH_HLEN);
+       __skb_pull(skb, ETH_HLEN);
 
        switch (type) {
        case PTP_CLASS_V1_IPV4:
index 13992e1..15dcc1a 100644 (file)
@@ -661,8 +661,10 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
        err = 0;
        switch (cmd) {
        case SIOCSIFADDR:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
+               if (!capable(CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       break;
+               }
 
                edev = dev->ec_ptr;
                if (edev == NULL) {
@@ -849,9 +851,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
 {
        struct iphdr *ip = ip_hdr(skb);
        unsigned char stn = ntohl(ip->saddr) & 0xff;
+       struct dst_entry *dst = skb_dst(skb);
+       struct ec_device *edev = NULL;
        struct sock *sk = NULL;
        struct sk_buff *newskb;
-       struct ec_device *edev = skb->dev->ec_ptr;
+
+       if (dst)
+               edev = dst->dev->ec_ptr;
 
        if (! edev)
                goto bad;
index 1b48eb1..b14ec7d 100644 (file)
@@ -253,6 +253,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP),
        SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
        SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
+       SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
        SNMP_MIB_SENTINEL
 };
 
index 43cf901..a66735f 100644 (file)
@@ -347,7 +347,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                 * socket up.  We've got bigger problems than
                 * non-graceful socket closings.
                 */
-               LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n");
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW);
        }
 
        tcp_update_metrics(sk);
index 05b1ecf..61c2463 100644 (file)
@@ -231,11 +231,10 @@ void tcp_select_initial_window(int __space, __u32 mss,
                /* when initializing use the value from init_rcv_wnd
                 * rather than the default from above
                 */
-               if (init_rcv_wnd &&
-                   (*rcv_wnd > init_rcv_wnd * mss))
-                       *rcv_wnd = init_rcv_wnd * mss;
-               else if (*rcv_wnd > init_cwnd * mss)
-                       *rcv_wnd = init_cwnd * mss;
+               if (init_rcv_wnd)
+                       *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
+               else
+                       *rcv_wnd = min(*rcv_wnd, init_cwnd * mss);
        }
 
        /* Set the clamp no higher than max representable value */
@@ -386,27 +385,30 @@ struct tcp_out_options {
  */
 static u8 tcp_cookie_size_check(u8 desired)
 {
-       if (desired > 0) {
+       int cookie_size;
+
+       if (desired > 0)
                /* previously specified */
                return desired;
-       }
-       if (sysctl_tcp_cookie_size <= 0) {
+
+       cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
+       if (cookie_size <= 0)
                /* no default specified */
                return 0;
-       }
-       if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) {
+
+       if (cookie_size <= TCP_COOKIE_MIN)
                /* value too small, specify minimum */
                return TCP_COOKIE_MIN;
-       }
-       if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) {
+
+       if (cookie_size >= TCP_COOKIE_MAX)
                /* value too large, specify maximum */
                return TCP_COOKIE_MAX;
-       }
-       if (0x1 & sysctl_tcp_cookie_size) {
+
+       if (cookie_size & 1)
                /* 8-bit multiple, illegal, fix it */
-               return (u8)(sysctl_tcp_cookie_size + 0x1);
-       }
-       return (u8)sysctl_tcp_cookie_size;
+               cookie_size++;
+
+       return (u8)cookie_size;
 }
 
 /* Write previously computed TCP options to the packet.
@@ -1513,6 +1515,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        struct tcp_sock *tp = tcp_sk(sk);
        const struct inet_connection_sock *icsk = inet_csk(sk);
        u32 send_win, cong_win, limit, in_flight;
+       int win_divisor;
 
        if (TCP_SKB_CB(skb)->flags & TCPHDR_FIN)
                goto send_now;
@@ -1544,13 +1547,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        if ((skb != tcp_write_queue_tail(sk)) && (limit >= skb->len))
                goto send_now;
 
-       if (sysctl_tcp_tso_win_divisor) {
+       win_divisor = ACCESS_ONCE(sysctl_tcp_tso_win_divisor);
+       if (win_divisor) {
                u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
 
                /* If at least some fraction of a window is available,
                 * just use it.
                 */
-               chunk /= sysctl_tcp_tso_win_divisor;
+               chunk /= win_divisor;
                if (limit >= chunk)
                        goto send_now;
        } else {
index 23cc8e1..93b7a93 100644 (file)
@@ -4021,11 +4021,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
                kfree_skb(skb);
                goto errout;
        }
-       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
        return;
 errout:
        if (err < 0)
-               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
 }
 
 static inline size_t inet6_prefix_nlmsg_size(void)
index 2a59610..70e891a 100644 (file)
@@ -1175,6 +1175,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
                                sizeof (struct ipv6hdr);
 
                        dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr);
+                       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+                               dev->mtu-=8;
 
                        if (dev->mtu < IPV6_MIN_MTU)
                                dev->mtu = IPV6_MIN_MTU;
@@ -1363,12 +1365,17 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
+       struct ip6_tnl *t;
+
        dev->netdev_ops = &ip6_tnl_netdev_ops;
        dev->destructor = ip6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
        dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
        dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
+       t = netdev_priv(dev);
+       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+               dev->mtu-=8;
        dev->flags |= IFF_NOARP;
        dev->addr_len = sizeof(struct in6_addr);
        dev->features |= NETIF_F_NETNS_LOCAL;
index d6bfaec..8c4d00c 100644 (file)
@@ -606,8 +606,9 @@ static int ipip6_rcv(struct sk_buff *skb)
                return 0;
        }
 
-       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+       /* no tunnel matched,  let upstream know, ipsec may handle it */
        rcu_read_unlock();
+       return 1;
 out:
        kfree_skb(skb);
        return 0;
index 0bf6a59..522e219 100644 (file)
@@ -674,4 +674,8 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, SOCK_DGRAM, IPPROTO_L2TP);
+
+/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like
+ * enums
+ */
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
index 5826129..e35dbe5 100644 (file)
@@ -317,8 +317,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                goto out;
        rc = -ENODEV;
        rtnl_lock();
+       rcu_read_lock();
        if (sk->sk_bound_dev_if) {
-               llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
+               llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
                if (llc->dev) {
                        if (!addr->sllc_arphrd)
                                addr->sllc_arphrd = llc->dev->type;
@@ -329,13 +330,13 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                            !llc_mac_match(addr->sllc_mac,
                                           llc->dev->dev_addr)) {
                                rc = -EINVAL;
-                               dev_put(llc->dev);
                                llc->dev = NULL;
                        }
                }
        } else
                llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd,
                                           addr->sllc_mac);
+       rcu_read_unlock();
        rtnl_unlock();
        if (!llc->dev)
                goto out;
index 902b03e..54fb4a0 100644 (file)
@@ -2247,6 +2247,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
                break;
        case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
        case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+               if (is_multicast_ether_addr(mgmt->da) &&
+                   !is_broadcast_ether_addr(mgmt->da))
+                       return RX_DROP_MONITOR;
+
                /* process only for station */
                if (sdata->vif.type != NL80211_IFTYPE_STATION)
                        return RX_DROP_MONITOR;
@@ -2741,6 +2745,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
+                       goto out;
                }
        }
 
@@ -2780,6 +2785,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                        return;
        }
 
+ out:
        dev_kfree_skb(skb);
 }
 
index 96c5943..7a637b8 100644 (file)
@@ -1587,7 +1587,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                                list) {
                                if (!ieee80211_sdata_running(tmp_sdata))
                                        continue;
-                               if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
+                               if (tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_MONITOR ||
+                                   tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_AP_VLAN ||
+                                       tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_WDS)
                                        continue;
                                if (compare_ether_addr(tmp_sdata->vif.addr,
                                                       hdr->addr2) == 0) {
@@ -1732,15 +1737,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        int nh_pos, h_pos;
        struct sta_info *sta = NULL;
        u32 sta_flags = 0;
+       struct sk_buff *tmp_skb;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                ret = NETDEV_TX_OK;
                goto fail;
        }
 
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
        /* convert Ethernet header to proper 802.11 header (based on
         * operation mode) */
        ethertype = (skb->data[12] << 8) | skb->data[13];
@@ -1913,6 +1916,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                goto fail;
        }
 
+       /*
+        * If the skb is shared we need to obtain our own copy.
+        */
+       if (skb_shared(skb)) {
+               tmp_skb = skb;
+               skb = skb_copy(skb, GFP_ATOMIC);
+               kfree_skb(tmp_skb);
+
+               if (!skb) {
+                       ret = NETDEV_TX_OK;
+                       goto fail;
+               }
+       }
+
        hdr.frame_control = fc;
        hdr.duration_id = 0;
        hdr.seq_ctrl = 0;
@@ -1931,6 +1948,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                encaps_len = 0;
        }
 
+       nh_pos = skb_network_header(skb) - skb->data;
+       h_pos = skb_transport_header(skb) - skb->data;
+
        skb_pull(skb, skip_header_bytes);
        nh_pos -= skip_header_bytes;
        h_pos -= skip_header_bytes;
index 6bd5543..0b9ee34 100644 (file)
@@ -2932,6 +2932,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        struct sctp_association *asoc = NULL;
        struct sctp_setpeerprim prim;
        struct sctp_chunk       *chunk;
+       struct sctp_af          *af;
        int                     err;
 
        sp = sctp_sk(sk);
@@ -2959,6 +2960,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        if (!sctp_state(asoc, ESTABLISHED))
                return -ENOTCONN;
 
+       af = sctp_get_af_specific(prim.sspp_addr.ss_family);
+       if (!af)
+               return -EINVAL;
+
+       if (!af->addr_valid((union sctp_addr *)&prim.sspp_addr, sp, NULL))
+               return -EADDRNOTAVAIL;
+
        if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
                return -EADDRNOTAVAIL;
 
index 3ca2fd9..088fb3f 100644 (file)
@@ -732,6 +732,21 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
        return ret;
 }
 
+/**
+ * kernel_recvmsg - Receive a message from a socket (kernel space)
+ * @sock:       The socket to receive the message from
+ * @msg:        Received message
+ * @vec:        Input s/g array for message data
+ * @num:        Size of input s/g array
+ * @size:       Number of bytes to read
+ * @flags:      Message flags (MSG_DONTWAIT, etc...)
+ *
+ * On return the msg structure contains the scatter/gather array passed in the
+ * vec argument. The array is modified so that it consists of the unfilled
+ * portion of the original array.
+ *
+ * The returned value is the total number of bytes received, or an error.
+ */
 int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
                   struct kvec *vec, size_t num, size_t size, int flags)
 {
index ea2ff78..3f2c555 100644 (file)
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
        spin_lock(&svc_xprt_class_lock);
        list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
                struct svc_xprt *newxprt;
+               unsigned short newport;
 
                if (strcmp(xprt_name, xcl->xcl_name))
                        continue;
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                spin_lock_bh(&serv->sv_lock);
                list_add(&newxprt->xpt_list, &serv->sv_permsocks);
                spin_unlock_bh(&serv->sv_lock);
+               newport = svc_xprt_local_port(newxprt);
                clear_bit(XPT_BUSY, &newxprt->xpt_flags);
-               return svc_xprt_local_port(newxprt);
+               return newport;
        }
  err:
        spin_unlock(&svc_xprt_class_lock);
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt)
 {
        BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
        xprt->xpt_pool = NULL;
+       /* As soon as we clear busy, the xprt could be closed and
+        * 'put', so we need a reference to call svc_xprt_enqueue with:
+        */
+       svc_xprt_get(xprt);
        clear_bit(XPT_BUSY, &xprt->xpt_flags);
        svc_xprt_enqueue(xprt);
+       svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_received);
 
index 73e7b95..b25c646 100644 (file)
@@ -394,6 +394,7 @@ void __exit x25_link_free(void)
        list_for_each_safe(entry, tmp, &x25_neigh_list) {
                nb = list_entry(entry, struct x25_neigh, node);
                __x25_remove_neigh(nb);
+               dev_put(nb->dev);
        }
        write_unlock_bh(&x25_neigh_list_lock);
 }
index eb96ce5..220ebc0 100644 (file)
@@ -1268,7 +1268,7 @@ struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
 
        return xc;
 error:
-       kfree(xc);
+       xfrm_state_put(xc);
        return NULL;
 }
 EXPORT_SYMBOL(xfrm_state_migrate);
index cb0c23a..4a66347 100644 (file)
@@ -189,6 +189,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
        a->channels = GRAB_BITS(buf, 0, 0, 3);
        a->channels++;
 
+       a->sample_bits = 0;
+       a->max_bitrate = 0;
+
        a->format = GRAB_BITS(buf, 0, 3, 4);
        switch (a->format) {
        case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
@@ -198,7 +201,6 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 
        case AUDIO_CODING_TYPE_LPCM:
                val = GRAB_BITS(buf, 2, 0, 3);
-               a->sample_bits = 0;
                for (i = 0; i < 3; i++)
                        if (val & (1 << i))
                                a->sample_bits |= cea_sample_sizes[i + 1];
@@ -598,24 +600,19 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
 {
        int i;
 
-       pcm->rates = 0;
-       pcm->formats = 0;
-       pcm->maxbps = 0;
-       pcm->channels_min = -1;
-       pcm->channels_max = 0;
+       /* assume basic audio support (the basic audio flag is not in ELD;
+        * however, all audio capable sinks are required to support basic
+        * audio) */
+       pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+       pcm->formats = SNDRV_PCM_FMTBIT_S16_LE;
+       pcm->maxbps = 16;
+       pcm->channels_max = 2;
        for (i = 0; i < eld->sad_count; i++) {
                struct cea_sad *a = &eld->sad[i];
                pcm->rates |= a->rates;
-               if (a->channels < pcm->channels_min)
-                       pcm->channels_min = a->channels;
                if (a->channels > pcm->channels_max)
                        pcm->channels_max = a->channels;
                if (a->format == AUDIO_CODING_TYPE_LPCM) {
-                       if (a->sample_bits & AC_SUPPCM_BITS_16) {
-                               pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE;
-                               if (pcm->maxbps < 16)
-                                       pcm->maxbps = 16;
-                       }
                        if (a->sample_bits & AC_SUPPCM_BITS_20) {
                                pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
                                if (pcm->maxbps < 20)
@@ -635,7 +632,6 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        /* restrict the parameters by the values the codec provides */
        pcm->rates &= codec_pars->rates;
        pcm->formats &= codec_pars->formats;
-       pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min);
        pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
index 21aa9b0..b030c8e 100644 (file)
@@ -2296,6 +2296,7 @@ static int azx_dev_free(struct snd_device *device)
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
index 846d1ea..76bd58a 100644 (file)
@@ -2116,8 +2116,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        struct conexant_spec *spec = codec->spec;
        unsigned int pinctl;
 
-       snd_printdd("CXT5066: update speaker, hp_present=%d\n",
-               spec->hp_present);
+       snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
+                   spec->hp_present, spec->cur_eapd);
 
        /* Port A (HP) */
        pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
@@ -2125,11 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
                        pinctl);
 
        /* Port D (HP/LO) */
-       pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
-               ? spec->port_d_mode : 0;
-       /* Mute if Port A is connected on Thinkpad */
-       if (spec->thinkpad && (spec->hp_present & 1))
-               pinctl = 0;
+       if (spec->dell_automute) {
+               /* DELL AIO Port Rule: PortA>  PortD>  IntSpk */
+               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
+                       ? PIN_OUT : 0;
+       } else if (spec->thinkpad) {
+               if (spec->cur_eapd)
+                       pinctl = spec->port_d_mode;
+               /* Mute dock line-out if Port A (laptop HP) is present */
+               if (spec->hp_present&  1)
+                       pinctl = 0;
+       } else {
+               pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
+                       ? spec->port_d_mode : 0;
+       }
        snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
 
@@ -2137,14 +2146,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
        snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
-
-       if (spec->dell_automute) {
-               /* DELL AIO Port Rule: PortA > PortD > IntSpk */
-               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
-                       ? PIN_OUT : 0;
-               snd_hda_codec_write(codec, 0x1c, 0,
-                       AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
-       }
 }
 
 /* turn on/off EAPD (+ mute HP) as a master switch */
@@ -3095,8 +3096,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
-                     CXT5066_DELL_LAPTOP),
+       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
@@ -3109,6 +3109,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD),
index d3e49aa..31df774 100644 (file)
@@ -834,7 +834,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
                        return -ENODEV;
        } else {
                /* fallback to the codec default */
-               hinfo->channels_min = codec_pars->channels_min;
                hinfo->channels_max = codec_pars->channels_max;
                hinfo->rates = codec_pars->rates;
                hinfo->formats = codec_pars->formats;
index 8fddc9d..427da45 100644 (file)
@@ -4595,6 +4595,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+       SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
@@ -10829,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, err;
+       int i, err, type;
+       int type_idx = 0;
        hda_nid_t nid;
 
        for (i = 0; i < cfg->num_inputs; i++) {
@@ -10838,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
                nid = cfg->inputs[i].pin;
                if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
                        char label[32];
+                       type = cfg->inputs[i].type;
+                       if (i > 0 && type == cfg->inputs[i - 1].type)
+                               type_idx++;
+                       else
+                               type_idx = 0;
                        snprintf(label, sizeof(label), "%s Boost",
                                 hda_get_autocfg_input_label(codec, cfg, i));
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label,
+                                         type_idx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
@@ -14799,6 +14807,8 @@ static int alc269_resume(struct hda_codec *codec)
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC269_FIXUP_DELL_M101Z,
+       ALC269_FIXUP_LENOVO_EDGE14,
+       ALC269_FIXUP_ASUS_G73JW,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14816,11 +14826,22 @@ static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC269_FIXUP_LENOVO_EDGE14] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
+       },
+       [ALC269_FIXUP_ASUS_G73JW] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_LENOVO_EDGE14),
+       SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        {}
 };
 
index a2e0ed5..8725d4e 100644 (file)
 static const u16 wm8580_reg[] = {
        0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
        0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
-       0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/
+       0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/
        0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
        0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
        0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
@@ -491,16 +491,16 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                paifa |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               paifa |= 0x10;
-               paifb |= WM8580_AIF_LENGTH_24;
+               paifa |= 0x0;
+               paifb |= WM8580_AIF_LENGTH_32;
                break;
        default:
                return -EINVAL;
index fca60a0..9001cc4 100644 (file)
@@ -818,7 +818,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8904->deemph;
+       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       return 0;
 }
 
 static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
index f89ad6c..9cbab8e 100644 (file)
@@ -380,7 +380,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8955->deemph;
+       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       return 0;
 }
 
 static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
index 8d5efb3..21986c4 100644 (file)
@@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8960->deemph;
+       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       return 0;
 }
 
 static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
index e809274..1304ca9 100644 (file)
@@ -3339,7 +3339,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        int mask;
        int active;
 
-       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
 
        active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
        active &= ~mask;
index 19ca782..0e24092 100644 (file)
@@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch",
 SOC_DOUBLE_R("Speaker ZC Switch",
             WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
             7, 1, 0),
-SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
+SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
               spkboost_tlv),
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
index 441285a..85b7d54 100644 (file)
@@ -1619,12 +1619,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #ifdef CONFIG_SND_SOC_AC97_BUS
        /* register any AC97 codecs */
        for (i = 0; i < card->num_rtd; i++) {
-                       ret = soc_register_ac97_dai_link(&card->rtd[i]);
-                       if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
-                               goto probe_dai_err;
-                       }
+               ret = soc_register_ac97_dai_link(&card->rtd[i]);
+               if (ret < 0) {
+                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       while (--i >= 0)
+                               soc_unregister_ac97_dai_link(&card->rtd[i]);
+                       goto probe_dai_err;
                }
+       }
 #endif
 
        card->instantiated = 1;
@@ -3072,7 +3074,9 @@ int snd_soc_register_dais(struct device *dev,
                pr_debug("Registered DAI '%s'\n", dai->name);
        }
 
+       mutex_lock(&client_mutex);
        snd_soc_instantiate_cards();
+       mutex_unlock(&client_mutex);
        return 0;
 
 err:
index 75ed649..c721502 100644 (file)
@@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                case SND_SOC_DAPM_STREAM_RESUME:
                        sys_power = 1;
                        break;
+               case SND_SOC_DAPM_STREAM_STOP:
+                       sys_power = !!codec->active;
+                       break;
                case SND_SOC_DAPM_STREAM_SUSPEND:
                        sys_power = 0;
                        break;