Merge branch 'stable-3.2' into pandora-3.2
authorGrazvydas Ignotas <notasas@gmail.com>
Sun, 13 Dec 2015 17:57:16 +0000 (19:57 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 13 Dec 2015 17:57:16 +0000 (19:57 +0200)
483 files changed:
Documentation/networking/rds.txt
Documentation/pinctrl.txt
Documentation/sysctl/fs.txt
Makefile
arch/arm/Makefile
arch/arm/include/asm/elf.h
arch/arm/kernel/signal.c
arch/arm/mach-pxa/include/mach/pxa27x.h
arch/arm/mach-pxa/pxa27x.c
arch/m68k/include/asm/linkage.h
arch/mips/include/asm/atomic.h
arch/mips/include/asm/cacheflush.h
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
arch/mips/include/asm/octeon/pci-octeon.h
arch/mips/include/asm/pgtable.h
arch/mips/kernel/irq.c
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/mm/cache.c
arch/mips/mm/dma-default.c
arch/mips/pci/pci-octeon.c
arch/mips/pci/pcie-octeon.c
arch/mips/power/hibernate.S
arch/parisc/kernel/irq.c
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/lib/Makefile
arch/parisc/lib/ucmpdi2.c [new file with mode: 0644]
arch/powerpc/kernel/cacheinfo.c
arch/powerpc/kernel/perf_callchain.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/mmap_64.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/mpic_pasemi_msi.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/ppc4xx_msi.c
arch/s390/crypto/ghash_s390.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/process.c
arch/s390/kernel/sclp.S
arch/s390/kernel/suspend.c
arch/s390/kvm/priv.c
arch/sparc/include/asm/visasm.h
arch/sparc/kernel/leon_pci.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/lib/VISsave.S
arch/tile/kernel/setup.c
arch/x86/Kconfig
arch/x86/crypto/ghash-clmulni-intel_glue.c
arch/x86/include/asm/desc.h
arch/x86/include/asm/iommu_table.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mmu.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/head_64.S
arch/x86/kernel/ldt.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/step.c
arch/x86/kernel/tsc.c
arch/x86/kernel/verify_cpu.S
arch/x86/kvm/i8254.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/usercopy_64.c
arch/x86/math-emu/fpu_entry.c
arch/x86/math-emu/fpu_system.h
arch/x86/math-emu/get_address.c
arch/x86/net/bpf_jit_comp.c
arch/x86/power/cpu.c
arch/x86/xen/enlighten.c
arch/x86/xen/setup.c
crypto/ablkcipher.c
crypto/ahash.c
crypto/algapi.c
crypto/algif_hash.c
crypto/api.c
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utxface.c
drivers/acpi/osl.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/auxdisplay/ks0108.c
drivers/base/devres.c
drivers/base/platform.c
drivers/base/regmap/regmap-debugfs.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/agp/intel-gtt.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/talitos.c
drivers/dma/mv_xor.c
drivers/dma/mv_xor.h
drivers/edac/Kconfig
drivers/edac/sb_edac.c
drivers/firewire/ohci.c
drivers/firmware/dmi_scan.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/hid/hid-core.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mlx4/ah.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/qib/qib.h
drivers/infiniband/hw/qib/qib_keys.c
drivers/infiniband/hw/qib/qib_verbs.c
drivers/infiniband/hw/qib/qib_verbs.h
drivers/input/evdev.c
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/intel-iommu.c
drivers/lguest/core.c
drivers/macintosh/windfarm_core.c
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree-spine.c
drivers/md/persistent-data/dm-btree.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid1.h
drivers/md/raid10.c
drivers/md/raid10.h
drivers/md/raid5.c
drivers/media/dvb/frontends/cx24116.c
drivers/media/dvb/frontends/s5h1420.c
drivers/media/rc/rc-main.c
drivers/memstick/core/mspro_block.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mtd/maps/dc21285.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdpart.c
drivers/mtd/ubi/attach.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/vtbl.c
drivers/mtd/ubi/wl.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/stmicro/stmmac/descs.h
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/niu.c
drivers/net/phy/dp83640.c
drivers/net/ppp/pppoe.c
drivers/net/usb/asix.c
drivers/net/virtio_net.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netback/xenbus.c
drivers/of/address.c
drivers/of/base.c
drivers/pci/access.c
drivers/pci/quirks.c
drivers/pcmcia/topic.h
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/ideapad-laptop.c
drivers/power/wm831x_power.c
drivers/regulator/core.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-sas.c
drivers/scsi/3w-sas.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/ipr.h
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libiscsi.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/spi/spi-pxa2xx.c
drivers/staging/hv/storvsc_drv.c
drivers/staging/iio/accel/sca3000_ring.c
drivers/staging/iio/dac/ad5624r_spi.c
drivers/staging/line6/pcm.c
drivers/staging/panel/panel.c
drivers/staging/rtl8712/rtl8712_recv.c
drivers/staging/rtl8712/usb_intf.c
drivers/staging/vt6655/device_main.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_device.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_pscsi.h
drivers/tty/hvc/hvc_xen.c
drivers/tty/n_tty.c
drivers/tty/serial/8250_pnp.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/uartlite.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_io.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/m66592-udc.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-sysfs.c
drivers/usb/host/ehci.h
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_core.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/sierra.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/vhost.c
drivers/watchdog/omap_wdt.c
drivers/xen/events.c
drivers/xen/gntdev.c
drivers/xen/xen-pciback/conf_space.c
drivers/xen/xen-pciback/conf_space.h
drivers/xen/xen-pciback/conf_space_header.c
firmware/ihex2fw.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/binfmt_elf.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/print-tree.c
fs/btrfs/tree-log.c
fs/btrfs/xattr.c
fs/buffer.c
fs/cachefiles/rdwr.c
fs/ceph/super.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/inode.c
fs/dcache.c
fs/debugfs/inode.c
fs/ecryptfs/dentry.c
fs/exec.c
fs/ext4/extents.c
fs/ext4/indirect.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fhandle.c
fs/fscache/netfs.c
fs/fscache/page.c
fs/fuse/inode.c
fs/gfs2/super.c
fs/hfs/bnode.c
fs/hfs/brec.c
fs/hfs/super.c
fs/hfsplus/bnode.c
fs/hfsplus/options.c
fs/hostfs/hostfs_kern.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/namei.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfsd/nfs4state.c
fs/nilfs2/btree.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlmglue.c
fs/ocfs2/super.c
fs/omfs/inode.c
fs/pipe.c
fs/proc/task_mmu.c
fs/splice.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_super.c
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/linux/acpi.h
include/linux/buffer_head.h
include/linux/fsl_devices.h
include/linux/jbd2.h
include/linux/jhash.h
include/linux/libata.h
include/linux/nfs_xdr.h
include/linux/nilfs2_fs.h
include/linux/of.h
include/linux/pci.h
include/linux/sched.h
include/linux/seq_file.h
include/linux/skbuff.h
include/net/inet_common.h
include/net/ip.h
include/net/ip6_fib.h
include/net/ip_vs.h
include/net/sctp/structs.h
include/sound/emu10k1.h
include/sound/wm8904.h
include/trace/events/jbd2.h
include/xen/events.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
kernel/cgroup.c
kernel/events/core.c
kernel/hrtimer.c
kernel/irq/proc.c
kernel/module.c
kernel/ptrace.c
kernel/rcutiny.c
kernel/sched.c
kernel/softirq.c
kernel/time/clocksource.c
kernel/trace/ring_buffer_benchmark.c
kernel/trace/trace_events_filter.c
lib/bitmap.c
lib/devres.c
lib/string.c
mm/filemap.c
mm/hugetlb.c
mm/kmemleak.c
mm/memory.c
mm/page-writeback.c
mm/slub.c
net/9p/client.c
net/Kconfig
net/bridge/br_ioctl.c
net/bridge/br_multicast.c
net/bridge/br_netfilter.c
net/bridge/br_stp_if.c
net/caif/caif_socket.c
net/ceph/osdmap.c
net/core/datagram.c
net/core/dev.c
net/core/dst.c
net/core/ethtool.c
net/core/fib_rules.c
net/core/neighbour.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/datagram.c
net/ipv4/ip_fragment.c
net/ipv4/ipmr.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/ip6_fib.c
net/ipv6/ip6mr.c
net/ipv6/ndisc.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tunnel6.c
net/ipv6/udp.c
net/irda/irlmp.c
net/key/af_key.c
net/mac80211/debugfs_netdev.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/wep.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_expect.c
net/packet/af_packet.c
net/rds/connection.c
net/rds/ib_rdma.c
net/rds/info.c
net/rds/tcp_recv.c
net/rose/af_rose.c
net/rxrpc/ar-recvmsg.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/socket.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/xprtsock.c
net/tipc/socket.c
net/unix/af_unix.c
scripts/kconfig/streamline_config.pl
scripts/recordmcount.h
security/keys/gc.c
security/selinux/hooks.c
security/selinux/nlmsgtab.c
sound/arm/Kconfig
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_callback.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8903.h
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8994.c
sound/soc/pxa/Kconfig
sound/soc/soc-dapm.c
sound/synth/emux/emux_oss.c
sound/synth/emux/emux_seq.c
sound/usb/mixer.c
sound/usb/mixer_maps.c
sound/usb/quirks-table.h
tools/perf/Makefile
tools/perf/util/header.c

index c67077c..e1a3d59 100644 (file)
@@ -62,11 +62,10 @@ Socket Interface
 ================
 
   AF_RDS, PF_RDS, SOL_RDS
-        These constants haven't been assigned yet, because RDS isn't in
-        mainline yet. Currently, the kernel module assigns some constant
-        and publishes it to user space through two sysctl files
-                /proc/sys/net/rds/pf_rds
-                /proc/sys/net/rds/sol_rds
+       AF_RDS and PF_RDS are the domain type to be used with socket(2)
+       to create RDS sockets. SOL_RDS is the socket-level to be used
+       with setsockopt(2) and getsockopt(2) for RDS specific socket
+       options.
 
   fd = socket(PF_RDS, SOCK_SEQPACKET, 0);
         This creates a new, unbound RDS socket.
index b04cb7d..074da62 100644 (file)
@@ -164,8 +164,8 @@ static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
 }
 
 static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
-                              unsigned ** const pins,
-                              unsigned * const num_pins)
+                              const unsigned **pins,
+                              unsigned *num_pins)
 {
        *pins = (unsigned *) foo_groups[selector].pins;
        *num_pins = foo_groups[selector].num_pins;
index 88fd7f5..b318a78 100644 (file)
@@ -163,16 +163,22 @@ This value can be used to query and set the core dump mode for setuid
 or otherwise protected/tainted binaries. The modes are
 
 0 - (default) - traditional behaviour. Any process which has changed
-       privilege levels or is execute only will not be dumped
+       privilege levels or is execute only will not be dumped.
 1 - (debug) - all processes dump core when possible. The core dump is
        owned by the current user and no security is applied. This is
        intended for system debugging situations only. Ptrace is unchecked.
+       This is insecure as it allows regular users to examine the memory
+       contents of privileged processes.
 2 - (suidsafe) - any binary which normally would not be dumped is dumped
-       readable by root only. This allows the end user to remove
-       such a dump but not access it directly. For security reasons
-       core dumps in this mode will not overwrite one another or
-       other files. This mode is appropriate when administrators are
-       attempting to debug problems in a normal environment.
+       anyway, but only if the "core_pattern" kernel sysctl is set to
+       either a pipe handler or a fully qualified path. (For more details
+       on this limitation, see CVE-2006-2451.) This mode is appropriate
+       when administrators are attempting to debug problems in a normal
+       environment, and either have a core dump pipe handler that knows
+       to treat privileged core dumps with care, or specific directory
+       defined for catching core dumps. If a core dump happens without
+       a pipe handler or fully qualifid path, a message will be emitted
+       to syslog warning about the lack of a correct setting.
 
 ==============================================================
 
index 8071888..89a7d05 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 69
+SUBLEVEL = 74
 EXTRAVERSION =
 NAME = Saber-toothed Squirrel
 
index 18ec2fc..e9925e0 100644 (file)
@@ -53,6 +53,14 @@ endif
 
 comma = ,
 
+#
+# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and
+# later may result in code being generated that handles signed short and signed
+# char struct members incorrectly. So disable it.
+# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932)
+#
+KBUILD_CFLAGS  += $(call cc-option,-fno-ipa-sra)
+
 # This selects which instruction set is used.
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
index 0e9ce8d..a4b1186 100644 (file)
@@ -116,7 +116,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE        (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE        (TASK_SIZE / 3 * 2)
 
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
index 9e617bd..c1d9c77 100644 (file)
@@ -486,12 +486,23 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
                 */
                thumb = handler & 1;
 
+#if __LINUX_ARM_ARCH__ >= 6
+               /*
+                * Clear the If-Then Thumb-2 execution state.  ARM spec
+                * requires this to be all 000s in ARM mode.  Snapdragon
+                * S4/Krait misbehaves on a Thumb=>ARM signal transition
+                * without this.
+                *
+                * We must do this whenever we are running on a Thumb-2
+                * capable CPU, which includes ARMv6T2.  However, we elect
+                * to do this whenever we're on an ARMv6 or later CPU for
+                * simplicity.
+                */
+               cpsr &= ~PSR_IT_MASK;
+#endif
+
                if (thumb) {
                        cpsr |= PSR_T_BIT;
-#if __LINUX_ARM_ARCH__ >= 7
-                       /* clear the If-Then Thumb-2 execution state */
-                       cpsr &= ~PSR_IT_MASK;
-#endif
                } else
                        cpsr &= ~PSR_T_BIT;
        }
index 7cff640..66c4cbf 100644 (file)
@@ -21,7 +21,7 @@
 
 extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
-extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern int pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 
 #define pxa27x_handle_irq      ichp_handle_irq
index a9447f9..f7510b1 100644 (file)
@@ -241,7 +241,7 @@ static struct clk_lookup pxa27x_clkregs[] = {
  */
 static unsigned int pwrmode = PWRMODE_SLEEP;
 
-int __init pxa27x_set_pwrmode(unsigned int mode)
+int pxa27x_set_pwrmode(unsigned int mode)
 {
        switch (mode) {
        case PWRMODE_SLEEP:
index 5a822bb..066e74f 100644 (file)
@@ -4,4 +4,34 @@
 #define __ALIGN .align 4
 #define __ALIGN_STR ".align 4"
 
+/*
+ * Make sure the compiler doesn't do anything stupid with the
+ * arguments on the stack - they are owned by the *caller*, not
+ * the callee. This just fools gcc into not spilling into them,
+ * and keeps it from doing tailcall recursion and/or using the
+ * stack slots for temporaries, since they are live and "used"
+ * all the way to the end of the function.
+ */
+#define asmlinkage_protect(n, ret, args...) \
+       __asmlinkage_protect##n(ret, ##args)
+#define __asmlinkage_protect_n(ret, args...) \
+       __asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
+#define __asmlinkage_protect0(ret) \
+       __asmlinkage_protect_n(ret)
+#define __asmlinkage_protect1(ret, arg1) \
+       __asmlinkage_protect_n(ret, "m" (arg1))
+#define __asmlinkage_protect2(ret, arg1, arg2) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2))
+#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3))
+#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4))
+#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5))
+#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5), "m" (arg6))
+
 #endif
index 1d93f81..9d4581d 100644 (file)
@@ -679,7 +679,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns the old value of @v.
+ * Returns true iff @v was not @u.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
index 69468de..484c5bc 100644 (file)
  *  - flush_icache_all() flush the entire instruction cache
  *  - flush_data_cache_page() flushes a page from the data cache
  */
+
+ /*
+ * This flag is used to indicate that the page pointed to by a pte
+ * is dirty and requires cleaning before returning it to the user.
+ */
+#define PG_dcache_dirty                        PG_arch_1
+
+#define Page_dcache_dirty(page)                \
+       test_bit(PG_dcache_dirty, &(page)->flags)
+#define SetPageDcacheDirty(page)       \
+       set_bit(PG_dcache_dirty, &(page)->flags)
+#define ClearPageDcacheDirty(page)     \
+       clear_bit(PG_dcache_dirty, &(page)->flags)
+
 extern void (*flush_cache_all)(void);
 extern void (*__flush_cache_all)(void);
 extern void (*flush_cache_mm)(struct mm_struct *mm);
@@ -37,13 +51,15 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma,
        unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 extern void __flush_dcache_page(struct page *page);
+extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 static inline void flush_dcache_page(struct page *page)
 {
-       if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
+       if (cpu_has_dc_aliases)
                __flush_dcache_page(page);
-
+       else if (!cpu_has_ic_fills_f_dc)
+               SetPageDcacheDirty(page);
 }
 
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
@@ -61,6 +77,11 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 static inline void flush_icache_page(struct vm_area_struct *vma,
        struct page *page)
 {
+       if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) &&
+           Page_dcache_dirty(page)) {
+               __flush_icache_page(vma, page);
+               ClearPageDcacheDirty(page);
+       }
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
@@ -95,19 +116,6 @@ extern void (*flush_icache_all)(void);
 extern void (*local_flush_data_cache_page)(void * addr);
 extern void (*flush_data_cache_page)(unsigned long addr);
 
-/*
- * This flag is used to indicate that the page pointed to by a pte
- * is dirty and requires cleaning before returning it to the user.
- */
-#define PG_dcache_dirty                        PG_arch_1
-
-#define Page_dcache_dirty(page)                \
-       test_bit(PG_dcache_dirty, &(page)->flags)
-#define SetPageDcacheDirty(page)       \
-       set_bit(PG_dcache_dirty, &(page)->flags)
-#define ClearPageDcacheDirty(page)     \
-       clear_bit(PG_dcache_dirty, &(page)->flags)
-
 /* Run kernel code uncached, useful for cache probing functions. */
 unsigned long run_uncached(void *func);
 
index ca400f7..0f4991b 100644 (file)
 #define cpu_has_mips_r (cpu_has_mips32r1 | cpu_has_mips32r2 | \
                         cpu_has_mips64r1 | cpu_has_mips64r2)
 
+/*
+ * cpu_has_mips_r2_exec_hazard - return if IHB is required on current processor
+ *
+ * Returns non-zero value if the current processor implementation requires
+ * an IHB instruction to deal with an instruction hazard as per MIPS R2
+ * architecture specification, zero otherwise.
+ */
 #ifndef cpu_has_mips_r2_exec_hazard
-#define cpu_has_mips_r2_exec_hazard cpu_has_mips_r2
+#define cpu_has_mips_r2_exec_hazard                                    \
+({                                                                     \
+       int __res;                                                      \
+                                                                       \
+       switch (current_cpu_type()) {                                   \
+       case CPU_74K:                                                   \
+       case CPU_CAVIUM_OCTEON:                                         \
+       case CPU_CAVIUM_OCTEON_PLUS:                                    \
+       case CPU_CAVIUM_OCTEON2:                                        \
+               __res = 0;                                              \
+               break;                                                  \
+                                                                       \
+       default:                                                        \
+               __res = 1;                                              \
+       }                                                               \
+                                                                       \
+       __res;                                                          \
+})
 #endif
 
 /*
index a58addb..6ae8e3c 100644 (file)
@@ -51,7 +51,6 @@
 #define cpu_has_mips32r2       0
 #define cpu_has_mips64r1       0
 #define cpu_has_mips64r2       1
-#define cpu_has_mips_r2_exec_hazard 0
 #define cpu_has_dsp            0
 #define cpu_has_mipsmt         0
 #define cpu_has_vint           0
index fba2ba2..ac83283 100644 (file)
@@ -11,9 +11,6 @@
 
 #include <linux/pci.h>
 
-/* Some PCI cards require delays when accessing config space. */
-#define PCI_CONFIG_SPACE_DELAY 10000
-
 /*
  * The physical memory base mapped by BAR1.  256MB at the end of the
  * first 4GB.
index b2202a6..95bcedb 100644 (file)
@@ -153,8 +153,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                 * Make sure the buddy is global too (if it's !none,
                 * it better already be global)
                 */
+#ifdef CONFIG_SMP
+               /*
+                * For SMP, multiple CPUs can race, so we need to do
+                * this atomically.
+                */
+#ifdef CONFIG_64BIT
+#define LL_INSN "lld"
+#define SC_INSN "scd"
+#else /* CONFIG_32BIT */
+#define LL_INSN "ll"
+#define SC_INSN "sc"
+#endif
+               unsigned long page_global = _PAGE_GLOBAL;
+               unsigned long tmp;
+
+               __asm__ __volatile__ (
+                       "       .set    push\n"
+                       "       .set    noreorder\n"
+                       "1:     " LL_INSN "     %[tmp], %[buddy]\n"
+                       "       bnez    %[tmp], 2f\n"
+                       "        or     %[tmp], %[tmp], %[global]\n"
+                       "       " SC_INSN "     %[tmp], %[buddy]\n"
+                       "       beqz    %[tmp], 1b\n"
+                       "        nop\n"
+                       "2:\n"
+                       "       .set pop"
+                       : [buddy] "+m" (buddy->pte),
+                         [tmp] "=&r" (tmp)
+                       : [global] "r" (page_global));
+#else /* !CONFIG_SMP */
                if (pte_none(*buddy))
                        pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
+#endif /* CONFIG_SMP */
        }
 #endif
 }
index 7f50318..6e489e5 100644 (file)
@@ -111,7 +111,7 @@ void __init init_IRQ(void)
 #endif
 }
 
-#ifdef DEBUG_STACKOVERFLOW
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
 static inline void check_stack_overflow(void)
 {
        unsigned long sp;
index 802e616..c7e2684 100644 (file)
@@ -154,7 +154,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
                                      unsigned long __user *user_mask_ptr)
 {
        unsigned int real_len;
-       cpumask_t mask;
+       cpumask_t allowed, mask;
        int retval;
        struct task_struct *p;
 
@@ -173,7 +173,8 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
        if (retval)
                goto out_unlock;
 
-       cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+       cpumask_or(&allowed, &p->thread.user_cpus_allowed, &p->cpus_allowed);
+       cpumask_and(&mask, &allowed, cpu_active_mask);
 
 out_unlock:
        read_unlock(&tasklist_lock);
index 829320c..0f8839b 100644 (file)
@@ -118,6 +118,18 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)
 
 EXPORT_SYMBOL(__flush_anon_page);
 
+void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+       unsigned long addr;
+
+       if (PageHighMem(page))
+               return;
+
+       addr = (unsigned long) page_address(page);
+       flush_data_cache_page(addr);
+}
+EXPORT_SYMBOL_GPL(__flush_icache_page);
+
 void __update_cache(struct vm_area_struct *vma, unsigned long address,
        pte_t pte)
 {
index 4608491..2bc2802 100644 (file)
@@ -67,7 +67,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
        else
 #endif
 #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
-            if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+            if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
                dma_flag = __GFP_DMA;
        else
 #endif
index ed1c542..66d3c38 100644 (file)
@@ -279,9 +279,6 @@ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
        pci_addr.s.func = devfn & 0x7;
        pci_addr.s.reg = reg;
 
-#if PCI_CONFIG_SPACE_DELAY
-       udelay(PCI_CONFIG_SPACE_DELAY);
-#endif
        switch (size) {
        case 4:
                *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64));
@@ -316,9 +313,6 @@ static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
        pci_addr.s.func = devfn & 0x7;
        pci_addr.s.reg = reg;
 
-#if PCI_CONFIG_SPACE_DELAY
-       udelay(PCI_CONFIG_SPACE_DELAY);
-#endif
        switch (size) {
        case 4:
                cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val));
index 0583c46..37a8790 100644 (file)
@@ -1219,9 +1219,6 @@ static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus,
                                        devfn & 0x7, reg, val);
                return PCIBIOS_SUCCESSFUL;
        }
-#if PCI_CONFIG_SPACE_DELAY
-       udelay(PCI_CONFIG_SPACE_DELAY);
-#endif
        return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
index 5bf34ec..2ca1735 100644 (file)
@@ -31,6 +31,8 @@ LEAF(swsusp_arch_suspend)
 END(swsusp_arch_suspend)
 
 LEAF(swsusp_arch_resume)
+       /* Avoid TLB mismatch during and after kernel resume */
+       jal local_flush_tlb_all
        PTR_L t0, restore_pblist
 0:
        PTR_L t1, PBE_ADDRESS(t0)   /* source */
@@ -44,7 +46,6 @@ LEAF(swsusp_arch_resume)
        bne t1, t3, 1b
        PTR_L t0, PBE_NEXT(t0)
        bnez t0, 0b
-       jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
        PTR_LA t0, saved_regs
        PTR_L ra, PT_R31(t0)
        PTR_L sp, PT_R29(t0)
index c0b1aff..88934b3 100644 (file)
@@ -336,8 +336,8 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        struct pt_regs *old_regs;
        unsigned long eirr_val;
        int irq, cpu = smp_processor_id();
-#ifdef CONFIG_SMP
        struct irq_desc *desc;
+#ifdef CONFIG_SMP
        cpumask_t dest;
 #endif
 
@@ -350,8 +350,12 @@ void do_cpu_irq_mask(struct pt_regs *regs)
                goto set_out;
        irq = eirr_to_irq(eirr_val);
 
-#ifdef CONFIG_SMP
+       /* Filter out spurious interrupts, mostly from serial port at bootup */
        desc = irq_to_desc(irq);
+       if (unlikely(!desc->action))
+               goto set_out;
+
+#ifdef CONFIG_SMP
        cpumask_copy(&dest, desc->irq_data.affinity);
        if (irqd_is_per_cpu(&desc->irq_data) &&
            !cpu_isset(smp_processor_id(), dest)) {
index a7bb757..c3f1be9 100644 (file)
@@ -121,11 +121,13 @@ extern void __ashrdi3(void);
 extern void __ashldi3(void);
 extern void __lshrdi3(void);
 extern void __muldi3(void);
+extern void __ucmpdi2(void);
 
 EXPORT_SYMBOL(__ashrdi3);
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
 
 asmlinkage void * __canonicalize_funcptr_for_compare(void *);
 EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
index 5f2e690..5651536 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for parisc-specific library files
 #
 
-lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
+lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \
+          ucmpdi2.o
 
 obj-y  := iomap.o
diff --git a/arch/parisc/lib/ucmpdi2.c b/arch/parisc/lib/ucmpdi2.c
new file mode 100644 (file)
index 0000000..149c016
--- /dev/null
@@ -0,0 +1,25 @@
+#include <linux/module.h>
+
+union ull_union {
+       unsigned long long ull;
+       struct {
+               unsigned int high;
+               unsigned int low;
+       } ui;
+};
+
+int __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+       union ull_union au = {.ull = a};
+       union ull_union bu = {.ull = b};
+
+       if (au.ui.high < bu.ui.high)
+               return 0;
+       else if (au.ui.high > bu.ui.high)
+               return 2;
+       if (au.ui.low < bu.ui.low)
+               return 0;
+       else if (au.ui.low > bu.ui.low)
+               return 2;
+       return 1;
+}
index 02ebe1a..4f15565 100644 (file)
@@ -62,11 +62,21 @@ struct cache_type_info {
 };
 
 /* These are used to index the cache_type_info array. */
-#define CACHE_TYPE_UNIFIED     0
-#define CACHE_TYPE_INSTRUCTION 1
-#define CACHE_TYPE_DATA        2
+#define CACHE_TYPE_UNIFIED     0 /* cache-size, cache-block-size, etc. */
+#define CACHE_TYPE_UNIFIED_D   1 /* d-cache-size, d-cache-block-size, etc */
+#define CACHE_TYPE_INSTRUCTION 2
+#define CACHE_TYPE_DATA        3
 
 static const struct cache_type_info cache_type_info[] = {
+       {
+               /* Embedded systems that use cache-size, cache-block-size,
+                * etc. for the Unified (typically L2) cache. */
+               .name            = "Unified",
+               .size_prop       = "cache-size",
+               .line_size_props = { "cache-line-size",
+                                    "cache-block-size", },
+               .nr_sets_prop    = "cache-sets",
+       },
        {
                /* PowerPC Processor binding says the [di]-cache-*
                 * must be equal on unified caches, so just use
@@ -293,7 +303,8 @@ static struct cache *cache_find_first_sibling(struct cache *cache)
 {
        struct cache *iter;
 
-       if (cache->type == CACHE_TYPE_UNIFIED)
+       if (cache->type == CACHE_TYPE_UNIFIED ||
+           cache->type == CACHE_TYPE_UNIFIED_D)
                return cache;
 
        list_for_each_entry(iter, &cache_list, list)
@@ -324,15 +335,29 @@ static bool cache_node_is_unified(const struct device_node *np)
        return of_get_property(np, "cache-unified", NULL);
 }
 
-static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node *node, int level)
+/*
+ * Unified caches can have two different sets of tags.  Most embedded
+ * use cache-size, etc. for the unified cache size, but open firmware systems
+ * use d-cache-size, etc.   Check on initialization for which type we have, and
+ * return the appropriate structure type.  Assume it's embedded if it isn't
+ * open firmware.  If it's yet a 3rd type, then there will be missing entries
+ * in /sys/devices/system/cpu/cpu0/cache/index2/, and this code will need
+ * to be extended further.
+ */
+static int cache_is_unified_d(const struct device_node *np)
 {
-       struct cache *cache;
+       return of_get_property(np,
+               cache_type_info[CACHE_TYPE_UNIFIED_D].size_prop, NULL) ?
+               CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED;
+}
 
+/*
+ */
+static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node *node, int level)
+{
        pr_debug("creating L%d ucache for %s\n", level, node->full_name);
 
-       cache = new_cache(CACHE_TYPE_UNIFIED, level, node);
-
-       return cache;
+       return new_cache(cache_is_unified_d(node), level, node);
 }
 
 static struct cache *__cpuinit cache_do_one_devnode_split(struct device_node *node, int level)
index 564c1d8..e80026c 100644 (file)
@@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
        sp = regs->gpr[1];
        perf_callchain_store(entry, next_ip);
 
-       for (;;) {
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
                fp = (unsigned long __user *) sp;
                if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
                        return;
index 434a180..17dbd34 100644 (file)
@@ -992,6 +992,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!rtas.entry)
+               return -EINVAL;
+
        if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
                return -EFAULT;
 
index 82288e9..83940d7 100644 (file)
@@ -428,7 +428,7 @@ void __init smp_setup_cpu_maps(void)
        DBG("smp_setup_cpu_maps()\n");
 
        while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < nr_cpu_ids) {
-               const int *intserv;
+               const __be32 *intserv;
                int j, len;
 
                DBG("  * %s...\n", dn->full_name);
@@ -447,10 +447,18 @@ void __init smp_setup_cpu_maps(void)
                }
 
                for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
+                       bool avail;
+
                        DBG("    thread %d -> cpu %d (hard id %d)\n",
-                           j, cpu, intserv[j]);
-                       set_cpu_present(cpu, of_device_is_available(dn));
-                       set_hard_smp_processor_id(cpu, intserv[j]);
+                           j, cpu, be32_to_cpu(intserv[j]));
+
+                       avail = of_device_is_available(dn);
+                       if (!avail)
+                               avail = !of_property_match_string(dn,
+                                               "enable-method", "spin-table");
+
+                       set_cpu_present(cpu, avail);
+                       set_hard_smp_processor_id(cpu, be32_to_cpu(intserv[j]));
                        set_cpu_possible(cpu, true);
                        cpu++;
                }
index 3e8fe4b..cec664a 100644 (file)
@@ -212,6 +212,7 @@ SECTIONS
                *(.opd)
        }
 
+       . = ALIGN(256);
        .got : AT(ADDR(.got) - LOAD_OFFSET) {
                __toc_start = .;
                *(.got)
index 5a783d8..67a42ed 100644 (file)
@@ -53,14 +53,6 @@ static inline int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-/*
- * Since get_random_int() returns the same value within a 1 jiffy window,
- * we will almost always get the same randomisation for the stack and mmap
- * region. This will mean the relative distance between stack and mmap will
- * be the same.
- *
- * To avoid this we can shift the randomness by 1 bit.
- */
 static unsigned long mmap_rnd(void)
 {
        unsigned long rnd = 0;
@@ -68,11 +60,11 @@ static unsigned long mmap_rnd(void)
        if (current->flags & PF_RANDOMIZE) {
                /* 8MB for 32bit, 1GB for 64bit */
                if (is_32bit_task())
-                       rnd = (long)(get_random_int() % (1<<(22-PAGE_SHIFT)));
+                       rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
                else
-                       rnd = (long)(get_random_int() % (1<<(29-PAGE_SHIFT)));
+                       rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
        }
-       return (rnd << PAGE_SHIFT) * 2;
+       return rnd << PAGE_SHIFT;
 }
 
 static inline unsigned long mmap_base(void)
index 85bb66d..15a05ca 100644 (file)
@@ -130,6 +130,7 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
        if (WARN_ON(!phb))
                return;
@@ -137,9 +138,10 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
        list_for_each_entry(entry, &pdev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               pnv_put_msi(phb, virq_to_hw(entry->irq));
                irq_dispose_mapping(entry->irq);
+               pnv_put_msi(phb, hwirq);
        }
 }
 #endif /* CONFIG_PCI_MSI */
index 0f1b706..2767276 100644 (file)
@@ -416,6 +416,12 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
                goto out;
        }
 
+       rc = dlpar_acquire_drc(drc_index);
+       if (rc) {
+               rc = -EINVAL;
+               goto out;
+       }
+
        dn = dlpar_configure_connector(drc_index);
        if (!dn) {
                rc = -EINVAL;
@@ -436,13 +442,6 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        kfree(dn->full_name);
        dn->full_name = cpu_name;
 
-       rc = dlpar_acquire_drc(drc_index);
-       if (rc) {
-               dlpar_free_cc_nodes(dn);
-               rc = -EINVAL;
-               goto out;
-       }
-
        rc = dlpar_attach_node(dn);
        if (rc) {
                dlpar_release_drc(drc_index);
index e5c344d..8ebbdc6 100644 (file)
@@ -106,15 +106,16 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
        struct fsl_msi *msi_data;
+       irq_hw_number_t hwirq;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                msi_data = irq_get_chip_data(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_data->bitmap,
-                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
        }
 
        return;
index 38e6238..e873616 100644 (file)
@@ -74,6 +74,7 @@ static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
        pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
 
@@ -81,10 +82,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
 
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
-                                      virq_to_hw(entry->irq), ALLOC_CHUNK);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, ALLOC_CHUNK);
        }
 
        return;
index 9a7aa0e..dfc3486 100644 (file)
@@ -124,15 +124,16 @@ static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
         list_for_each_entry(entry, &pdev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
 
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
-                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
        }
 
        return;
index 1c2d7af..4aae9c8 100644 (file)
@@ -114,16 +114,17 @@ void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct msi_desc *entry;
        struct ppc4xx_msi *msi_data = &ppc4xx_msi;
+       irq_hw_number_t hwirq;
 
        dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
 
        list_for_each_entry(entry, &dev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_data->bitmap,
-                               virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
        }
 }
 
index 31086ea..568521a 100644 (file)
 #define GHASH_DIGEST_SIZE      16
 
 struct ghash_ctx {
-       u8 icv[16];
-       u8 key[16];
+       u8 key[GHASH_BLOCK_SIZE];
 };
 
 struct ghash_desc_ctx {
+       u8 icv[GHASH_BLOCK_SIZE];
+       u8 key[GHASH_BLOCK_SIZE];
        u8 buffer[GHASH_BLOCK_SIZE];
        u32 bytes;
 };
@@ -28,8 +29,10 @@ struct ghash_desc_ctx {
 static int ghash_init(struct shash_desc *desc)
 {
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+       struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 
        memset(dctx, 0, sizeof(*dctx));
+       memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
 
        return 0;
 }
@@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm,
        }
 
        memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
-       memset(ctx->icv, 0, GHASH_BLOCK_SIZE);
 
        return 0;
 }
@@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc,
                         const u8 *src, unsigned int srclen)
 {
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
-       struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
        unsigned int n;
        u8 *buf = dctx->buffer;
        int ret;
@@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc,
                src += n;
 
                if (!dctx->bytes) {
-                       ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf,
+                       ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf,
                                              GHASH_BLOCK_SIZE);
                        if (ret != GHASH_BLOCK_SIZE)
                                return -EIO;
@@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc,
 
        n = srclen & ~(GHASH_BLOCK_SIZE - 1);
        if (n) {
-               ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n);
+               ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n);
                if (ret != n)
                        return -EIO;
                src += n;
@@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc,
        return 0;
 }
 
-static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
+static int ghash_flush(struct ghash_desc_ctx *dctx)
 {
        u8 *buf = dctx->buffer;
        int ret;
@@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 
                memset(pos, 0, dctx->bytes);
 
-               ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE);
+               ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
                if (ret != GHASH_BLOCK_SIZE)
                        return -EIO;
+
+               dctx->bytes = 0;
        }
 
-       dctx->bytes = 0;
        return 0;
 }
 
 static int ghash_final(struct shash_desc *desc, u8 *dst)
 {
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
-       struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
        int ret;
 
-       ret = ghash_flush(ctx, dctx);
+       ret = ghash_flush(dctx);
        if (!ret)
-               memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
+               memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
        return ret;
 }
 
index 9fdd05d..8831a40 100644 (file)
@@ -52,6 +52,19 @@ typedef struct
        __u32 gprs_high[NUM_GPRS];
 } rt_sigframe32;
 
+static inline void sigset_to_sigset32(unsigned long *set64,
+                                     compat_sigset_word *set32)
+{
+       set32[0] = (compat_sigset_word) set64[0];
+       set32[1] = (compat_sigset_word)(set64[0] >> 32);
+}
+
+static inline void sigset32_to_sigset(compat_sigset_word *set32,
+                                     unsigned long *set64)
+{
+       set64[0] = (unsigned long) set32[0] | ((unsigned long) set32[1] << 32);
+}
+
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
        int err;
@@ -361,12 +374,14 @@ asmlinkage long sys32_sigreturn(void)
 {
        struct pt_regs *regs = task_pt_regs(current);
        sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
+       compat_sigset_t cset;
        sigset_t set;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
+       if (__copy_from_user(&cset.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
                goto badframe;
+       sigset32_to_sigset(cset.sig, set.sig);
        sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->sregs))
@@ -383,6 +398,7 @@ asmlinkage long sys32_rt_sigreturn(void)
 {
        struct pt_regs *regs = task_pt_regs(current);
        rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
+       compat_sigset_t cset;
        sigset_t set;
        stack_t st;
        __u32 ss_sp;
@@ -391,8 +407,9 @@ asmlinkage long sys32_rt_sigreturn(void)
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+       if (__copy_from_user(&cset, &frame->uc.uc_sigmask, sizeof(cset)))
                goto badframe;
+       sigset32_to_sigset(cset.sig, set.sig);
        sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
@@ -464,13 +481,16 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
                        sigset_t *set, struct pt_regs * regs)
 {
        sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
+       compat_sigset_t cset;
+
        if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
                goto give_sigsegv;
 
        if (frame == (void __user *) -1UL)
                goto give_sigsegv;
 
-       if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
+       sigset_to_sigset32(set->sig, cset.sig);
+       if (__copy_to_user(&frame->sc.oldmask, &cset.sig, _SIGMASK_COPY_SIZE32))
                goto give_sigsegv;
 
        if (save_sigregs32(regs, &frame->sregs))
@@ -524,6 +544,7 @@ give_sigsegv:
 static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs * regs)
 {
+       compat_sigset_t cset;
        int err = 0;
        rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
        if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
@@ -536,6 +557,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                goto give_sigsegv;
 
        /* Create the ucontext.  */
+       sigset_to_sigset32(set->sig, cset.sig);
        err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
        err |= __put_user(0, &frame->uc.uc_link);
        err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
@@ -544,7 +566,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
        err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
        err |= save_sigregs_gprs_high(regs, frame->gprs_high);
-       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+       err |= __copy_to_user(&frame->uc.uc_sigmask, &cset, sizeof(cset));
        if (err)
                goto give_sigsegv;
 
index 53088e2..2ba1226 100644 (file)
@@ -250,7 +250,7 @@ asmlinkage void execve_tail(void)
 {
        current->thread.fp_regs.fpc = 0;
        if (MACHINE_HAS_IEEE)
-               asm volatile("sfpc %0,%0" : : "d" (0));
+               asm volatile("sfpc %0" : : "d" (0));
 }
 
 /*
index 95792d8..51ca1c3 100644 (file)
@@ -270,6 +270,8 @@ ENTRY(_sclp_print_early)
        jno     .Lesa2
        ahi     %r15,-80
        stmh    %r6,%r15,96(%r15)               # store upper register halves
+       basr    %r13,0
+       lmh     %r0,%r15,.Lzeroes-.(%r13)       # clear upper register halves
 .Lesa2:
 #endif
        lr      %r10,%r2                        # save string pointer
@@ -293,6 +295,8 @@ ENTRY(_sclp_print_early)
 #endif
        lm      %r6,%r15,120(%r15)              # restore registers
        br      %r14
+.Lzeroes:
+       .fill   64,4,0
 
 .LwritedataS4:
        .long   0x00760005                      # SCLP command for write data
index 47df775..ba17092 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/mm.h>
+#include <asm/ipl.h>
+#include <asm/sections.h>
 #include <asm/system.h>
 
 /*
@@ -137,6 +139,8 @@ int pfn_is_nosave(unsigned long pfn)
 {
        unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
        unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end));
+       unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
+       unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
 
        /* Always save lowcore pages (LC protection might be enabled). */
        if (pfn <= LC_PAGES)
@@ -144,6 +148,8 @@ int pfn_is_nosave(unsigned long pfn)
        if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
                return 1;
        /* Skip memory holes and read-only pages (NSS, DCSS, ...). */
+       if (pfn >= stext_pfn && pfn <= eshared_pfn)
+               return ipl_info.type == IPL_TYPE_NSS ? 1 : 0;
        if (tprot(PFN_PHYS(pfn)))
                return 1;
        return 0;
index d026389..c593e1e 100644 (file)
@@ -219,6 +219,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
        for (n = mem->count - 1; n > 0 ; n--)
                memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
 
+       memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
        mem->vm[0].cpus_total = cpus;
        mem->vm[0].cpus_configured = cpus;
        mem->vm[0].cpus_standby = 0;
index 39ca301..3a8c2af 100644 (file)
  * Must preserve %o5 between VISEntryHalf and VISExitHalf */
 
 #define VISEntryHalf                                   \
-       rd              %fprs, %o5;                     \
-       andcc           %o5, FPRS_FEF, %g0;             \
-       be,pt           %icc, 297f;                     \
-        sethi          %hi(298f), %g7;                 \
-       sethi           %hi(VISenterhalf), %g1;         \
-       jmpl            %g1 + %lo(VISenterhalf), %g0;   \
-        or             %g7, %lo(298f), %g7;            \
-       clr             %o5;                            \
-297:   wr              %o5, FPRS_FEF, %fprs;           \
-298:
+       VISEntry
 
 #define VISExitHalf                                    \
+       VISExit
+
+#define VISExitHalfFast                                        \
        wr              %o5, 0, %fprs;
 
 #ifndef __ASSEMBLY__
index f1cf6ef..a0ef32e 100644 (file)
@@ -78,7 +78,6 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
 
 void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
 {
-       struct leon_pci_info *info = pbus->sysdata;
        struct pci_dev *dev;
        int i, has_io, has_mem;
        u16 cmd;
@@ -153,18 +152,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return pci_enable_resources(dev, mask);
 }
 
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
-       /*
-        * Currently the OpenBoot nodes are not connected with the PCI device,
-        * this is because the LEON PROM does not create PCI nodes. Eventually
-        * this will change and the same approach as pcic.c can be used to
-        * match PROM nodes with pci devices.
-        */
-       return NULL;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
 void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
 {
 #ifdef CONFIG_PCI_DEBUG
index 5e4252b..0ff682d 100644 (file)
@@ -368,11 +368,11 @@ static unsigned long mmap_rnd(void)
        if (current->flags & PF_RANDOMIZE) {
                unsigned long val = get_random_int();
                if (test_thread_flag(TIF_32BIT))
-                       rnd = (val % (1UL << (22UL-PAGE_SHIFT)));
+                       rnd = (val % (1UL << (23UL-PAGE_SHIFT)));
                else
-                       rnd = (val % (1UL << (29UL-PAGE_SHIFT)));
+                       rnd = (val % (1UL << (30UL-PAGE_SHIFT)));
        }
-       return (rnd << PAGE_SHIFT) * 2;
+       return rnd << PAGE_SHIFT;
 }
 
 void arch_pick_mmap_layout(struct mm_struct *mm)
index b320ae9..a063d84 100644 (file)
@@ -44,9 +44,8 @@ vis1: ldub            [%g6 + TI_FPSAVED], %g3
 
         stx            %g3, [%g6 + TI_GSR]
 2:     add             %g6, %g1, %g3
-       cmp             %o5, FPRS_DU
-       be,pn           %icc, 6f
-        sll            %g1, 3, %g1
+       mov             FPRS_DU | FPRS_DL | FPRS_FEF, %o5
+       sll             %g1, 3, %g1
        stb             %o5, [%g3 + TI_FPSAVED]
        rd              %gsr, %g2
        add             %g6, %g1, %g3
@@ -80,65 +79,3 @@ vis1:        ldub            [%g6 + TI_FPSAVED], %g3
        .align          32
 80:    jmpl            %g7 + %g0, %g0
         nop
-
-6:     ldub            [%g3 + TI_FPSAVED], %o5
-       or              %o5, FPRS_DU, %o5
-       add             %g6, TI_FPREGS+0x80, %g2
-       stb             %o5, [%g3 + TI_FPSAVED]
-
-       sll             %g1, 5, %g1
-       add             %g6, TI_FPREGS+0xc0, %g3
-       wr              %g0, FPRS_FEF, %fprs
-       membar          #Sync
-       stda            %f32, [%g2 + %g1] ASI_BLK_P
-       stda            %f48, [%g3 + %g1] ASI_BLK_P
-       membar          #Sync
-       ba,pt           %xcc, 80f
-        nop
-
-       .align          32
-80:    jmpl            %g7 + %g0, %g0
-        nop
-
-       .align          32
-VISenterhalf:
-       ldub            [%g6 + TI_FPDEPTH], %g1
-       brnz,a,pn       %g1, 1f
-        cmp            %g1, 1
-       stb             %g0, [%g6 + TI_FPSAVED]
-       stx             %fsr, [%g6 + TI_XFSR]
-       clr             %o5
-       jmpl            %g7 + %g0, %g0
-        wr             %g0, FPRS_FEF, %fprs
-
-1:     bne,pn          %icc, 2f
-        srl            %g1, 1, %g1
-       ba,pt           %xcc, vis1
-        sub            %g7, 8, %g7
-2:     addcc           %g6, %g1, %g3
-       sll             %g1, 3, %g1
-       andn            %o5, FPRS_DU, %g2
-       stb             %g2, [%g3 + TI_FPSAVED]
-
-       rd              %gsr, %g2
-       add             %g6, %g1, %g3
-       stx             %g2, [%g3 + TI_GSR]
-       add             %g6, %g1, %g2
-       stx             %fsr, [%g2 + TI_XFSR]
-       sll             %g1, 5, %g1
-3:     andcc           %o5, FPRS_DL, %g0
-       be,pn           %icc, 4f
-        add            %g6, TI_FPREGS, %g2
-
-       add             %g6, TI_FPREGS+0x40, %g3
-       membar          #Sync
-       stda            %f0, [%g2 + %g1] ASI_BLK_P
-       stda            %f16, [%g3 + %g1] ASI_BLK_P
-       membar          #Sync
-       ba,pt           %xcc, 4f
-        nop
-
-       .align          32
-4:     and             %o5, FPRS_DU, %o5
-       jmpl            %g7 + %g0, %g0
-        wr             %o5, FPRS_FEF, %fprs
index a09b6c3..bf3e71a 100644 (file)
@@ -973,7 +973,7 @@ static void __init load_hv_initrd(void)
 
 void __init free_initrd_mem(unsigned long begin, unsigned long end)
 {
-       free_bootmem(__pa(begin), end - begin);
+       free_bootmem_late(__pa(begin), end - begin);
 }
 
 #else
index 4fe9c89..c2274c1 100644 (file)
@@ -134,7 +134,8 @@ config SBUS
        bool
 
 config NEED_DMA_MAP_STATE
-       def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG)
+       def_bool y
+       depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB
 
 config NEED_SG_DMA_LENGTH
        def_bool y
index f781251..4827b23 100644 (file)
@@ -291,6 +291,7 @@ static struct ahash_alg ghash_async_alg = {
                        .cra_name               = "ghash",
                        .cra_driver_name        = "ghash-clmulni",
                        .cra_priority           = 400,
+                       .cra_ctxsize            = sizeof(struct ghash_async_ctx),
                        .cra_flags              = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
                        .cra_blocksize          = GHASH_BLOCK_SIZE,
                        .cra_type               = &crypto_ahash_type,
index 3225868..382ce8a 100644 (file)
@@ -277,21 +277,6 @@ static inline void clear_LDT(void)
        set_ldt(NULL, 0);
 }
 
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
-       set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
-       preempt_disable();
-       load_LDT_nolock(pc);
-       preempt_enable();
-}
-
 static inline unsigned long get_desc_base(const struct desc_struct *desc)
 {
        return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
index f229b13..0c54822 100644 (file)
@@ -79,11 +79,12 @@ struct iommu_table_entry {
  *  d). Similar to the 'init', except that this gets called from pci_iommu_init
  *      where we do have a memory allocator.
  *
- * The standard vs the _FINISH differs in that the _FINISH variant will
- * continue detecting other IOMMUs in the call list after the
- * the detection routine returns a positive number. The _FINISH will
- * stop the execution chain. Both will still call the 'init' and
- * 'late_init' functions if they are set.
+ * The standard IOMMU_INIT differs from the IOMMU_INIT_FINISH variant
+ * in that the former will continue detecting other IOMMUs in the call
+ * list after the detection routine returns a positive number, while the
+ * latter will stop the execution chain upon first successful detection.
+ * Both variants will still call the 'init' and 'late_init' functions if
+ * they are set.
  */
 #define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init)         \
        __IOMMU_INIT(_detect, _depend, _init, _late_init, 1)
index 9171618..51f85fc 100644 (file)
@@ -83,6 +83,7 @@
 #define GP_VECTOR 13
 #define PF_VECTOR 14
 #define MF_VECTOR 16
+#define AC_VECTOR 17
 #define MC_VECTOR 18
 
 #define SELECTOR_TI_MASK (1 << 2)
@@ -472,7 +473,7 @@ struct kvm_arch {
        struct kvm_pic *vpic;
        struct kvm_ioapic *vioapic;
        struct kvm_pit *vpit;
-       int vapics_in_nmi_mode;
+       atomic_t vapics_in_nmi_mode;
 
        unsigned int tss_addr;
        struct page *apic_access_page;
index 5f55e69..926f672 100644 (file)
@@ -9,8 +9,7 @@
  * we put the segment information here.
  */
 typedef struct {
-       void *ldt;
-       int size;
+       struct ldt_struct *ldt;
 
 #ifdef CONFIG_X86_64
        /* True if mm supports a task running in 32 bit compatibility mode. */
index 6902152..ce4ea94 100644 (file)
@@ -15,6 +15,51 @@ static inline void paravirt_activate_mm(struct mm_struct *prev,
 }
 #endif /* !CONFIG_PARAVIRT */
 
+/*
+ * ldt_structs can be allocated, used, and freed, but they are never
+ * modified while live.
+ */
+struct ldt_struct {
+       /*
+        * Xen requires page-aligned LDTs with special permissions.  This is
+        * needed to prevent us from installing evil descriptors such as
+        * call gates.  On native, we could merge the ldt_struct and LDT
+        * allocations, but it's not worth trying to optimize.
+        */
+       struct desc_struct *entries;
+       int size;
+};
+
+static inline void load_mm_ldt(struct mm_struct *mm)
+{
+       struct ldt_struct *ldt;
+
+       /* smp_read_barrier_depends synchronizes with barrier in install_ldt */
+       ldt = ACCESS_ONCE(mm->context.ldt);
+       smp_read_barrier_depends();
+
+       /*
+        * Any change to mm->context.ldt is followed by an IPI to all
+        * CPUs with the mm active.  The LDT will not be freed until
+        * after the IPI is handled by all such CPUs.  This means that,
+        * if the ldt_struct changes before we return, the values we see
+        * will be safe, and the new values will be loaded before we run
+        * any user code.
+        *
+        * NB: don't try to convert this to use RCU without extreme care.
+        * We would still need IRQs off, because we don't want to change
+        * the local LDT after an IPI loaded a newer value than the one
+        * that we can see.
+        */
+
+       if (unlikely(ldt))
+               set_ldt(ldt->entries, ldt->size);
+       else
+               clear_LDT();
+
+       DEBUG_LOCKS_WARN_ON(preemptible());
+}
+
 /*
  * Used for LDT copy/destruction.
  */
@@ -52,7 +97,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                 * load the LDT, if the LDT is different:
                 */
                if (unlikely(prev->context.ldt != next->context.ldt))
-                       load_LDT_nolock(&next->context);
+                       load_mm_ldt(next);
        }
 #ifdef CONFIG_SMP
        else {
@@ -65,7 +110,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                         * to make sure to use no freed page tables.
                         */
                        load_cr3(next->pgd);
-                       load_LDT_nolock(&next->context);
+                       load_mm_ldt(next);
                }
        }
 #endif
index 5538b13..3d48aa4 100644 (file)
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK                0x18000000
 #define MSR_K8_TSEG_ADDR               0xc0010112
+#define MSR_K8_TSEG_MASK               0xc0010113
 #define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
 #define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
 #define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
index 6284d6d..0cbdebf 100644 (file)
@@ -1225,7 +1225,7 @@ void __cpuinit cpu_init(void)
        load_sp0(t, &current->thread);
        set_tss_desc(cpu, t);
        load_TR_desc();
-       load_LDT(&init_mm.context);
+       load_mm_ldt(&init_mm);
 
        clear_all_debug_regs();
        dbg_restore_debug_regs();
@@ -1273,7 +1273,7 @@ void __cpuinit cpu_init(void)
        load_sp0(t, thread);
        set_tss_desc(cpu, t);
        load_TR_desc();
-       load_LDT(&init_mm.context);
+       load_mm_ldt(&init_mm);
 
        t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 
index 8d15c69..f6daf3c 100644 (file)
@@ -1504,7 +1504,18 @@ END(error_exit)
        /* runs on exception stack */
 ENTRY(nmi)
        INTR_FRAME
+       /*
+        * Fix up the exception frame if we're on Xen.
+        * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
+        * one value to the stack on native, so it may clobber the rdx
+        * scratch slot, but it won't clobber any of the important
+        * slots past it.
+        *
+        * Xen is a different story, because the Xen frame itself overlaps
+        * the "NMI executing" variable.
+        */
        PARAVIRT_ADJUST_EXCEPTION_FRAME
+
        pushq_cfi $-1
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
index e11e394..0f8ebf7 100644 (file)
@@ -63,6 +63,9 @@ startup_64:
         * tables and then reload them.
         */
 
+       /* Sanitize CPU configuration */
+       call verify_cpu
+
        /* Compute the delta between the address I am compiled to run at and the
         * address I am actually running at.
         */
@@ -160,6 +163,9 @@ ENTRY(secondary_startup_64)
         * after the boot processor executes this code.
         */
 
+       /* Sanitize CPU configuration */
+       call verify_cpu
+
        /* Enable PAE mode and PGE */
        movl    $(X86_CR4_PAE | X86_CR4_PGE), %eax
        movq    %rax, %cr4
@@ -253,6 +259,8 @@ ENTRY(secondary_startup_64)
        pushq   %rax            # target address in negative space
        lretq
 
+#include "verify_cpu.S"
+
        /* SMP bootup changes these two */
        __REFDATA
        .align  8
index 0a8e65e..1dd3230 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 
-#ifdef CONFIG_SMP
+/* context.lock is held for us, so we don't need any locking. */
 static void flush_ldt(void *current_mm)
 {
-       if (current->active_mm == current_mm)
-               load_LDT(&current->active_mm->context);
+       mm_context_t *pc;
+
+       if (current->active_mm != current_mm)
+               return;
+
+       pc = &current->active_mm->context;
+       set_ldt(pc->ldt->entries, pc->ldt->size);
 }
-#endif
 
-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
+static struct ldt_struct *alloc_ldt_struct(int size)
 {
-       void *oldldt, *newldt;
-       int oldsize;
-
-       if (mincount <= pc->size)
-               return 0;
-       oldsize = pc->size;
-       mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
-                       (~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
-       if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
-               newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
+       struct ldt_struct *new_ldt;
+       int alloc_size;
+
+       if (size > LDT_ENTRIES)
+               return NULL;
+
+       new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
+       if (!new_ldt)
+               return NULL;
+
+       BUILD_BUG_ON(LDT_ENTRY_SIZE != sizeof(struct desc_struct));
+       alloc_size = size * LDT_ENTRY_SIZE;
+
+       /*
+        * Xen is very picky: it requires a page-aligned LDT that has no
+        * trailing nonzero bytes in any page that contains LDT descriptors.
+        * Keep it simple: zero the whole allocation and never allocate less
+        * than PAGE_SIZE.
+        */
+       if (alloc_size > PAGE_SIZE)
+               new_ldt->entries = vzalloc(alloc_size);
        else
-               newldt = (void *)__get_free_page(GFP_KERNEL);
-
-       if (!newldt)
-               return -ENOMEM;
+               new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
 
-       if (oldsize)
-               memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
-       oldldt = pc->ldt;
-       memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
-              (mincount - oldsize) * LDT_ENTRY_SIZE);
+       if (!new_ldt->entries) {
+               kfree(new_ldt);
+               return NULL;
+       }
 
-       paravirt_alloc_ldt(newldt, mincount);
+       new_ldt->size = size;
+       return new_ldt;
+}
 
-#ifdef CONFIG_X86_64
-       /* CHECKME: Do we really need this ? */
-       wmb();
-#endif
-       pc->ldt = newldt;
-       wmb();
-       pc->size = mincount;
-       wmb();
-
-       if (reload) {
-#ifdef CONFIG_SMP
-               preempt_disable();
-               load_LDT(pc);
-               if (!cpumask_equal(mm_cpumask(current->mm),
-                                  cpumask_of(smp_processor_id())))
-                       smp_call_function(flush_ldt, current->mm, 1);
-               preempt_enable();
-#else
-               load_LDT(pc);
-#endif
-       }
-       if (oldsize) {
-               paravirt_free_ldt(oldldt, oldsize);
-               if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
-                       vfree(oldldt);
-               else
-                       put_page(virt_to_page(oldldt));
-       }
-       return 0;
+/* After calling this, the LDT is immutable. */
+static void finalize_ldt_struct(struct ldt_struct *ldt)
+{
+       paravirt_alloc_ldt(ldt->entries, ldt->size);
 }
 
-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+/* context.lock is held */
+static void install_ldt(struct mm_struct *current_mm,
+                       struct ldt_struct *ldt)
 {
-       int err = alloc_ldt(new, old->size, 0);
-       int i;
+       /* Synchronizes with smp_read_barrier_depends in load_mm_ldt. */
+        barrier();
+        ACCESS_ONCE(current_mm->context.ldt) = ldt;
+
+       /* Activate the LDT for all CPUs using current_mm. */
+       smp_call_function_many(mm_cpumask(current_mm), flush_ldt, current_mm,
+                              true);
+       local_irq_disable();
+       flush_ldt(current_mm);
+       local_irq_enable();
+}
 
-       if (err < 0)
-               return err;
+static void free_ldt_struct(struct ldt_struct *ldt)
+{
+       if (likely(!ldt))
+               return;
 
-       for (i = 0; i < old->size; i++)
-               write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
-       return 0;
+       paravirt_free_ldt(ldt->entries, ldt->size);
+       if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
+               vfree(ldt->entries);
+       else
+               kfree(ldt->entries);
+       kfree(ldt);
 }
 
 /*
@@ -105,17 +111,37 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
  */
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
+       struct ldt_struct *new_ldt;
        struct mm_struct *old_mm;
        int retval = 0;
 
        mutex_init(&mm->context.lock);
-       mm->context.size = 0;
        old_mm = current->mm;
-       if (old_mm && old_mm->context.size > 0) {
-               mutex_lock(&old_mm->context.lock);
-               retval = copy_ldt(&mm->context, &old_mm->context);
-               mutex_unlock(&old_mm->context.lock);
+       if (!old_mm) {
+               mm->context.ldt = NULL;
+               return 0;
+       }
+
+       mutex_lock(&old_mm->context.lock);
+       if (!old_mm->context.ldt) {
+               mm->context.ldt = NULL;
+               goto out_unlock;
        }
+
+       new_ldt = alloc_ldt_struct(old_mm->context.ldt->size);
+       if (!new_ldt) {
+               retval = -ENOMEM;
+               goto out_unlock;
+       }
+
+       memcpy(new_ldt->entries, old_mm->context.ldt->entries,
+              new_ldt->size * LDT_ENTRY_SIZE);
+       finalize_ldt_struct(new_ldt);
+
+       mm->context.ldt = new_ldt;
+
+out_unlock:
+       mutex_unlock(&old_mm->context.lock);
        return retval;
 }
 
@@ -126,53 +152,47 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
  */
 void destroy_context(struct mm_struct *mm)
 {
-       if (mm->context.size) {
-#ifdef CONFIG_X86_32
-               /* CHECKME: Can this ever happen ? */
-               if (mm == current->active_mm)
-                       clear_LDT();
-#endif
-               paravirt_free_ldt(mm->context.ldt, mm->context.size);
-               if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
-                       vfree(mm->context.ldt);
-               else
-                       put_page(virt_to_page(mm->context.ldt));
-               mm->context.size = 0;
-       }
+       free_ldt_struct(mm->context.ldt);
+       mm->context.ldt = NULL;
 }
 
 static int read_ldt(void __user *ptr, unsigned long bytecount)
 {
-       int err;
+       int retval;
        unsigned long size;
        struct mm_struct *mm = current->mm;
 
-       if (!mm->context.size)
-               return 0;
+       mutex_lock(&mm->context.lock);
+
+       if (!mm->context.ldt) {
+               retval = 0;
+               goto out_unlock;
+       }
+
        if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
                bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
 
-       mutex_lock(&mm->context.lock);
-       size = mm->context.size * LDT_ENTRY_SIZE;
+       size = mm->context.ldt->size * LDT_ENTRY_SIZE;
        if (size > bytecount)
                size = bytecount;
 
-       err = 0;
-       if (copy_to_user(ptr, mm->context.ldt, size))
-               err = -EFAULT;
-       mutex_unlock(&mm->context.lock);
-       if (err < 0)
-               goto error_return;
+       if (copy_to_user(ptr, mm->context.ldt->entries, size)) {
+               retval = -EFAULT;
+               goto out_unlock;
+       }
+
        if (size != bytecount) {
-               /* zero-fill the rest */
-               if (clear_user(ptr + size, bytecount - size) != 0) {
-                       err = -EFAULT;
-                       goto error_return;
+               /* Zero-fill the rest and pretend we read bytecount bytes. */
+               if (clear_user(ptr + size, bytecount - size)) {
+                       retval = -EFAULT;
+                       goto out_unlock;
                }
        }
-       return bytecount;
-error_return:
-       return err;
+       retval = bytecount;
+
+out_unlock:
+       mutex_unlock(&mm->context.lock);
+       return retval;
 }
 
 static int read_default_ldt(void __user *ptr, unsigned long bytecount)
@@ -196,6 +216,8 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
        struct desc_struct ldt;
        int error;
        struct user_desc ldt_info;
+       int oldsize, newsize;
+       struct ldt_struct *new_ldt, *old_ldt;
 
        error = -EINVAL;
        if (bytecount != sizeof(ldt_info))
@@ -214,34 +236,39 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
                        goto out;
        }
 
-       mutex_lock(&mm->context.lock);
-       if (ldt_info.entry_number >= mm->context.size) {
-               error = alloc_ldt(&current->mm->context,
-                                 ldt_info.entry_number + 1, 1);
-               if (error < 0)
-                       goto out_unlock;
-       }
-
-       /* Allow LDTs to be cleared by the user. */
-       if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
-               if (oldmode || LDT_empty(&ldt_info)) {
-                       memset(&ldt, 0, sizeof(ldt));
-                       goto install;
+       if ((oldmode && !ldt_info.base_addr && !ldt_info.limit) ||
+           LDT_empty(&ldt_info)) {
+               /* The user wants to clear the entry. */
+               memset(&ldt, 0, sizeof(ldt));
+       } else {
+               if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
+                       error = -EINVAL;
+                       goto out;
                }
+
+               fill_ldt(&ldt, &ldt_info);
+               if (oldmode)
+                       ldt.avl = 0;
        }
 
-       if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
-               error = -EINVAL;
+       mutex_lock(&mm->context.lock);
+
+       old_ldt = mm->context.ldt;
+       oldsize = old_ldt ? old_ldt->size : 0;
+       newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+
+       error = -ENOMEM;
+       new_ldt = alloc_ldt_struct(newsize);
+       if (!new_ldt)
                goto out_unlock;
-       }
 
-       fill_ldt(&ldt, &ldt_info);
-       if (oldmode)
-               ldt.avl = 0;
+       if (old_ldt)
+               memcpy(new_ldt->entries, old_ldt->entries, oldsize * LDT_ENTRY_SIZE);
+       new_ldt->entries[ldt_info.entry_number] = ldt;
+       finalize_ldt_struct(new_ldt);
 
-       /* Install the new entry ...  */
-install:
-       write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
+       install_ldt(mm, new_ldt);
+       free_ldt_struct(old_ldt);
        error = 0;
 
 out_unlock:
index 84c938f..af5b675 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/timer.h>
 
-/* nop stub */
-void _paravirt_nop(void)
-{
-}
+/*
+ * nop stub, which must not clobber anything *including the stack* to
+ * avoid confusing the entry prologues.
+ */
+extern void _paravirt_nop(void);
+asm (".pushsection .entry.text, \"ax\"\n"
+     ".global _paravirt_nop\n"
+     "_paravirt_nop:\n\t"
+     "ret\n\t"
+     ".size _paravirt_nop, . - _paravirt_nop\n\t"
+     ".type _paravirt_nop, @function\n\t"
+     ".popsection");
 
 /* identity function, which can be inlined */
 u32 _paravirt_ident_32(u32 x)
index e361095..aaab32e 100644 (file)
@@ -218,11 +218,11 @@ void __show_regs(struct pt_regs *regs, int all)
 void release_thread(struct task_struct *dead_task)
 {
        if (dead_task->mm) {
-               if (dead_task->mm->context.size) {
+               if (dead_task->mm->context.ldt) {
                        printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
                                        dead_task->comm,
                                        dead_task->mm->context.ldt,
-                                       dead_task->mm->context.size);
+                                       dead_task->mm->context.ldt->size);
                        BUG();
                }
        }
@@ -555,27 +555,59 @@ void set_personality_ia32(void)
        current_thread_info()->status |= TS_COMPAT;
 }
 
+/*
+ * Called from fs/proc with a reference on @p to find the function
+ * which called into schedule(). This needs to be done carefully
+ * because the task might wake up and we might look at a stack
+ * changing under us.
+ */
 unsigned long get_wchan(struct task_struct *p)
 {
-       unsigned long stack;
-       u64 fp, ip;
+       unsigned long start, bottom, top, sp, fp, ip;
        int count = 0;
 
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
-       stack = (unsigned long)task_stack_page(p);
-       if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
+
+       start = (unsigned long)task_stack_page(p);
+       if (!start)
+               return 0;
+
+       /*
+        * Layout of the stack page:
+        *
+        * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long)
+        * PADDING
+        * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING
+        * stack
+        * ----------- bottom = start + sizeof(thread_info)
+        * thread_info
+        * ----------- start
+        *
+        * The tasks stack pointer points at the location where the
+        * framepointer is stored. The data on the stack is:
+        * ... IP FP ... IP FP
+        *
+        * We need to read FP and IP, so we need to adjust the upper
+        * bound by another unsigned long.
+        */
+       top = start + THREAD_SIZE;
+       top -= 2 * sizeof(unsigned long);
+       bottom = start + sizeof(struct thread_info);
+
+       sp = ACCESS_ONCE(p->thread.sp);
+       if (sp < bottom || sp > top)
                return 0;
-       fp = *(u64 *)(p->thread.sp);
+
+       fp = ACCESS_ONCE(*(unsigned long *)sp);
        do {
-               if (fp < (unsigned long)stack ||
-                   fp >= (unsigned long)stack+THREAD_SIZE)
+               if (fp < bottom || fp > top)
                        return 0;
-               ip = *(u64 *)(fp+8);
+               ip = ACCESS_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
                if (!in_sched_functions(ip))
                        return ip;
-               fp = *(u64 *)fp;
-       } while (count++ < 16);
+               fp = ACCESS_ONCE(*(unsigned long *)fp);
+       } while (count++ < 16 && p->state != TASK_RUNNING);
        return 0;
 }
 
index 41b2f57..78842ce 100644 (file)
@@ -700,9 +700,12 @@ void native_machine_shutdown(void)
        /* Make certain I only run on the appropriate processor */
        set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
 
-       /* O.K Now that I'm on the appropriate processor,
-        * stop all of the others.
+       /*
+        * O.K Now that I'm on the appropriate processor, stop all of the
+        * others. Also disable the local irq to not receive the per-cpu
+        * timer interrupt which may trigger scheduler's load balance.
         */
+       local_irq_disable();
        stop_other_cpus();
 #endif
 
index d4f278e..bfe6a14 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/mm.h>
 #include <linux/ptrace.h>
 #include <asm/desc.h>
+#include <asm/mmu_context.h>
 
 unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
 {
@@ -27,13 +28,14 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re
                struct desc_struct *desc;
                unsigned long base;
 
-               seg &= ~7UL;
+               seg >>= 3;
 
                mutex_lock(&child->mm->context.lock);
-               if (unlikely((seg >> 3) >= child->mm->context.size))
+               if (unlikely(!child->mm->context.ldt ||
+                            seg >= child->mm->context.ldt->size))
                        addr = -1L; /* bogus selector, access would fault */
                else {
-                       desc = child->mm->context.ldt + seg;
+                       desc = &child->mm->context.ldt->entries[seg];
                        base = get_desc_base(desc);
 
                        /* 16-bit code segment? */
index 9f3706e..e8177b1 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/hypervisor.h>
 #include <asm/nmi.h>
 #include <asm/x86_init.h>
+#include <asm/geode.h>
 
 unsigned int __read_mostly cpu_khz;    /* TSC clocks / usec, not used here */
 EXPORT_SYMBOL(cpu_khz);
@@ -802,15 +803,17 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static void __init check_system_tsc_reliable(void)
 {
-#ifdef CONFIG_MGEODE_LX
-       /* RTSC counts during suspend */
+#if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC)
+       if (is_geode_lx()) {
+               /* RTSC counts during suspend */
 #define RTSC_SUSP 0x100
-       unsigned long res_low, res_high;
+               unsigned long res_low, res_high;
 
-       rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
-       /* Geode_LX - the OLPC CPU has a very reliable TSC */
-       if (res_low & RTSC_SUSP)
-               tsc_clocksource_reliable = 1;
+               rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
+               /* Geode_LX - the OLPC CPU has a very reliable TSC */
+               if (res_low & RTSC_SUSP)
+                       tsc_clocksource_reliable = 1;
+       }
 #endif
        if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
                tsc_clocksource_reliable = 1;
index b9242ba..4cf401f 100644 (file)
 #include <asm/msr-index.h>
 
 verify_cpu:
-       pushfl                          # Save caller passed flags
-       pushl   $0                      # Kill any dangerous flags
-       popfl
+       pushf                           # Save caller passed flags
+       push    $0                      # Kill any dangerous flags
+       popf
 
+#ifndef __x86_64__
        pushfl                          # standard way to check for cpuid
        popl    %eax
        movl    %eax,%ebx
@@ -48,6 +49,7 @@ verify_cpu:
        popl    %eax
        cmpl    %eax,%ebx
        jz      verify_cpu_no_longmode  # cpu has no cpuid
+#endif
 
        movl    $0x0,%eax               # See if cpuid 1 is implemented
        cpuid
@@ -130,10 +132,10 @@ verify_cpu_sse_test:
        jmp     verify_cpu_sse_test     # try again
 
 verify_cpu_no_longmode:
-       popfl                           # Restore caller passed flags
+       popf                            # Restore caller passed flags
        movl $1,%eax
        ret
 verify_cpu_sse_ok:
-       popfl                           # Restore caller passed flags
+       popf                            # Restore caller passed flags
        xorl %eax, %eax
        ret
index cced57f..ab98fe5 100644 (file)
@@ -318,7 +318,7 @@ static void pit_do_work(struct work_struct *work)
                 * LVT0 to NMI delivery. Other PIC interrupts are just sent to
                 * VCPU0, and only if its LVT0 is in EXTINT mode.
                 */
-               if (kvm->arch.vapics_in_nmi_mode > 0)
+               if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0)
                        kvm_for_each_vcpu(i, vcpu, kvm)
                                kvm_apic_nmi_wd_deliver(vcpu);
        }
index 176205a..055cc49 100644 (file)
@@ -757,10 +757,10 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
                if (!nmi_wd_enabled) {
                        apic_debug("Receive NMI setting on APIC_LVT0 "
                                   "for cpu %d\n", apic->vcpu->vcpu_id);
-                       apic->vcpu->kvm->arch.vapics_in_nmi_mode++;
+                       atomic_inc(&apic->vcpu->kvm->arch.vapics_in_nmi_mode);
                }
        } else if (nmi_wd_enabled)
-               apic->vcpu->kvm->arch.vapics_in_nmi_mode--;
+               atomic_dec(&apic->vcpu->kvm->arch.vapics_in_nmi_mode);
 }
 
 static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
@@ -1253,6 +1253,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 
        apic_update_ppr(apic);
        hrtimer_cancel(&apic->lapic_timer.timer);
+       apic_manage_nmi_watchdog(apic, apic_get_reg(apic, APIC_LVT0));
        update_divide_count(apic);
        start_apic_timer(apic);
        apic->irr_pending = true;
index bfc9507..4a949c7 100644 (file)
@@ -3609,7 +3609,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                }
        }
 
-       mask.cr0_wp = mask.cr4_pae = mask.nxe = 1;
+       mask.cr0_wp = mask.cr4_pae = mask.nxe = mask.smep_andnot_wp = 1;
        for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn, node) {
                pte_size = sp->role.cr4_pae ? 8 : 4;
                misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
index 7a2d9d6..ff3535a 100644 (file)
@@ -1014,6 +1014,8 @@ static void init_vmcb(struct vcpu_svm *svm)
        set_exception_intercept(svm, PF_VECTOR);
        set_exception_intercept(svm, UD_VECTOR);
        set_exception_intercept(svm, MC_VECTOR);
+       set_exception_intercept(svm, AC_VECTOR);
+       set_exception_intercept(svm, DB_VECTOR);
 
        set_intercept(svm, INTERCEPT_INTR);
        set_intercept(svm, INTERCEPT_NMI);
@@ -1549,20 +1551,13 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
        mark_dirty(svm->vmcb, VMCB_SEG);
 }
 
-static void update_db_intercept(struct kvm_vcpu *vcpu)
+static void update_bp_intercept(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
-       clr_exception_intercept(svm, DB_VECTOR);
        clr_exception_intercept(svm, BP_VECTOR);
 
-       if (svm->nmi_singlestep)
-               set_exception_intercept(svm, DB_VECTOR);
-
        if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
-               if (vcpu->guest_debug &
-                   (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
-                       set_exception_intercept(svm, DB_VECTOR);
                if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
                        set_exception_intercept(svm, BP_VECTOR);
        } else
@@ -1580,7 +1575,7 @@ static void svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
 
        mark_dirty(svm->vmcb, VMCB_DR);
 
-       update_db_intercept(vcpu);
+       update_bp_intercept(vcpu);
 }
 
 static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
@@ -1654,7 +1649,6 @@ static int db_interception(struct vcpu_svm *svm)
                if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
                        svm->vmcb->save.rflags &=
                                ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
-               update_db_intercept(&svm->vcpu);
        }
 
        if (svm->vcpu.guest_debug &
@@ -1689,6 +1683,12 @@ static int ud_interception(struct vcpu_svm *svm)
        return 1;
 }
 
+static int ac_interception(struct vcpu_svm *svm)
+{
+       kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
+       return 1;
+}
+
 static void svm_fpu_activate(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -3188,6 +3188,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
        [SVM_EXIT_EXCP_BASE + NM_VECTOR]        = nm_interception,
        [SVM_EXIT_EXCP_BASE + MC_VECTOR]        = mc_interception,
+       [SVM_EXIT_EXCP_BASE + AC_VECTOR]        = ac_interception,
        [SVM_EXIT_INTR]                         = intr_interception,
        [SVM_EXIT_NMI]                          = nmi_interception,
        [SVM_EXIT_SMI]                          = nop_on_interception,
@@ -3549,7 +3550,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu)
         */
        svm->nmi_singlestep = true;
        svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
-       update_db_intercept(vcpu);
 }
 
 static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
index 911d264..7216916 100644 (file)
@@ -244,6 +244,7 @@ TRACE_EVENT(kvm_apic,
        { SVM_EXIT_EXCP_BASE + UD_VECTOR,       "UD excp" }, \
        { SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
        { SVM_EXIT_EXCP_BASE + NM_VECTOR,       "NM excp" }, \
+       { SVM_EXIT_EXCP_BASE + AC_VECTOR,       "AC excp" }, \
        { SVM_EXIT_EXCP_BASE + MC_VECTOR,       "MC excp" }, \
        { SVM_EXIT_INTR,                        "interrupt" }, \
        { SVM_EXIT_NMI,                         "nmi" }, \
index 8831c43..fb8c23d 100644 (file)
@@ -1171,7 +1171,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        u32 eb;
 
        eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
-            (1u << NM_VECTOR) | (1u << DB_VECTOR);
+            (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR);
        if ((vcpu->guest_debug &
             (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
            (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
@@ -3032,8 +3032,16 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 
 static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-       unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
-                   KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
+       /*
+        * Pass through host's Machine Check Enable value to hw_cr4, which
+        * is in force while we are in guest mode.  Do not let guests control
+        * this bit, even if host CR4.MCE == 0.
+        */
+       unsigned long hw_cr4 =
+               (read_cr4() & X86_CR4_MCE) |
+               (cr4 & ~X86_CR4_MCE) |
+               (to_vmx(vcpu)->rmode.vm86_active ?
+                KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
        if (cr4 & X86_CR4_VMXE) {
                /*
@@ -4258,6 +4266,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
 
        ex_no = intr_info & INTR_INFO_VECTOR_MASK;
        switch (ex_no) {
+       case AC_VECTOR:
+               kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
+               return 1;
        case DB_VECTOR:
                dr6 = vmcs_readl(EXIT_QUALIFICATION);
                if (!(vcpu->guest_debug &
index bb179cc..0e3289b 100644 (file)
@@ -1885,6 +1885,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_IA32_LASTINTFROMIP:
        case MSR_IA32_LASTINTTOIP:
        case MSR_K8_SYSCFG:
+       case MSR_K8_TSEG_ADDR:
+       case MSR_K8_TSEG_MASK:
        case MSR_K7_HWCR:
        case MSR_VM_HSAVE_PA:
        case MSR_P6_PERFCTR0:
index 554b7b5..433b21d 100644 (file)
@@ -113,7 +113,7 @@ long __strnlen_user(const char __user *s, long n)
        char c;
 
        while (1) {
-               if (res>n)
+               if (res >= n)
                        return n+1;
                if (__get_user(c, s))
                        return 0;
index 7718541..dab1f8b 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/regset.h>
 
 #include <asm/uaccess.h>
-#include <asm/desc.h>
 #include <asm/user.h>
 #include <asm/i387.h>
 
@@ -184,7 +183,7 @@ void math_emulate(struct math_emu_info *info)
                        math_abort(FPU_info, SIGILL);
                }
 
-               code_descriptor = LDT_DESCRIPTOR(FPU_CS);
+               code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
                if (SEG_D_SIZE(code_descriptor)) {
                        /* The above test may be wrong, the book is not clear */
                        /* Segmented 32 bit protected mode */
index 2c61441..d342fce 100644 (file)
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
-/* s is always from a cpu register, and the cpu does bounds checking
- * during register load --> no further bounds checks needed */
-#define LDT_DESCRIPTOR(s)      (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
+#include <asm/desc.h>
+#include <asm/mmu_context.h>
+
+static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg)
+{
+       static struct desc_struct zero_desc;
+       struct desc_struct ret = zero_desc;
+
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+       seg >>= 3;
+       mutex_lock(&current->mm->context.lock);
+       if (current->mm->context.ldt && seg < current->mm->context.ldt->size)
+               ret = current->mm->context.ldt->entries[seg];
+       mutex_unlock(&current->mm->context.lock);
+#endif
+       return ret;
+}
+
 #define SEG_D_SIZE(x)          ((x).b & (3 << 21))
 #define SEG_G_BIT(x)           ((x).b & (1 << 23))
 #define SEG_GRANULARITY(x)     (((x).b & (1 << 23)) ? 4096 : 1)
index 6ef5e99..8300db7 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/stddef.h>
 
 #include <asm/uaccess.h>
-#include <asm/desc.h>
 
 #include "fpu_system.h"
 #include "exception.h"
@@ -158,7 +157,7 @@ static long pm_address(u_char FPU_modrm, u_char segment,
                addr->selector = PM_REG_(segment);
        }
 
-       descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
+       descriptor = FPU_get_ldt_descriptor(addr->selector);
        base_address = SEG_BASE_ADDR(descriptor);
        address = base_address + offset;
        limit = base_address
index 5a5b6e4..11e3100 100644 (file)
@@ -150,7 +150,12 @@ void bpf_jit_compile(struct sk_filter *fp)
        }
        cleanup_addr = proglen; /* epilogue address */
 
-       for (pass = 0; pass < 10; pass++) {
+       /* JITed image shrinks with every pass and the loop iterates
+        * until the image stops shrinking. Very large bpf programs
+        * may converge on the last pass. In such case do one more
+        * pass to emit the final image
+        */
+       for (pass = 0; pass < 10 || image; pass++) {
                u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
                /* no prologue/epilogue for trivial filters (RET something) */
                proglen = 0;
index 43c9f6a..bc21909 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/xcr.h>
 #include <asm/suspend.h>
 #include <asm/debugreg.h>
+#include <asm/mmu_context.h>
 
 #ifdef CONFIG_X86_32
 static struct saved_context saved_context;
@@ -147,7 +148,7 @@ static void fix_processor_context(void)
        syscall_init();                         /* This sets MSR_*STAR and related */
 #endif
        load_TR_desc();                         /* This does ltr */
-       load_LDT(&current->active_mm->context); /* This does lldt */
+       load_mm_ldt(current->active_mm);        /* This does lldt */
 }
 
 /**
index 5189fe8..81afe1b 100644 (file)
@@ -321,6 +321,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
        pte_t pte;
        unsigned long pfn;
        struct page *page;
+       unsigned char dummy;
 
        ptep = lookup_address((unsigned long)v, &level);
        BUG_ON(ptep == NULL);
@@ -330,6 +331,32 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 
        pte = pfn_pte(pfn, prot);
 
+       /*
+        * Careful: update_va_mapping() will fail if the virtual address
+        * we're poking isn't populated in the page tables.  We don't
+        * need to worry about the direct map (that's always in the page
+        * tables), but we need to be careful about vmap space.  In
+        * particular, the top level page table can lazily propagate
+        * entries between processes, so if we've switched mms since we
+        * vmapped the target in the first place, we might not have the
+        * top-level page table entry populated.
+        *
+        * We disable preemption because we want the same mm active when
+        * we probe the target and when we issue the hypercall.  We'll
+        * have the same nominal mm, but if we're a kernel thread, lazy
+        * mm dropping could change our pgd.
+        *
+        * Out of an abundance of caution, this uses __get_user() to fault
+        * in the target address just in case there's some obscure case
+        * in which the target address isn't readable.
+        */
+
+       preempt_disable();
+
+       pagefault_disable();    /* Avoid warnings due to being atomic. */
+       __get_user(dummy, (unsigned char __user __force *)v);
+       pagefault_enable();
+
        if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
                BUG();
 
@@ -341,6 +368,8 @@ static void set_aliased_prot(void *v, pgprot_t prot)
                                BUG();
        } else
                kmap_flush_unused();
+
+       preempt_enable();
 }
 
 static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
@@ -348,6 +377,17 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
        const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
        int i;
 
+       /*
+        * We need to mark the all aliases of the LDT pages RO.  We
+        * don't need to call vm_flush_aliases(), though, since that's
+        * only responsible for flushing aliases out the TLBs, not the
+        * page tables, and Xen will flush the TLB for us if needed.
+        *
+        * To avoid confusing future readers: none of this is necessary
+        * to load the LDT.  The hypervisor only checks this when the
+        * LDT is faulted in due to subsequent descriptor access.
+        */
+
        for(i = 0; i < entries; i += entries_per_page)
                set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
 }
index 4d54b38..3c7b70d 100644 (file)
@@ -273,7 +273,7 @@ char * __init xen_memory_setup(void)
                xen_ignore_unusable(map, memmap.nr_entries);
 
        /* Make sure the Xen-supplied memory map is well-ordered. */
-       sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
+       sanitize_e820_map(map, ARRAY_SIZE(map), &memmap.nr_entries);
 
        max_pages = xen_get_max_pages();
        if (max_pages > max_pfn)
index 9f73037..d53a30b 100644 (file)
@@ -700,7 +700,7 @@ struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index 7fe1752..96c8e7c 100644 (file)
@@ -462,7 +462,8 @@ static int ahash_prepare_alg(struct ahash_alg *alg)
        struct crypto_alg *base = &alg->halg.base;
 
        if (alg->halg.digestsize > PAGE_SIZE / 8 ||
-           alg->halg.statesize > PAGE_SIZE / 8)
+           alg->halg.statesize > PAGE_SIZE / 8 ||
+           alg->halg.statesize == 0)
                return -EINVAL;
 
        base->cra_type = &crypto_ahash_type;
index 3b9ef92..5593afd 100644 (file)
@@ -342,7 +342,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval)
                crypto_alg_tested(larval->alg.cra_driver_name, 0);
        }
 
-       err = wait_for_completion_interruptible(&larval->completion);
+       err = wait_for_completion_killable(&larval->completion);
        WARN_ON(err);
 
 out:
index 8502462..a68b56a 100644 (file)
@@ -192,9 +192,14 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
        struct sock *sk2;
        struct alg_sock *ask2;
        struct hash_ctx *ctx2;
+       bool more;
        int err;
 
-       err = crypto_ahash_export(req, state);
+       lock_sock(sk);
+       more = ctx->more;
+       err = more ? crypto_ahash_export(req, state) : 0;
+       release_sock(sk);
+
        if (err)
                return err;
 
@@ -205,7 +210,10 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
        sk2 = newsock->sk;
        ask2 = alg_sk(sk2);
        ctx2 = ask2->private;
-       ctx2->more = 1;
+       ctx2->more = more;
+
+       if (!more)
+               return err;
 
        err = crypto_ahash_import(&ctx2->req, state);
        if (err) {
index ac80794..a5547fb 100644 (file)
@@ -178,7 +178,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
        struct crypto_larval *larval = (void *)alg;
        long timeout;
 
-       timeout = wait_for_completion_interruptible_timeout(
+       timeout = wait_for_completion_killable_timeout(
                &larval->completion, 60 * HZ);
 
        alg = larval->adult;
@@ -441,7 +441,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
@@ -558,7 +558,7 @@ void *crypto_alloc_tfm(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index b7491ee..6454fe6 100644 (file)
 #define ACPI_SET64(ptr)                 *ACPI_CAST_PTR (u64, ptr)
 
 /*
- * printf() format helpers
+ * printf() format helper. This macros is a workaround for the difficulties
+ * with emitting 64-bit integers and 64-bit pointers with the same code
+ * for both 32-bit and 64-bit hosts.
  */
 
 /* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i), ACPI_LODWORD(i)
 
-#if ACPI_MACHINE_WIDTH == 64
-#define ACPI_FORMAT_NATIVE_UINT(i)      ACPI_FORMAT_UINT64(i)
-#else
-#define ACPI_FORMAT_NATIVE_UINT(i)      0, (i)
-#endif
-
 /*
  * Macros for moving data around to/from buffers that are possibly unaligned.
  * If the hardware supports the transfer of unaligned data, just do the store.
index c627a28..9d19587 100644 (file)
@@ -446,7 +446,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
                          obj_desc,
-                         ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
+                         ACPI_FORMAT_UINT64(obj_desc->region.address),
                          obj_desc->region.length));
 
        /* Now the address and length are valid for this opregion */
@@ -545,7 +545,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
                          obj_desc,
-                         ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
+                         ACPI_FORMAT_UINT64(obj_desc->region.address),
                          obj_desc->region.length));
 
        /* Now the address and length are valid for this opregion */
index f0edf5c..cb18ab4 100644 (file)
@@ -450,8 +450,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                          "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
                          &region_obj->region.handler->address_space, handler,
-                         ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
-                                                 region_offset),
+                         ACPI_FORMAT_UINT64(region_obj->region.address +
+                                            region_offset),
                          acpi_ut_get_region_name(region_obj->region.
                                                  space_id)));
 
index 61b8c0e..c572fa0 100644 (file)
@@ -613,8 +613,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
                        acpi_os_printf("\n");
                } else {
                        acpi_os_printf(" base %8.8X%8.8X Length %X\n",
-                                      ACPI_FORMAT_NATIVE_UINT(obj_desc->region.
-                                                              address),
+                                      ACPI_FORMAT_UINT64(obj_desc->region.
+                                                         address),
                                       obj_desc->region.length);
                }
                break;
index b334f54..be22142 100644 (file)
@@ -257,17 +257,15 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
        }
 
        ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
-                             " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
+                             " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
                              acpi_ut_get_region_name(rgn_desc->region.
                                                      space_id),
                              rgn_desc->region.space_id,
                              obj_desc->common_field.access_byte_width,
                              obj_desc->common_field.base_byte_offset,
-                             field_datum_byte_offset, ACPI_CAST_PTR(void,
-                                                                    (rgn_desc->
-                                                                     region.
-                                                                     address +
-                                                                     region_offset))));
+                             field_datum_byte_offset,
+                             ACPI_FORMAT_UINT64(rgn_desc->region.address +
+                                                region_offset)));
 
        /* Invoke the appropriate address_space/op_region handler */
 
index f0d5e14..dd5e930 100644 (file)
@@ -174,7 +174,7 @@ acpi_ex_system_memory_space_handler(u32 function,
                if (!mem_info->mapped_logical_address) {
                        ACPI_ERROR((AE_INFO,
                                    "Could not map memory at 0x%8.8X%8.8X, size %u",
-                                   ACPI_FORMAT_NATIVE_UINT(address),
+                                   ACPI_FORMAT_UINT64(address),
                                    (u32) map_length));
                        mem_info->mapped_length = 0;
                        return_ACPI_STATUS(AE_NO_MEMORY);
@@ -195,8 +195,7 @@ acpi_ex_system_memory_space_handler(u32 function,
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
-                         bit_width, function,
-                         ACPI_FORMAT_NATIVE_UINT(address)));
+                         bit_width, function, ACPI_FORMAT_UINT64(address)));
 
        /*
         * Perform the memory read or write
@@ -298,8 +297,7 @@ acpi_ex_system_io_space_handler(u32 function,
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
-                         bit_width, function,
-                         ACPI_FORMAT_NATIVE_UINT(address)));
+                         bit_width, function, ACPI_FORMAT_UINT64(address)));
 
        /* Decode the function parameter */
 
index 5f16058..d43b8af 100644 (file)
@@ -141,17 +141,17 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
        byte_width = ACPI_DIV_8(bit_width);
        last_address = address + byte_width - 1;
 
-       ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
-                         ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void,
-                                                                     last_address),
-                         byte_width));
+       ACPI_DEBUG_PRINT((ACPI_DB_IO,
+                         "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X",
+                         ACPI_FORMAT_UINT64(address),
+                         ACPI_FORMAT_UINT64(last_address), byte_width));
 
        /* Maximum 16-bit address in I/O space */
 
        if (last_address > ACPI_UINT16_MAX) {
                ACPI_ERROR((AE_INFO,
-                           "Illegal I/O port address/length above 64K: %p/0x%X",
-                           ACPI_CAST_PTR(void, address), byte_width));
+                           "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X",
+                           ACPI_FORMAT_UINT64(address), byte_width));
                return_ACPI_STATUS(AE_LIMIT);
        }
 
@@ -180,8 +180,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
 
                        if (acpi_gbl_osi_data >= port_info->osi_dependency) {
                                ACPI_DEBUG_PRINT((ACPI_DB_IO,
-                                                 "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
-                                                 ACPI_CAST_PTR(void, address),
+                                                 "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)",
+                                                 ACPI_FORMAT_UINT64(address),
                                                  byte_width, port_info->name,
                                                  port_info->start,
                                                  port_info->end));
index b683cc2..0a68c73 100644 (file)
@@ -251,12 +251,11 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                switch (type) {
                case ACPI_TYPE_PROCESSOR:
 
-                       acpi_os_printf("ID %X Len %.4X Addr %p\n",
+                       acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n",
                                       obj_desc->processor.proc_id,
                                       obj_desc->processor.length,
-                                      ACPI_CAST_PTR(void,
-                                                    obj_desc->processor.
-                                                    address));
+                                      ACPI_FORMAT_UINT64(obj_desc->processor.
+                                                         address));
                        break;
 
                case ACPI_TYPE_DEVICE:
@@ -327,8 +326,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                                                               space_id));
                        if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
                                acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
-                                              ACPI_FORMAT_NATIVE_UINT
-                                              (obj_desc->region.address),
+                                              ACPI_FORMAT_UINT64(obj_desc->
+                                                                 region.
+                                                                 address),
                                               obj_desc->region.length);
                        } else {
                                acpi_os_printf
index 62365f6..08a3380 100644 (file)
@@ -228,9 +228,9 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
        status = acpi_os_table_override(table_desc->pointer, &override_table);
        if (ACPI_SUCCESS(status) && override_table) {
                ACPI_INFO((AE_INFO,
-                          "%4.4s @ 0x%p Table override, replaced with:",
+                          "%4.4s @ 0x%8.8X%8.8X Table override, replaced with:",
                           table_desc->pointer->signature,
-                          ACPI_CAST_PTR(void, table_desc->address)));
+                          ACPI_FORMAT_UINT64(table_desc->address)));
 
                /* We can delete the table that was passed as a parameter */
 
index 0f2d395..24de78f 100644 (file)
@@ -237,16 +237,12 @@ acpi_tb_print_table_header(acpi_physical_address address,
 {
        struct acpi_table_header local_header;
 
-       /*
-        * The reason that the Address is cast to a void pointer is so that we
-        * can use %p which will work properly on both 32-bit and 64-bit hosts.
-        */
        if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
 
                /* FACS only has signature and length fields */
 
-               ACPI_INFO((AE_INFO, "%4.4s %p %05X",
-                          header->signature, ACPI_CAST_PTR(void, address),
+               ACPI_INFO((AE_INFO, "%4.4s 0x%8.8X%8.8X %05X",
+                          header->signature, ACPI_FORMAT_UINT64(address),
                           header->length));
        } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
 
@@ -257,8 +253,8 @@ acpi_tb_print_table_header(acpi_physical_address address,
                                          header)->oem_id, ACPI_OEM_ID_SIZE);
                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 
-               ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
-                          ACPI_CAST_PTR (void, address),
+               ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %05X (v%.2d %6.6s)",
+                          ACPI_FORMAT_UINT64(address),
                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
                            revision >
                            0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
@@ -272,8 +268,8 @@ acpi_tb_print_table_header(acpi_physical_address address,
                acpi_tb_cleanup_table_header(&local_header, header);
 
                ACPI_INFO((AE_INFO,
-                          "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
-                          local_header.signature, ACPI_CAST_PTR(void, address),
+                          "%-4.4s 0x%8.8X%8.8X %05X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
+                          local_header.signature, ACPI_FORMAT_UINT64(address),
                           local_header.length, local_header.revision,
                           local_header.oem_id, local_header.oem_table_id,
                           local_header.oem_revision,
@@ -488,9 +484,8 @@ acpi_tb_install_table(acpi_physical_address address,
        status = acpi_os_table_override(mapped_table, &override_table);
        if (ACPI_SUCCESS(status) && override_table) {
                ACPI_INFO((AE_INFO,
-                          "%4.4s @ 0x%p Table override, replaced with:",
-                          mapped_table->signature, ACPI_CAST_PTR(void,
-                                                                 address)));
+                          "%4.4s @ 0x%8.8X%8.8X Table override, replaced with:",
+                          mapped_table->signature, ACPI_FORMAT_UINT64(address)));
 
                acpi_gbl_root_table_list.tables[table_index].pointer =
                    override_table;
index 7eb6c6c..0272fbe 100644 (file)
@@ -119,7 +119,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  *
  ******************************************************************************/
 
-acpi_status acpi_find_root_pointer(acpi_size *table_address)
+acpi_status acpi_find_root_pointer(acpi_physical_address * table_address)
 {
        u8 *table_ptr;
        u8 *mem_rover;
@@ -177,7 +177,8 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
                        physical_address +=
                            (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
-                       *table_address = physical_address;
+                       *table_address =
+                           (acpi_physical_address) physical_address;
                        return_ACPI_STATUS(AE_OK);
                }
        }
@@ -210,7 +211,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
                    (ACPI_HI_RSDP_WINDOW_BASE +
                     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
-               *table_address = physical_address;
+               *table_address = (acpi_physical_address) physical_address;
                return_ACPI_STATUS(AE_OK);
        }
 
index 420ebfe..ecc428e 100644 (file)
@@ -163,10 +163,12 @@ acpi_status acpi_enable_subsystem(u32 flags)
         * Obtain a permanent mapping for the FACS. This is required for the
         * Global Lock and the Firmware Waking Vector
         */
-       status = acpi_tb_initialize_facs();
-       if (ACPI_FAILURE(status)) {
-               ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
-               return_ACPI_STATUS(status);
+       if (!(flags & ACPI_NO_FACS_INIT)) {
+               status = acpi_tb_initialize_facs();
+               if (ACPI_FAILURE(status)) {
+                       ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
+                       return_ACPI_STATUS(status);
+               }
        }
 
        /*
index a6664d2..ec965de 100644 (file)
@@ -82,6 +82,7 @@ static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
 struct workqueue_struct *kacpi_hotplug_wq;
 EXPORT_SYMBOL(kacpi_hotplug_wq);
+unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;
 
 struct acpi_res_list {
        resource_size_t start;
@@ -179,7 +180,7 @@ static void __init acpi_request_region (struct acpi_generic_address *addr,
                request_mem_region(addr->address, length, desc);
 }
 
-static int __init acpi_reserve_resources(void)
+static void __init acpi_reserve_resources(void)
 {
        acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
                "ACPI PM1a_EVT_BLK");
@@ -208,10 +209,7 @@ static int __init acpi_reserve_resources(void)
        if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
                acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
                               acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
-
-       return 0;
 }
-device_initcall(acpi_reserve_resources);
 
 void acpi_os_printf(const char *fmt, ...)
 {
@@ -569,17 +567,19 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
                acpi_irq_handler = NULL;
                return AE_NOT_ACQUIRED;
        }
+       acpi_sci_irq = irq;
 
        return AE_OK;
 }
 
-acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
+acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
 {
-       if (irq != acpi_gbl_FADT.sci_interrupt)
+       if (gsi != acpi_gbl_FADT.sci_interrupt || !acpi_sci_irq_valid())
                return AE_BAD_PARAMETER;
 
-       free_irq(irq, acpi_irq);
+       free_irq(acpi_sci_irq, acpi_irq);
        acpi_irq_handler = NULL;
+       acpi_sci_irq = INVALID_ACPI_IRQ;
 
        return AE_OK;
 }
@@ -1630,6 +1630,7 @@ acpi_status __init acpi_os_initialize(void)
 
 acpi_status __init acpi_os_initialize1(void)
 {
+       acpi_reserve_resources();
        kacpid_wq = alloc_workqueue("kacpid", 0, 1);
        kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
        kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
index 81f32e5..e2958aa 100644 (file)
@@ -67,6 +67,7 @@ enum board_ids {
        board_ahci_yes_fbs,
 
        /* board IDs for specific chipsets in alphabetical order */
+       board_ahci_avn,
        board_ahci_mcp65,
        board_ahci_mcp77,
        board_ahci_mcp89,
@@ -85,6 +86,8 @@ enum board_ids {
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
                                 unsigned long deadline);
+static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline);
 static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
                                unsigned long deadline);
 #ifdef CONFIG_PM
@@ -108,6 +111,11 @@ static struct ata_port_operations ahci_p5wdh_ops = {
 
 #define AHCI_HFLAGS(flags)     .private_data   = (void *)(flags)
 
+static struct ata_port_operations ahci_avn_ops = {
+       .inherits               = &ahci_ops,
+       .hardreset              = ahci_avn_hardreset,
+};
+
 static const struct ata_port_info ahci_port_info[] = {
        /* by features */
        [board_ahci] =
@@ -156,6 +164,12 @@ static const struct ata_port_info ahci_port_info[] = {
                .port_ops       = &ahci_ops,
        },
        /* by chipsets */
+       [board_ahci_avn] = {
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_avn_ops,
+       },
        [board_ahci_mcp65] =
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
@@ -302,14 +316,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
-       { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
-       { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
+       { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
+       { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
        { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
@@ -680,6 +694,78 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
        return rc;
 }
 
+/*
+ * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
+ *
+ * It has been observed with some SSDs that the timing of events in the
+ * link synchronization phase can leave the port in a state that can not
+ * be recovered by a SATA-hard-reset alone.  The failing signature is
+ * SStatus.DET stuck at 1 ("Device presence detected but Phy
+ * communication not established").  It was found that unloading and
+ * reloading the driver when this problem occurs allows the drive
+ * connection to be recovered (DET advanced to 0x3).  The critical
+ * component of reloading the driver is that the port state machines are
+ * reset by bouncing "port enable" in the AHCI PCS configuration
+ * register.  So, reproduce that effect by bouncing a port whenever we
+ * see DET==1 after a reset.
+ */
+static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline)
+{
+       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+       struct ata_port *ap = link->ap;
+       struct ahci_port_priv *pp = ap->private_data;
+       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+       unsigned long tmo = deadline - jiffies;
+       struct ata_taskfile tf;
+       bool online;
+       int rc, i;
+
+       DPRINTK("ENTER\n");
+
+       ahci_stop_engine(ap);
+
+       for (i = 0; i < 2; i++) {
+               u16 val;
+               u32 sstatus;
+               int port = ap->port_no;
+               struct ata_host *host = ap->host;
+               struct pci_dev *pdev = to_pci_dev(host->dev);
+
+               /* clear D2H reception area to properly wait for D2H FIS */
+               ata_tf_init(link->device, &tf);
+               tf.command = ATA_BUSY;
+               ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+               rc = sata_link_hardreset(link, timing, deadline, &online,
+                               ahci_check_ready);
+
+               if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
+                               (sstatus & 0xf) != 1)
+                       break;
+
+               ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
+                               port);
+
+               pci_read_config_word(pdev, 0x92, &val);
+               val &= ~(1 << port);
+               pci_write_config_word(pdev, 0x92, val);
+               ata_msleep(ap, 1000);
+               val |= 1 << port;
+               pci_write_config_word(pdev, 0x92, val);
+               deadline += tmo;
+       }
+
+       ahci_start_engine(ap);
+
+       if (online)
+               *class = ahci_dev_classify(ap);
+
+       DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+       return rc;
+}
+
+
 #ifdef CONFIG_PM
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
index b175000..cdf58f7 100644 (file)
@@ -314,6 +314,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
 extern struct ata_port_operations ahci_ops;
 extern struct ata_port_operations ahci_pmp_retry_srst_ops;
 
+unsigned int ahci_dev_classify(struct ata_port *ap);
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
                        u32 opts);
 void ahci_save_initial_config(struct device *dev,
index de2802c..41ffb8c 100644 (file)
@@ -1137,7 +1137,7 @@ static void ahci_dev_config(struct ata_device *dev)
        }
 }
 
-static unsigned int ahci_dev_classify(struct ata_port *ap)
+unsigned int ahci_dev_classify(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_taskfile tf;
@@ -1151,6 +1151,7 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)
 
        return ata_dev_classify(&tf);
 }
+EXPORT_SYMBOL_GPL(ahci_dev_classify);
 
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
                        u32 opts)
@@ -1668,8 +1669,7 @@ static void ahci_port_intr(struct ata_port *ap)
        if (unlikely(resetting))
                status &= ~PORT_IRQ_BAD_PMP;
 
-       /* if LPM is enabled, PHYRDY doesn't mean anything */
-       if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+       if (sata_lpm_ignore_phy_events(&ap->link)) {
                status &= ~PORT_IRQ_PHYRDY;
                ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
        }
index 5d8fc3d..4e9beff 100644 (file)
@@ -4107,9 +4107,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
-       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       /* drives which fail FPDMA_AA activation (some may freeze afterwards) */
        { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
        { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+       { "VB0250EAVER",        "HPG7",         ATA_HORKAGE_BROKEN_FPDMA_AA },
 
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
@@ -4154,6 +4155,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* devices that don't properly handle TRIM commands */
+       { "SuperSSpeed S238*",          NULL,   ATA_HORKAGE_NOTRIM, },
+
        /*
         * Some WD SATA-I drives spin up and down erratically when the link
         * is put into the slumber mode.  We don't have full list of the
@@ -4458,7 +4462,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
        else /* In the ancient relic department - skip all of this */
                return 0;
 
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+       /* On some disks, this command causes spin-up, so we need longer timeout */
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000);
 
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
@@ -6615,6 +6620,38 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
        return tmp;
 }
 
+/**
+ *     sata_lpm_ignore_phy_events - test if PHY event should be ignored
+ *     @link: Link receiving the event
+ *
+ *     Test whether the received PHY event has to be ignored or not.
+ *
+ *     LOCKING:
+ *     None:
+ *
+ *     RETURNS:
+ *     True if the event has to be ignored.
+ */
+bool sata_lpm_ignore_phy_events(struct ata_link *link)
+{
+       unsigned long lpm_timeout = link->last_lpm_change +
+                                   msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY);
+
+       /* if LPM is enabled, PHYRDY doesn't mean anything */
+       if (link->lpm_policy > ATA_LPM_MAX_POWER)
+               return true;
+
+       /* ignore the first PHY event after the LPM policy changed
+        * as it is might be spurious
+        */
+       if ((link->flags & ATA_LFLAG_CHANGED) &&
+           time_before(jiffies, lpm_timeout))
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events);
+
 /*
  * Dummy port_ops
  */
index 7d1a478..f54b077 100644 (file)
@@ -3423,6 +3423,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                }
        }
 
+       link->last_lpm_change = jiffies;
+       link->flags |= ATA_LFLAG_CHANGED;
+
        return 0;
 
 fail:
index 0ba32fe..93ea335 100644 (file)
@@ -460,6 +460,13 @@ static void sata_pmp_quirks(struct ata_port *ap)
                                       ATA_LFLAG_NO_SRST |
                                       ATA_LFLAG_ASSUME_ATA;
                }
+       } else if (vendor == 0x11ab && devid == 0x4140) {
+               /* Marvell 4140 quirks */
+               ata_for_each_link(link, ap, EDGE) {
+                       /* port 4 is for SEMB device and it doesn't like SRST */
+                       if (link->pmp == 4)
+                               link->flags |= ATA_LFLAG_DISABLED;
+               }
        }
 }
 
index 8460e62..0ac7a5e 100644 (file)
@@ -2473,7 +2473,8 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
                rbuf[14] = (lowest_aligned >> 8) & 0x3f;
                rbuf[15] = lowest_aligned;
 
-               if (ata_id_has_trim(args->id)) {
+               if (ata_id_has_trim(args->id) &&
+                   !(dev->horkage & ATA_HORKAGE_NOTRIM)) {
                        rbuf[14] |= 0x80; /* TPE */
 
                        if (ata_id_has_zero_after_trim(args->id))
index 5b93852..0d75285 100644 (file)
@@ -139,6 +139,7 @@ static int __init ks0108_init(void)
 
        ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME,
                NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+       parport_put_port(ks0108_parport);
        if (ks0108_pardevice == NULL) {
                printk(KERN_ERR KS0108_NAME ": ERROR: "
                        "parport didn't register new device\n");
index 65cd748..cc956a4 100644 (file)
@@ -254,10 +254,10 @@ void * devres_get(struct device *dev, void *new_res,
        if (!dr) {
                add_dr(dev, &new_dr->node);
                dr = new_dr;
-               new_dr = NULL;
+               new_res = NULL;
        }
        spin_unlock_irqrestore(&dev->devres_lock, flags);
-       devres_free(new_dr);
+       devres_free(new_res);
 
        return dr->data;
 }
index 7a24895..ba8f361 100644 (file)
@@ -311,9 +311,7 @@ int platform_device_add(struct platform_device *pdev)
  failed:
        while (--i >= 0) {
                struct resource *r = &pdev->resource[i];
-               unsigned long type = resource_type(r);
-
-               if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+               if (r->parent)
                        release_resource(r);
        }
 
@@ -338,9 +336,7 @@ void platform_device_del(struct platform_device *pdev)
 
                for (i = 0; i < pdev->num_resources; i++) {
                        struct resource *r = &pdev->resource[i];
-                       unsigned long type = resource_type(r);
-
-                       if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+                       if (r->parent)
                                release_resource(r);
                }
        }
index cd252e0..a7197e4 100644 (file)
@@ -23,8 +23,7 @@ static struct dentry *regmap_debugfs_root;
 /* Calculate the length of a fixed format  */
 static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
 {
-       snprintf(buf, buf_size, "%x", max_val);
-       return strlen(buf);
+       return snprintf(NULL, 0, "%x", max_val);
 }
 
 static int regmap_open_file(struct inode *inode, struct file *file)
@@ -140,7 +139,7 @@ static ssize_t regmap_access_read_file(struct file *file,
                /* If we're in the region the user is trying to read */
                if (p >= *ppos) {
                        /* ...but not beyond it */
-                       if (buf_pos >= count - 1 - tot_len)
+                       if (buf_pos + tot_len + 1 >= count)
                                break;
 
                        /* Format the register */
index 96b8cb7..857f363 100644 (file)
@@ -1292,7 +1292,8 @@ static void blkback_changed(struct xenbus_device *dev,
                        break;
                /* Missed the backend's Closing state -- fallthrough */
        case XenbusStateClosing:
-               blkfront_closing(info);
+               if (info)
+                       blkfront_closing(info);
                break;
        }
 }
index 3eb6ad2..9fb9287 100644 (file)
@@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 with sflash firmware*/
        { USB_DEVICE(0x0489, 0xE027) },
        { USB_DEVICE(0x0489, 0xE03D) },
+       { USB_DEVICE(0x04F2, 0xAFF1) },
        { USB_DEVICE(0x0930, 0x0215) },
        { USB_DEVICE(0x0CF3, 0x3002) },
        { USB_DEVICE(0x0CF3, 0xE019) },
@@ -77,6 +78,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x0489, 0xe056) },
        { USB_DEVICE(0x0489, 0xe05f) },
+       { USB_DEVICE(0x0489, 0xe076) },
        { USB_DEVICE(0x0489, 0xe078) },
        { USB_DEVICE(0x04c5, 0x1330) },
        { USB_DEVICE(0x04CA, 0x3004) },
@@ -85,8 +87,10 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x3007) },
        { USB_DEVICE(0x04CA, 0x3008) },
        { USB_DEVICE(0x04CA, 0x300b) },
+       { USB_DEVICE(0x04CA, 0x300f) },
        { USB_DEVICE(0x04CA, 0x3010) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x021c) },
        { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0930, 0x0227) },
        { USB_DEVICE(0x0b05, 0x17d0) },
@@ -98,6 +102,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0x311F) },
        { USB_DEVICE(0x0cf3, 0x3121) },
        { USB_DEVICE(0x0CF3, 0x817a) },
+       { USB_DEVICE(0x0CF3, 0x817b) },
        { USB_DEVICE(0x0cf3, 0xe003) },
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
@@ -108,6 +113,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3408) },
        { USB_DEVICE(0x13d3, 0x3423) },
        { USB_DEVICE(0x13d3, 0x3432) },
+       { USB_DEVICE(0x13d3, 0x3474) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -132,6 +138,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
@@ -140,8 +147,10 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -153,6 +162,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0CF3, 0x817b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
@@ -163,6 +173,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
index 5c385e5..d83c855 100644 (file)
@@ -148,6 +148,7 @@ static struct usb_device_id blacklist_table[] = {
        /* Atheros 3011 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
@@ -162,6 +163,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
@@ -170,8 +172,10 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -183,6 +187,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
@@ -193,6 +198,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
index 43c4ec3..59d4697 100644 (file)
@@ -1195,7 +1195,7 @@ static inline int needs_idle_maps(void)
        /* Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
         */
-       if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
+       if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG ||
             gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
             intel_iommu_gfx_mapped)
                return 1;
index 4c20c5b..8e9a8f0 100644 (file)
@@ -914,7 +914,6 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt)
                crypt->mode |= NPE_OP_NOT_IN_PLACE;
                /* This was never tested by Intel
                 * for more than one dst buffer, I think. */
-               BUG_ON(req->dst->length < nbytes);
                req_ctx->dst = NULL;
                if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook,
                                        flags, DMA_FROM_DEVICE))
index dbe76b5..90c76fc 100644 (file)
@@ -2384,6 +2384,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
                break;
        default:
                dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
+               kfree(t_alg);
                return ERR_PTR(-EINVAL);
        }
 
index 9b01145..a258101 100644 (file)
@@ -386,7 +386,8 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
        dma_cookie_t cookie = 0;
        int busy = mv_chan_is_busy(mv_chan);
        u32 current_desc = mv_chan_get_current_desc(mv_chan);
-       int seen_current = 0;
+       int current_cleaned = 0;
+       struct mv_xor_desc *hw_desc;
 
        dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
        dev_dbg(mv_chan->device->common.dev, "current_desc %x\n", current_desc);
@@ -398,38 +399,57 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
 
        list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
                                        chain_node) {
-               prefetch(_iter);
-               prefetch(&_iter->async_tx);
 
-               /* do not advance past the current descriptor loaded into the
-                * hardware channel, subsequent descriptors are either in
-                * process or have not been submitted
-                */
-               if (seen_current)
-                       break;
+               /* clean finished descriptors */
+               hw_desc = iter->hw_desc;
+               if (hw_desc->status & XOR_DESC_SUCCESS) {
+                       cookie = mv_xor_run_tx_complete_actions(iter, mv_chan,
+                                                               cookie);
 
-               /* stop the search if we reach the current descriptor and the
-                * channel is busy
-                */
-               if (iter->async_tx.phys == current_desc) {
-                       seen_current = 1;
-                       if (busy)
+                       /* done processing desc, clean slot */
+                       mv_xor_clean_slot(iter, mv_chan);
+
+                       /* break if we did cleaned the current */
+                       if (iter->async_tx.phys == current_desc) {
+                               current_cleaned = 1;
+                               break;
+                       }
+               } else {
+                       if (iter->async_tx.phys == current_desc) {
+                               current_cleaned = 0;
                                break;
+                       }
                }
-
-               cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie);
-
-               if (mv_xor_clean_slot(iter, mv_chan))
-                       break;
        }
 
        if ((busy == 0) && !list_empty(&mv_chan->chain)) {
-               struct mv_xor_desc_slot *chain_head;
-               chain_head = list_entry(mv_chan->chain.next,
-                                       struct mv_xor_desc_slot,
-                                       chain_node);
-
-               mv_xor_start_new_chain(mv_chan, chain_head);
+               if (current_cleaned) {
+                       /*
+                        * current descriptor cleaned and removed, run
+                        * from list head
+                        */
+                       iter = list_entry(mv_chan->chain.next,
+                                         struct mv_xor_desc_slot,
+                                         chain_node);
+                       mv_xor_start_new_chain(mv_chan, iter);
+               } else {
+                       if (!list_is_last(&iter->chain_node, &mv_chan->chain)) {
+                               /*
+                                * descriptors are still waiting after
+                                * current, trigger them
+                                */
+                               iter = list_entry(iter->chain_node.next,
+                                                 struct mv_xor_desc_slot,
+                                                 chain_node);
+                               mv_xor_start_new_chain(mv_chan, iter);
+                       } else {
+                               /*
+                                * some descriptors are still waiting
+                                * to be cleaned
+                                */
+                               tasklet_schedule(&mv_chan->irq_tasklet);
+                       }
+               }
        }
 
        if (cookie > 0)
index 977b592..ae2cfba 100644 (file)
@@ -30,6 +30,7 @@
 #define XOR_OPERATION_MODE_XOR         0
 #define XOR_OPERATION_MODE_MEMCPY      2
 #define XOR_OPERATION_MODE_MEMSET      4
+#define XOR_DESC_SUCCESS               0x40000000
 
 #define XOR_CURR_DESC(chan)    (chan->mmr_base + 0x210 + (chan->idx * 4))
 #define XOR_NEXT_DESC(chan)    (chan->mmr_base + 0x200 + (chan->idx * 4))
index 5948a21..203361e 100644 (file)
@@ -214,7 +214,7 @@ config EDAC_I7300
 
 config EDAC_SBRIDGE
        tristate "Intel Sandy-Bridge Integrated MC"
-       depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
+       depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
        depends on EXPERIMENTAL
        help
          Support for error detection and correction the Intel
index da71881..f8f790c 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mmzone.h>
 #include <linux/smp.h>
 #include <linux/bitmap.h>
+#include <linux/math64.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
@@ -671,6 +672,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        u32 reg;
        u64 limit, prv = 0;
        u64 tmp_mb;
+       u32 gb, mb;
        u32 rir_way;
 
        /*
@@ -683,8 +685,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tolm = GET_TOLM(reg);
        tmp_mb = (1 + pvt->tolm) >> 20;
 
-       debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+       gb = div_u64_rem(tmp_mb, 1024, &mb);
+       debugf0("TOHM: %u.%03u GB (0x%016Lx)\n",
+               gb, (mb*1000)/1024, (u64)pvt->tohm);
 
        /* Address range is already 45:25 */
        pci_read_config_dword(pvt->pci_sad1, TOHM,
@@ -692,8 +695,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tohm = GET_TOHM(reg);
        tmp_mb = (1 + pvt->tohm) >> 20;
 
-       debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+       gb = div_u64_rem(tmp_mb, 1024, &mb);
+       debugf0("TOHM: %u.%03u GB (0x%016Lx)",
+               gb, (mb*1000)/1024, (u64)pvt->tohm);
 
        /*
         * Step 2) Get SAD range and SAD Interleave list
@@ -715,10 +719,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
 
                tmp_mb = (limit + 1) >> 20;
-               debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+               gb = div_u64_rem(tmp_mb, 1000, &mb);
+               debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n",
                        n_sads,
                        get_dram_attr(reg),
-                       tmp_mb / 1000, tmp_mb % 1000,
+                       gb, (mb*1000)/1024,
                        ((u64)tmp_mb) << 20L,
                        INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
                        reg);
@@ -748,8 +753,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
                tmp_mb = (limit + 1) >> 20;
 
-               debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
-                       n_tads, tmp_mb / 1000, tmp_mb % 1000,
+               gb = div_u64_rem(tmp_mb, 1000, &mb);
+               debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+                       n_tads, gb, (mb*1000)/1024,
                        ((u64)tmp_mb) << 20L,
                        (u32)TAD_SOCK(reg),
                        (u32)TAD_CH(reg),
@@ -772,9 +778,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                              tad_ch_nilv_offset[j],
                                              &reg);
                        tmp_mb = TAD_OFFSET(reg) >> 20;
-                       debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+                       gb = div_u64_rem(tmp_mb, 1024, &mb);
+                       debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               gb, (mb*1000)/1024,
                                ((u64)tmp_mb) << 20L,
                                reg);
                }
@@ -796,9 +803,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
 
                        tmp_mb = RIR_LIMIT(reg) >> 20;
                        rir_way = 1 << RIR_WAY(reg);
-                       debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+                       gb = div_u64_rem(tmp_mb, 1024, &mb);
+                       debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               gb, (mb*1000)/1024,
                                ((u64)tmp_mb) << 20L,
                                rir_way,
                                reg);
@@ -809,9 +817,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                                      &reg);
                                tmp_mb = RIR_OFFSET(reg) << 6;
 
-                               debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+                               gb = div_u64_rem(tmp_mb, 1024, &mb);
+                               debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
                                        i, j, k,
-                                       tmp_mb / 1000, tmp_mb % 1000,
+                                       gb, (mb*1000)/1024,
                                        ((u64)tmp_mb) << 20L,
                                        (u32)RIR_RNK_TGT(reg),
                                        reg);
@@ -849,6 +858,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        u8                      ch_way,sck_way;
        u32                     tad_offset;
        u32                     rir_way;
+       u32                     gb, mb;
        u64                     ch_addr, offset, limit, prv = 0;
 
 
@@ -859,7 +869,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
         * range (e. g. VGA addresses). It is unlikely, however, that the
         * memory controller would generate an error on that range.
         */
-       if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+       if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
                sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
                edac_mc_handle_ce_no_info(mci, msg);
                return -EINVAL;
@@ -1054,7 +1064,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        ch_addr = addr & 0x7f;
        /* Remove socket wayness and remove 6 bits */
        addr >>= 6;
-       addr /= sck_xch;
+       addr = div_u64(addr, sck_xch);
 #if 0
        /* Divide by channel way */
        addr = addr / ch_way;
@@ -1074,10 +1084,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                        continue;
 
                limit = RIR_LIMIT(reg);
-
-               debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+               gb = div_u64_rem(limit >> 20, 1024, &mb);
+               debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
                        n_rir,
-                       (limit >> 20) / 1000, (limit >> 20) % 1000,
+                       gb, (mb*1000)/1024,
                        limit,
                        1 << RIR_WAY(reg));
                if  (ch_addr <= limit)
index 0a0225a..e6624c6 100644 (file)
@@ -3547,6 +3547,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
 
        reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
        ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+       /* JMicron JMB38x often shows 0 at first read, just ignore it */
+       if (!ohci->it_context_support) {
+               fw_notify("overriding IsoXmitIntMask\n");
+               ohci->it_context_support = 0xf;
+       }
        reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
        ohci->it_context_mask = ohci->it_context_support;
        ohci->n_it = hweight32(ohci->it_context_mask);
index 2861ef4..20f7daa 100644 (file)
@@ -410,24 +410,48 @@ static void __init dmi_dump_ids(void)
        printk(KERN_CONT "\n");
 }
 
-static int __init dmi_present(const char __iomem *p)
+static int __init dmi_present(const u8 *buf)
 {
-       u8 buf[15];
+       int smbios_ver;
 
-       memcpy_fromio(buf, p, 15);
-       if (dmi_checksum(buf, 15)) {
+       if (memcmp(buf, "_SM_", 4) == 0 &&
+           buf[5] < 32 && dmi_checksum(buf, buf[5])) {
+               smbios_ver = (buf[6] << 8) + buf[7];
+
+               /* Some BIOS report weird SMBIOS version, fix that up */
+               switch (smbios_ver) {
+               case 0x021F:
+               case 0x0221:
+                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
+                                smbios_ver & 0xFF, 3);
+                       smbios_ver = 0x0203;
+                       break;
+               case 0x0233:
+                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
+                       smbios_ver = 0x0206;
+                       break;
+               }
+       } else {
+               smbios_ver = 0;
+       }
+
+       buf += 16;
+
+       if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
+               if (smbios_ver)
+                       dmi_ver = smbios_ver;
+               else
+                       dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F);
                dmi_num = (buf[13] << 8) | buf[12];
                dmi_len = (buf[7] << 8) | buf[6];
                dmi_base = (buf[11] << 24) | (buf[10] << 16) |
                        (buf[9] << 8) | buf[8];
 
                if (dmi_walk_early(dmi_decode) == 0) {
-                       if (dmi_ver)
+                       if (smbios_ver) {
                                pr_info("SMBIOS %d.%d present.\n",
                                       dmi_ver >> 8, dmi_ver & 0xFF);
-                       else {
-                               dmi_ver = (buf[14] & 0xF0) << 4 |
-                                          (buf[14] & 0x0F);
+                       } else {
                                pr_info("Legacy DMI %d.%d present.\n",
                                       dmi_ver >> 8, dmi_ver & 0xFF);
                        }
@@ -435,40 +459,14 @@ static int __init dmi_present(const char __iomem *p)
                        return 0;
                }
        }
-       dmi_ver = 0;
-       return 1;
-}
 
-static int __init smbios_present(const char __iomem *p)
-{
-       u8 buf[32];
-
-       memcpy_fromio(buf, p, 32);
-       if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
-               dmi_ver = (buf[6] << 8) + buf[7];
-
-               /* Some BIOS report weird SMBIOS version, fix that up */
-               switch (dmi_ver) {
-               case 0x021F:
-               case 0x0221:
-                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
-                              dmi_ver & 0xFF, 3);
-                       dmi_ver = 0x0203;
-                       break;
-               case 0x0233:
-                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
-                       dmi_ver = 0x0206;
-                       break;
-               }
-               return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
-       }
        return 1;
 }
 
 void __init dmi_scan_machine(void)
 {
        char __iomem *p, *q;
-       int rc;
+       char buf[32];
 
        if (efi_enabled(EFI_CONFIG_TABLES)) {
                if (efi.smbios == EFI_INVALID_TABLE_ADDR)
@@ -481,10 +479,10 @@ void __init dmi_scan_machine(void)
                p = dmi_ioremap(efi.smbios, 32);
                if (p == NULL)
                        goto error;
-
-               rc = smbios_present(p);
+               memcpy_fromio(buf, p, 32);
                dmi_iounmap(p, 32);
-               if (!rc) {
+
+               if (!dmi_present(buf)) {
                        dmi_available = 1;
                        goto out;
                }
@@ -499,18 +497,15 @@ void __init dmi_scan_machine(void)
                if (p == NULL)
                        goto error;
 
+               memset(buf, 0, 16);
                for (q = p; q < p + 0x10000; q += 16) {
-                       if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
-                               rc = smbios_present(q);
-                       else if (memcmp(q, "_DMI_", 5) == 0)
-                               rc = dmi_present(q);
-                       else
-                               continue;
-                       if (!rc) {
+                       memcpy_fromio(buf + 16, q, 16);
+                       if (!dmi_present(buf)) {
                                dmi_available = 1;
                                dmi_iounmap(p, 0x10000);
                                goto out;
                        }
+                       memcpy(buf, buf + 16, 16);
                }
                dmi_iounmap(p, 0x10000);
        }
index 36ae055..e901fef 100644 (file)
@@ -726,6 +726,7 @@ static struct class gpio_class = {
  */
 int gpio_export(unsigned gpio, bool direction_may_change)
 {
+       struct gpio_chip        *chip;
        unsigned long           flags;
        struct gpio_desc        *desc;
        int                     status;
@@ -743,10 +744,18 @@ int gpio_export(unsigned gpio, bool direction_may_change)
                return -EINVAL;
        }
 
+       desc = &gpio_desc[gpio];
+       chip = desc->chip;
+
        mutex_lock(&sysfs_lock);
 
+       /* check if chip is being removed */
+       if (!chip || !chip->exported) {
+               status = -ENODEV;
+               goto fail_unlock;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
-       desc = &gpio_desc[gpio];
        if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
             test_bit(FLAG_EXPORT, &desc->flags)) {
                spin_unlock_irqrestore(&gpio_lock, flags);
@@ -973,12 +982,15 @@ static void gpiochip_unexport(struct gpio_chip *chip)
 {
        int                     status;
        struct device           *dev;
+       struct gpio_desc *desc;
+       unsigned int i;
 
        mutex_lock(&sysfs_lock);
        dev = class_find_device(&gpio_class, NULL, chip, match_export);
        if (dev) {
                put_device(dev);
                device_unregister(dev);
+               /* prevent further gpiod exports */
                chip->exported = 0;
                status = 0;
        } else
@@ -988,6 +1000,13 @@ static void gpiochip_unexport(struct gpio_chip *chip)
        if (status)
                pr_debug("%s: chip %s status %d\n", __func__,
                                chip->label, status);
+
+       /* unregister gpio class devices owned by sysfs */
+       for (i = 0; i < chip->ngpio; i++) {
+               desc = &gpio_desc[chip->base + i];
+               if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
+                       gpio_free(chip->base + i);
+       }
 }
 
 static int __init gpiolib_sysfs_init(void)
@@ -1137,6 +1156,8 @@ int gpiochip_remove(struct gpio_chip *chip)
        int             status = 0;
        unsigned        id;
 
+       gpiochip_unexport(chip);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        of_gpiochip_remove(chip);
@@ -1154,9 +1175,6 @@ int gpiochip_remove(struct gpio_chip *chip)
 
        spin_unlock_irqrestore(&gpio_lock, flags);
 
-       if (status == 0)
-               gpiochip_unexport(chip);
-
        return status;
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
index 09851ce..20110b4 100644 (file)
@@ -1505,6 +1505,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
+       /*
+        * Universal plane src offsets are only 16.16, prevent havoc for
+        * drivers using universal plane code internally.
+        */
+       if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
+               return -ERANGE;
+
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, crtc_req->crtc_id,
                                   DRM_MODE_OBJECT_CRTC);
index a0b69ae..9b9f447 100644 (file)
@@ -950,13 +950,13 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
                  u32 old_write = obj->base.write_domain;
 
 
+               obj->dirty = 1; /* be paranoid  */
                obj->base.read_domains = obj->base.pending_read_domains;
                obj->base.write_domain = obj->base.pending_write_domain;
                obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
 
                i915_gem_object_move_to_active(obj, ring, seqno);
                if (obj->base.write_domain) {
-                       obj->dirty = 1;
                        obj->pending_gpu_write = true;
                        list_move_tail(&obj->gpu_write_list,
                                       &ring->gpu_write_list);
index bd0b1fc..fc64ad0 100644 (file)
@@ -172,11 +172,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
        struct nouveau_bo *nvbo = nouveau_gem_object(gem);
        struct nouveau_vma *vma;
 
-       if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+       if (is_power_of_2(nvbo->valid_domains))
+               rep->domain = nvbo->valid_domains;
+       else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
                rep->domain = NOUVEAU_GEM_DOMAIN_GART;
        else
                rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
        rep->offset = nvbo->bo.offset;
        if (fpriv->vm) {
                vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
index 927d170..76c4f2a 100644 (file)
@@ -302,8 +302,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
@@ -346,8 +348,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
index 8115557..87a677e 100644 (file)
@@ -1259,10 +1259,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
 
                        if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) &&
                            (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) {
+                               u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8;
+
+                               if (hss > lvds->native_mode.hdisplay)
+                                       hss = (10 - 1) * 8;
+
                                lvds->native_mode.htotal = lvds->native_mode.hdisplay +
                                        (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8;
                                lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
-                                       (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8;
+                                       hss;
                                lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
                                        (RBIOS8(tmp + 23) * 8);
 
@@ -3394,6 +3399,14 @@ void radeon_combios_asic_init(struct drm_device *dev)
            rdev->pdev->subsystem_device == 0x30ae)
                return;
 
+       /* quirk for rs4xx HP Compaq dc5750 Small Form Factor to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS480 &&
+           rdev->pdev->subsystem_vendor == 0x103c &&
+           rdev->pdev->subsystem_device == 0x280a)
+               return;
+
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
        if (table)
index 683cede..6303fc8 100644 (file)
@@ -82,6 +82,11 @@ void radeon_connector_hotplug(struct drm_connector *connector)
                        if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
                        } else if (radeon_dp_needs_link_train(radeon_connector)) {
+                               /* Don't try to start link training before we
+                                * have the dpcd */
+                               if (!radeon_dp_getdpcd(radeon_connector))
+                                       return;
+
                                /* set it to OFF so that drm_helper_connector_dpms()
                                 * won't return immediately since the current state
                                 * is ON at this point.
index ba7ab79..d257210 100644 (file)
@@ -171,8 +171,10 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
                        }
                }
        }
-       mb();
-       radeon_gart_tlb_flush(rdev);
+       if (rdev->gart.ptr) {
+               mb();
+               radeon_gart_tlb_flush(rdev);
+       }
 }
 
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
@@ -217,8 +219,10 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                        }
                }
        }
-       mb();
-       radeon_gart_tlb_flush(rdev);
+       if (rdev->gart.ptr) {
+               mb();
+               radeon_gart_tlb_flush(rdev);
+       }
        return 0;
 }
 
index 4f9496e..42f5a2b 100644 (file)
@@ -51,10 +51,12 @@ static void radeon_hotplug_work_func(struct work_struct *work)
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_connector *connector;
 
+       mutex_lock(&mode_config->mutex);
        if (mode_config->num_connector) {
                list_for_each_entry(connector, &mode_config->connector_list, head)
                        radeon_connector_hotplug(connector);
        }
+       mutex_unlock(&mode_config->mutex);
        /* Just fire off a uevent and let userspace tell us what to do */
        drm_helper_hpd_irq_event(dev);
 }
index 64d79d2..61660f8 100644 (file)
@@ -1295,7 +1295,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
                "Multi-Axis Controller"
        };
        const char *type, *bus;
-       char buf[64];
+       char buf[64] = "";
        unsigned int i;
        int len;
        int ret;
index 44a1ea4..a7e6f03 100644 (file)
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto error0;
+               goto error_gpadl;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto error0;
+               goto error_gpadl;
        }
 
        if (userdatalen)
@@ -234,6 +234,9 @@ error1:
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+error_gpadl:
+       vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
+
 error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
index 12b85ff..7f96332 100644 (file)
@@ -606,7 +606,7 @@ int vmbus_request_offers(void)
 {
        struct vmbus_channel_message_header *msg;
        struct vmbus_channel_msginfo *msginfo;
-       int ret, t;
+       int ret;
 
        msginfo = kmalloc(sizeof(*msginfo) +
                          sizeof(struct vmbus_channel_message_header),
@@ -614,8 +614,6 @@ int vmbus_request_offers(void)
        if (!msginfo)
                return -ENOMEM;
 
-       init_completion(&msginfo->waitevent);
-
        msg = (struct vmbus_channel_message_header *)msginfo->msg;
 
        msg->msgtype = CHANNELMSG_REQUESTOFFERS;
@@ -629,14 +627,6 @@ int vmbus_request_offers(void)
                goto cleanup;
        }
 
-       t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-       if (t == 0) {
-               ret = -ETIMEDOUT;
-               goto cleanup;
-       }
-
-
-
 cleanup:
        kfree(msginfo);
 
index 8b72f39..722a893 100644 (file)
@@ -856,6 +856,11 @@ retest:
        case IB_CM_SIDR_REQ_RCVD:
                spin_unlock_irq(&cm_id_priv->lock);
                cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
+               spin_lock_irq(&cm.lock);
+               if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+                       rb_erase(&cm_id_priv->sidr_id_node,
+                                &cm.remote_sidr_table);
+               spin_unlock_irq(&cm.lock);
                break;
        case IB_CM_REQ_SENT:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
@@ -3092,7 +3097,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
        spin_lock_irqsave(&cm.lock, flags);
-       rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+       if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
+               rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+               RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
+       }
        spin_unlock_irqrestore(&cm.lock, flags);
        return 0;
 
index 055ebeb..c1fef27 100644 (file)
@@ -94,12 +94,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        if (dmasync)
                dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
+       if (!size)
+               return ERR_PTR(-EINVAL);
+
        /*
         * If the combination of the addr and size requested for this memory
         * region causes an integer overflow, return error.
         */
-       if ((PAGE_ALIGN(addr + size) <= size) ||
-           (PAGE_ALIGN(addr + size) <= addr))
+       if (((addr + size) < addr) ||
+           PAGE_ALIGN(addr + size) < (addr + size))
                return ERR_PTR(-EINVAL);
 
        if (!can_do_mlock())
index 5bcb2af..228af18 100644 (file)
@@ -69,7 +69,7 @@
  */
 
 struct ib_uverbs_device {
-       struct kref                             ref;
+       atomic_t                                refcount;
        int                                     num_comp_vectors;
        struct completion                       comp;
        struct device                          *dev;
@@ -78,6 +78,7 @@ struct ib_uverbs_device {
        struct cdev                             cdev;
        struct rb_root                          xrcd_tree;
        struct mutex                            xrcd_tree_mutex;
+       struct kobject                          kobj;
 };
 
 struct ib_uverbs_event_file {
index a8445b8..3be21aa 100644 (file)
@@ -1979,6 +1979,12 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                next->send_flags = user_wr->send_flags;
 
                if (is_ud) {
+                       if (next->opcode != IB_WR_SEND &&
+                           next->opcode != IB_WR_SEND_WITH_IMM) {
+                               ret = -EINVAL;
+                               goto out_put;
+                       }
+
                        next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
                                                     file->ucontext);
                        if (!next->wr.ud.ah) {
@@ -2015,9 +2021,11 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                                        user_wr->wr.atomic.compare_add;
                                next->wr.atomic.swap = user_wr->wr.atomic.swap;
                                next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
+                       case IB_WR_SEND:
                                break;
                        default:
-                               break;
+                               ret = -EINVAL;
+                               goto out_put;
                        }
                }
 
index 9379b97..f07c6e3 100644 (file)
@@ -117,14 +117,18 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device);
 
-static void ib_uverbs_release_dev(struct kref *ref)
+static void ib_uverbs_release_dev(struct kobject *kobj)
 {
        struct ib_uverbs_device *dev =
-               container_of(ref, struct ib_uverbs_device, ref);
+               container_of(kobj, struct ib_uverbs_device, kobj);
 
-       complete(&dev->comp);
+       kfree(dev);
 }
 
+static struct kobj_type ib_uverbs_dev_ktype = {
+       .release = ib_uverbs_release_dev,
+};
+
 static void ib_uverbs_release_event_file(struct kref *ref)
 {
        struct ib_uverbs_event_file *file =
@@ -273,13 +277,19 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        return context->device->dealloc_ucontext(context);
 }
 
+static void ib_uverbs_comp_dev(struct ib_uverbs_device *dev)
+{
+       complete(&dev->comp);
+}
+
 static void ib_uverbs_release_file(struct kref *ref)
 {
        struct ib_uverbs_file *file =
                container_of(ref, struct ib_uverbs_file, ref);
 
        module_put(file->device->ib_dev->owner);
-       kref_put(&file->device->ref, ib_uverbs_release_dev);
+       if (atomic_dec_and_test(&file->device->refcount))
+               ib_uverbs_comp_dev(file->device);
 
        kfree(file);
 }
@@ -621,9 +631,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        int ret;
 
        dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
-       if (dev)
-               kref_get(&dev->ref);
-       else
+       if (!atomic_inc_not_zero(&dev->refcount))
                return -ENXIO;
 
        if (!try_module_get(dev->ib_dev->owner)) {
@@ -644,6 +652,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        mutex_init(&file->mutex);
 
        filp->private_data = file;
+       kobject_get(&dev->kobj);
 
        return nonseekable_open(inode, filp);
 
@@ -651,13 +660,16 @@ err_module:
        module_put(dev->ib_dev->owner);
 
 err:
-       kref_put(&dev->ref, ib_uverbs_release_dev);
+       if (atomic_dec_and_test(&dev->refcount))
+               ib_uverbs_comp_dev(dev);
+
        return ret;
 }
 
 static int ib_uverbs_close(struct inode *inode, struct file *filp)
 {
        struct ib_uverbs_file *file = filp->private_data;
+       struct ib_uverbs_device *dev = file->device;
 
        ib_uverbs_cleanup_ucontext(file, file->ucontext);
 
@@ -665,6 +677,7 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
                kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
 
        kref_put(&file->ref, ib_uverbs_release_file);
+       kobject_put(&dev->kobj);
 
        return 0;
 }
@@ -760,10 +773,11 @@ static void ib_uverbs_add_one(struct ib_device *device)
        if (!uverbs_dev)
                return;
 
-       kref_init(&uverbs_dev->ref);
+       atomic_set(&uverbs_dev->refcount, 1);
        init_completion(&uverbs_dev->comp);
        uverbs_dev->xrcd_tree = RB_ROOT;
        mutex_init(&uverbs_dev->xrcd_tree_mutex);
+       kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
 
        spin_lock(&map_lock);
        devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -790,6 +804,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
        cdev_init(&uverbs_dev->cdev, NULL);
        uverbs_dev->cdev.owner = THIS_MODULE;
        uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+       uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj;
        kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
        if (cdev_add(&uverbs_dev->cdev, base, 1))
                goto err_cdev;
@@ -820,9 +835,10 @@ err_cdev:
                clear_bit(devnum, overflow_map);
 
 err:
-       kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+       if (atomic_dec_and_test(&uverbs_dev->refcount))
+               ib_uverbs_comp_dev(uverbs_dev);
        wait_for_completion(&uverbs_dev->comp);
-       kfree(uverbs_dev);
+       kobject_put(&uverbs_dev->kobj);
        return;
 }
 
@@ -842,9 +858,10 @@ static void ib_uverbs_remove_one(struct ib_device *device)
        else
                clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
 
-       kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+       if (atomic_dec_and_test(&uverbs_dev->refcount))
+               ib_uverbs_comp_dev(uverbs_dev);
        wait_for_completion(&uverbs_dev->comp);
-       kfree(uverbs_dev);
+       kobject_put(&uverbs_dev->kobj);
 }
 
 static char *uverbs_devnode(struct device *dev, mode_t *mode)
index 4b8f9c4..5426ccf 100644 (file)
@@ -169,9 +169,13 @@ int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
        enum rdma_link_layer ll;
 
        memset(ah_attr, 0, sizeof *ah_attr);
-       ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
        ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
        ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
+       if (ll == IB_LINK_LAYER_ETHERNET)
+               ah_attr->sl = be32_to_cpu(ah->av.eth.sl_tclass_flowlabel) >> 29;
+       else
+               ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+
        ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
        if (ah->av.ib.stat_rate)
                ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
index a16f0c8..2ed14a7 100644 (file)
@@ -1670,8 +1670,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
 
        memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
 
-       *lso_hdr_sz  = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
-                                  wr->wr.ud.hlen);
+       *lso_hdr_sz  = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
        *lso_seg_len = halign;
        return 0;
 }
index 4c2b079..c0b72a6 100644 (file)
@@ -1421,6 +1421,10 @@ extern struct mutex qib_mutex;
                        qib_get_unit_name((dd)->unit), ##__VA_ARGS__); \
        } while (0)
 
+#define qib_dev_warn(dd, fmt, ...) \
+       dev_warn(&(dd)->pcidev->dev, "%s: " fmt, \
+               qib_get_unit_name((dd)->unit), ##__VA_ARGS__)
+
 #define qib_dev_porterr(dd, port, fmt, ...) \
        do { \
                dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \
index 8fd19a4..ca6e6cf 100644 (file)
@@ -69,6 +69,10 @@ int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr)
         * unrestricted LKEY.
         */
        rkt->gen++;
+       /*
+        * bits are capped in qib_verbs.c to insure enough bits
+        * for generation number
+        */
        mr->lkey = (r << (32 - ib_qib_lkey_table_size)) |
                ((((1 << (24 - ib_qib_lkey_table_size)) - 1) & rkt->gen)
                 << 8);
index a894762..c51a6f9 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/rculist.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/vmalloc.h>
 
 #include "qib.h"
 #include "qib_common.h"
@@ -2035,10 +2036,16 @@ int qib_register_ib_device(struct qib_devdata *dd)
         * the LKEY).  The remaining bits act as a generation number or tag.
         */
        spin_lock_init(&dev->lk_table.lock);
+       /* insure generation is at least 4 bits see keys.c */
+       if (ib_qib_lkey_table_size > MAX_LKEY_TABLE_BITS) {
+               qib_dev_warn(dd, "lkey bits %u too large, reduced to %u\n",
+                       ib_qib_lkey_table_size, MAX_LKEY_TABLE_BITS);
+               ib_qib_lkey_table_size = MAX_LKEY_TABLE_BITS;
+       }
        dev->lk_table.max = 1 << ib_qib_lkey_table_size;
        lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
        dev->lk_table.table = (struct qib_mregion **)
-               __get_free_pages(GFP_KERNEL, get_order(lk_tab_size));
+               vmalloc(lk_tab_size);
        if (dev->lk_table.table == NULL) {
                ret = -ENOMEM;
                goto err_lk;
@@ -2208,7 +2215,7 @@ err_tx:
                                        sizeof(struct qib_pio_header),
                                  dev->pio_hdrs, dev->pio_hdrs_phys);
 err_hdrs:
-       free_pages((unsigned long) dev->lk_table.table, get_order(lk_tab_size));
+       vfree(dev->lk_table.table);
 err_lk:
        kfree(dev->qp_table);
 err_qpt:
@@ -2262,7 +2269,6 @@ void qib_unregister_ib_device(struct qib_devdata *dd)
                                        sizeof(struct qib_pio_header),
                                  dev->pio_hdrs, dev->pio_hdrs_phys);
        lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
-       free_pages((unsigned long) dev->lk_table.table,
-                  get_order(lk_tab_size));
+       vfree(dev->lk_table.table);
        kfree(dev->qp_table);
 }
index 0c19ef0..66f7f62 100644 (file)
@@ -622,6 +622,8 @@ struct qib_qpn_table {
        struct qpn_map map[QPNMAP_ENTRIES];
 };
 
+#define MAX_LKEY_TABLE_BITS 23
+
 struct qib_lkey_table {
        spinlock_t lock; /* protect changes in this struct */
        u32 next;               /* next unused index (speeds search) */
index 4cf2534..f55a3cf 100644 (file)
@@ -126,19 +126,14 @@ static int evdev_flush(struct file *file, fl_owner_t id)
 {
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
-       int retval;
 
-       retval = mutex_lock_interruptible(&evdev->mutex);
-       if (retval)
-               return retval;
+       mutex_lock(&evdev->mutex);
 
-       if (!evdev->exist)
-               retval = -ENODEV;
-       else
-               retval = input_flush_device(&evdev->handle, file);
+       if (evdev->exist)
+               input_flush_device(&evdev->handle, file);
 
        mutex_unlock(&evdev->mutex);
-       return retval;
+       return 0;
 }
 
 static void evdev_free(struct device *dev)
index 2d5bb5b..548ea99 100644 (file)
@@ -296,7 +296,7 @@ static void elantech_report_semi_mt_data(struct input_dev *dev,
                                         unsigned int x2, unsigned int y2)
 {
        elantech_set_slot(dev, 0, num_fingers != 0, x1, y1);
-       elantech_set_slot(dev, 1, num_fingers == 2, x2, y2);
+       elantech_set_slot(dev, 1, num_fingers >= 2, x2, y2);
 }
 
 /*
@@ -692,18 +692,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
 static int elantech_packet_check_v4(struct psmouse *psmouse)
 {
        unsigned char *packet = psmouse->packet;
+       unsigned char packet_type = packet[3] & 0x03;
 
-       if ((packet[0] & 0x0c) == 0x04 &&
-           (packet[3] & 0x1f) == 0x11)
+       switch (packet_type) {
+       case 0:
+               return PACKET_V4_STATUS;
+
+       case 1:
                return PACKET_V4_HEAD;
 
-       if ((packet[0] & 0x0c) == 0x04 &&
-           (packet[3] & 0x1f) == 0x12)
+       case 2:
                return PACKET_V4_MOTION;
-
-       if ((packet[0] & 0x0c) == 0x04 &&
-           (packet[3] & 0x1f) == 0x10)
-               return PACKET_V4_STATUS;
+       }
 
        return PACKET_UNKNOWN;
 }
@@ -765,6 +765,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
        return PSMOUSE_FULL_PACKET;
 }
 
+/*
+ * This writes the reg_07 value again to the hardware at the end of every
+ * set_rate call because the register loses its value. reg_07 allows setting
+ * absolute mode on v4 hardware
+ */
+static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse,
+               unsigned int rate)
+{
+       struct elantech_data *etd = psmouse->private;
+
+       etd->original_set_rate(psmouse, rate);
+       if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+               psmouse_err(psmouse, "restoring reg_07 failed\n");
+}
+
 /*
  * Put the touchpad into absolute mode
  */
@@ -1131,10 +1146,11 @@ static bool elantech_is_signature_valid(const unsigned char *param)
                return true;
 
        /*
-        * Some models have a revision higher then 20. Meaning param[2] may
-        * be 10 or 20, skip the rates check for these.
+        * Some hw_version >= 4 models have a revision higher then 20. Meaning
+        * that param[2] may be 10 or 20, skip the rates check for these.
         */
-       if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
+       if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f &&
+           param[2] < 40)
                return true;
 
        for (i = 0; i < ARRAY_SIZE(rates); i++)
@@ -1269,6 +1285,12 @@ static int elantech_set_properties(struct elantech_data *etd)
                        etd->hw_version = 3;
                        break;
                case 6:
+               case 7:
+               case 8:
+               case 9:
+               case 10:
+               case 13:
+               case 14:
                        etd->hw_version = 4;
                        break;
                default:
@@ -1353,6 +1375,11 @@ int elantech_init(struct psmouse *psmouse)
                goto init_fail;
        }
 
+       if (etd->fw_version == 0x381f17) {
+               etd->original_set_rate = psmouse->set_rate;
+               psmouse->set_rate = elantech_set_rate_restore_reg_07;
+       }
+
        if (elantech_set_input_params(psmouse)) {
                psmouse_err(psmouse, "failed to query touchpad range.\n");
                goto init_fail;
index 3569bed..092ac72 100644 (file)
@@ -136,6 +136,7 @@ struct elantech_data {
        unsigned int width;
        struct finger_pos mt[ETP_MAX_FINGERS];
        unsigned char parity[256];
+       void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
 };
 
 #ifdef CONFIG_MOUSE_PS2_ELANTECH
index 73fd664..e26a7c3 100644 (file)
@@ -528,6 +528,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
                goto err_out;
        }
 
+       /* TSC-25 data sheet specifies a delay after the RESET command */
+       msleep(150);
+
        /* set coordinate output rate */
        buf[0] = buf[1] = 0xFF;
        ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
index d3da166..41b7464 100644 (file)
@@ -1798,13 +1798,20 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
                                return -ENOMEM;
                        /* It is large page*/
                        if (largepage_lvl > 1) {
+                               unsigned long nr_superpages, end_pfn, lvl_pages;
+
                                pteval |= DMA_PTE_LARGE_PAGE;
-                               /* Ensure that old small page tables are removed to make room
-                                  for superpage, if they exist. */
-                               dma_pte_clear_range(domain, iov_pfn,
-                                                   iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
-                               dma_pte_free_pagetable(domain, iov_pfn,
-                                                      iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
+                               lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+                               nr_superpages = sg_res / lvl_pages;
+                               end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
+
+                               /*
+                                * Ensure that old small page tables are
+                                * removed to make room for superpage(s).
+                                */
+                               dma_pte_clear_range(domain, iov_pfn, end_pfn);
+                               dma_pte_free_pagetable(domain, iov_pfn, end_pfn);
                        } else {
                                pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
                        }
@@ -3565,10 +3572,15 @@ found:
        for (bus = dev->bus; bus; bus = bus->parent) {
                struct pci_dev *bridge = bus->self;
 
-               if (!bridge || !pci_is_pcie(bridge) ||
+               /* If it's an integrated device, allow ATS */
+               if (!bridge)
+                       return 1;
+               /* Connected via non-PCIe: no ATS */
+               if (!pci_is_pcie(bridge) ||
                    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
                        return 0;
 
+               /* If we found the root port, look it up in the ATSR */
                if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
                        for (i = 0; i < atsru->devices_cnt; i++)
                                if (atsru->devices[i] == bridge)
index b5fdcb7..34842e5 100644 (file)
@@ -171,7 +171,7 @@ static void unmap_switcher(void)
 bool lguest_address_ok(const struct lguest *lg,
                       unsigned long addr, unsigned long len)
 {
-       return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
+       return addr+len <= lg->pfn_limit * PAGE_SIZE && (addr+len >= addr);
 }
 
 /*
index ce88979..004fa10 100644 (file)
@@ -421,7 +421,7 @@ int wf_unregister_client(struct notifier_block *nb)
 {
        mutex_lock(&wf_lock);
        blocking_notifier_chain_unregister(&wf_client_list, nb);
-       wf_client_count++;
+       wf_client_count--;
        if (wf_client_count == 0)
                wf_stop_thread();
        mutex_unlock(&wf_lock);
index 80f8bd5..d9f23a4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #define        DM_MSG_PREFIX   "thin"
 
@@ -158,9 +159,7 @@ static struct bio_prison *prison_create(unsigned nr_cells)
 {
        unsigned i;
        uint32_t nr_buckets = calc_nr_buckets(nr_cells);
-       size_t len = sizeof(struct bio_prison) +
-               (sizeof(struct hlist_head) * nr_buckets);
-       struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
+       struct bio_prison *prison = kmalloc(sizeof(*prison), GFP_KERNEL);
 
        if (!prison)
                return NULL;
@@ -173,9 +172,15 @@ static struct bio_prison *prison_create(unsigned nr_cells)
                return NULL;
        }
 
+       prison->cells = vmalloc(sizeof(*prison->cells) * nr_buckets);
+       if (!prison->cells) {
+               mempool_destroy(prison->cell_pool);
+               kfree(prison);
+               return NULL;
+       }
+
        prison->nr_buckets = nr_buckets;
        prison->hash_mask = nr_buckets - 1;
-       prison->cells = (struct hlist_head *) (prison + 1);
        for (i = 0; i < nr_buckets; i++)
                INIT_HLIST_HEAD(prison->cells + i);
 
@@ -184,6 +189,7 @@ static struct bio_prison *prison_create(unsigned nr_cells)
 
 static void prison_destroy(struct bio_prison *prison)
 {
+       vfree(prison->cells);
        mempool_destroy(prison->cell_pool);
        kfree(prison);
 }
index ea8a181..0914534 100644 (file)
@@ -5384,9 +5384,9 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg)
        int err = -ENOMEM;
 
        if (md_allow_write(mddev))
-               file = kmalloc(sizeof(*file), GFP_NOIO);
+               file = kzalloc(sizeof(*file), GFP_NOIO);
        else
-               file = kmalloc(sizeof(*file), GFP_KERNEL);
+               file = kzalloc(sizeof(*file), GFP_KERNEL);
 
        if (!file)
                goto out;
@@ -7895,6 +7895,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
                /* Make sure they get written out promptly */
                sysfs_notify_dirent_safe(rdev->sysfs_state);
                set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
+               set_bit(MD_CHANGE_PENDING, &rdev->mddev->flags);
                md_wakeup_thread(rdev->mddev->thread);
        }
        return rv;
index acba54e..f8458ca 100644 (file)
@@ -134,4 +134,10 @@ int lower_bound(struct btree_node *n, uint64_t key);
 
 extern struct dm_block_validator btree_node_validator;
 
+/*
+ * Value type for upper levels of multi-level btrees.
+ */
+extern void init_le64_type(struct dm_transaction_manager *tm,
+                          struct dm_btree_value_type *vt);
+
 #endif /* DM_BTREE_INTERNAL_H */
index 1de0f5f..f77692b 100644 (file)
@@ -301,35 +301,40 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
 {
        int s;
        uint32_t max_entries = le32_to_cpu(left->header.max_entries);
-       unsigned target = (nr_left + nr_center + nr_right) / 3;
-       BUG_ON(target > max_entries);
+       unsigned total = nr_left + nr_center + nr_right;
+       unsigned target_right = total / 3;
+       unsigned remainder = (target_right * 3) != total;
+       unsigned target_left = target_right + remainder;
+
+       BUG_ON(target_left > max_entries);
+       BUG_ON(target_right > max_entries);
 
        if (nr_left < nr_right) {
-               s = nr_left - target;
+               s = nr_left - target_left;
 
                if (s < 0 && nr_center < -s) {
                        /* not enough in central node */
-                       shift(left, center, nr_center);
-                       s = nr_center - target;
+                       shift(left, center, -nr_center);
+                       s += nr_center;
                        shift(left, right, s);
                        nr_right += s;
                } else
                        shift(left, center, s);
 
-               shift(center, right, target - nr_right);
+               shift(center, right, target_right - nr_right);
 
        } else {
-               s = target - nr_right;
+               s = target_right - nr_right;
                if (s > 0 && nr_center < s) {
                        /* not enough in central node */
                        shift(center, right, nr_center);
-                       s = target - nr_center;
+                       s -= nr_center;
                        shift(left, right, s);
                        nr_left -= s;
                } else
                        shift(center, right, s);
 
-               shift(left, center, nr_left - target);
+               shift(left, center, nr_left - target_left);
        }
 
        *key_ptr(parent, c->index) = center->keys[0];
@@ -544,14 +549,6 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
        return r;
 }
 
-static struct dm_btree_value_type le64_type = {
-       .context = NULL,
-       .size = sizeof(__le64),
-       .inc = NULL,
-       .dec = NULL,
-       .equal = NULL
-};
-
 int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
                    uint64_t *keys, dm_block_t *new_root)
 {
@@ -559,12 +556,14 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
        int index = 0, r = 0;
        struct shadow_spine spine;
        struct btree_node *n;
+       struct dm_btree_value_type le64_vt;
 
+       init_le64_type(info->tm, &le64_vt);
        init_shadow_spine(&spine, info);
        for (level = 0; level < info->levels; level++) {
                r = remove_raw(&spine, info,
                               (level == last_level ?
-                               &info->value_type : &le64_type),
+                               &info->value_type : &le64_vt),
                               root, keys[level], (unsigned *)&index);
                if (r < 0)
                        break;
index 2f0805c..f6cb762 100644 (file)
@@ -242,3 +242,40 @@ int shadow_root(struct shadow_spine *s)
 {
        return s->root;
 }
+
+static void le64_inc(void *context, void *value_le)
+{
+       struct dm_transaction_manager *tm = context;
+       __le64 v_le;
+
+       memcpy(&v_le, value_le, sizeof(v_le));
+       dm_tm_inc(tm, le64_to_cpu(v_le));
+}
+
+static void le64_dec(void *context, void *value_le)
+{
+       struct dm_transaction_manager *tm = context;
+       __le64 v_le;
+
+       memcpy(&v_le, value_le, sizeof(v_le));
+       dm_tm_dec(tm, le64_to_cpu(v_le));
+}
+
+static int le64_equal(void *context, void *value1_le, void *value2_le)
+{
+       __le64 v1_le, v2_le;
+
+       memcpy(&v1_le, value1_le, sizeof(v1_le));
+       memcpy(&v2_le, value2_le, sizeof(v2_le));
+       return v1_le == v2_le;
+}
+
+void init_le64_type(struct dm_transaction_manager *tm,
+                   struct dm_btree_value_type *vt)
+{
+       vt->context = tm;
+       vt->size = sizeof(__le64);
+       vt->inc = le64_inc;
+       vt->dec = le64_dec;
+       vt->equal = le64_equal;
+}
index bbb2ec5..29e423f 100644 (file)
@@ -236,7 +236,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
        int r;
        struct del_stack *s;
 
-       s = kmalloc(sizeof(*s), GFP_KERNEL);
+       s = kmalloc(sizeof(*s), GFP_NOIO);
        if (!s)
                return -ENOMEM;
        s->tm = info->tm;
@@ -503,7 +503,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        r = new_block(s->info, &right);
        if (r < 0) {
-               /* FIXME: put left */
+               unlock_block(s->info, left);
                return r;
        }
 
@@ -647,12 +647,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
        struct btree_node *n;
        struct dm_btree_value_type le64_type;
 
-       le64_type.context = NULL;
-       le64_type.size = sizeof(__le64);
-       le64_type.inc = NULL;
-       le64_type.dec = NULL;
-       le64_type.equal = NULL;
-
+       init_le64_type(info->tm, &le64_type);
        init_shadow_spine(&spine, info);
 
        for (level = 0; level < (info->levels - 1); level++) {
index d3e6f35..c0b4a21 100644 (file)
@@ -88,6 +88,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        char b[BDEVNAME_SIZE];
        char b2[BDEVNAME_SIZE];
        struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+       unsigned short blksize = 512;
 
        if (!conf)
                return -ENOMEM;
@@ -102,6 +103,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
                sector_div(sectors, mddev->chunk_sectors);
                rdev1->sectors = sectors * mddev->chunk_sectors;
 
+               blksize = max(blksize, queue_logical_block_size(
+                                     rdev1->bdev->bd_disk->queue));
+
                list_for_each_entry(rdev2, &mddev->disks, same_set) {
                        pr_debug("md/raid0:%s:   comparing %s(%llu)"
                                 " with %s(%llu)\n",
@@ -138,6 +142,18 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        }
        pr_debug("md/raid0:%s: FINAL %d zones\n",
                 mdname(mddev), conf->nr_strip_zones);
+       /*
+        * now since we have the hard sector sizes, we can make sure
+        * chunk size is a multiple of that sector size
+        */
+       if ((mddev->chunk_sectors << 9) % blksize) {
+               printk(KERN_ERR "md/raid0:%s: chunk_size of %d not multiple of block size %d\n",
+                      mdname(mddev),
+                      mddev->chunk_sectors << 9, blksize);
+               err = -EINVAL;
+               goto abort;
+       }
+
        err = -ENOMEM;
        conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
                                conf->nr_strip_zones, GFP_KERNEL);
@@ -186,8 +202,6 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
                }
                dev[j] = rdev1;
 
-               disk_stack_limits(mddev->gendisk, rdev1->bdev,
-                                 rdev1->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_segments to 1, lying within
                 * a single page.
@@ -263,21 +277,6 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        mddev->queue->backing_dev_info.congested_fn = raid0_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
 
-       /*
-        * now since we have the hard sector sizes, we can make sure
-        * chunk size is a multiple of that sector size
-        */
-       if ((mddev->chunk_sectors << 9) % queue_logical_block_size(mddev->queue)) {
-               printk(KERN_ERR "md/raid0:%s: chunk_size of %d not valid\n",
-                      mdname(mddev),
-                      mddev->chunk_sectors << 9);
-               goto abort;
-       }
-
-       blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
-       blk_queue_io_opt(mddev->queue,
-                        (mddev->chunk_sectors << 9) * mddev->raid_disks);
-
        pr_debug("md/raid0:%s: done.\n", mdname(mddev));
        *private_conf = conf;
 
@@ -340,6 +339,7 @@ static int raid0_run(struct mddev *mddev)
 {
        struct r0conf *conf;
        int ret;
+       struct md_rdev *rdev;
 
        if (mddev->chunk_sectors == 0) {
                printk(KERN_ERR "md/raid0:%s: chunk size must be set.\n",
@@ -348,7 +348,6 @@ static int raid0_run(struct mddev *mddev)
        }
        if (md_check_no_bitmap(mddev))
                return -EINVAL;
-       blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
 
        /* if private is not null, we are here after takeover */
        if (mddev->private == NULL) {
@@ -359,6 +358,17 @@ static int raid0_run(struct mddev *mddev)
        }
        conf = mddev->private;
 
+       blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
+
+       blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
+       blk_queue_io_opt(mddev->queue,
+                        (mddev->chunk_sectors << 9) * mddev->raid_disks);
+
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
+       }
+
        /* calculate array device size */
        md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
 
index aec029a..5c8dd40 100644 (file)
@@ -313,7 +313,7 @@ static void raid1_end_read_request(struct bio *bio, int error)
                spin_lock_irqsave(&conf->device_lock, flags);
                if (r1_bio->mddev->degraded == conf->raid_disks ||
                    (r1_bio->mddev->degraded == conf->raid_disks-1 &&
-                    !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags)))
+                    test_bit(In_sync, &conf->mirrors[mirror].rdev->flags)))
                        uptodate = 1;
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
@@ -1208,6 +1208,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
        char b[BDEVNAME_SIZE];
        struct r1conf *conf = mddev->private;
+       unsigned long flags;
 
        /*
         * If it is not operational, then we have already marked it as dead
@@ -1227,19 +1228,19 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
                return;
        }
        set_bit(Blocked, &rdev->flags);
+       spin_lock_irqsave(&conf->device_lock, flags);
        if (test_and_clear_bit(In_sync, &rdev->flags)) {
-               unsigned long flags;
-               spin_lock_irqsave(&conf->device_lock, flags);
                mddev->degraded++;
                set_bit(Faulty, &rdev->flags);
-               spin_unlock_irqrestore(&conf->device_lock, flags);
        } else
                set_bit(Faulty, &rdev->flags);
+       spin_unlock_irqrestore(&conf->device_lock, flags);
        /*
         * if recovery is running, make sure it aborts.
         */
        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
+       set_bit(MD_CHANGE_PENDING, &mddev->flags);
        printk(KERN_ALERT
               "md/raid1:%s: Disk failure on %s, disabling device.\n"
               "md/raid1:%s: Operation continuing on %d devices.\n",
@@ -1292,7 +1293,10 @@ static int raid1_spare_active(struct mddev *mddev)
         * Find all failed disks within the RAID1 configuration 
         * and mark them readable.
         * Called under mddev lock, so rcu protection not needed.
+        * device_lock used to avoid races with raid1_end_read_request
+        * which expects 'In_sync' flags and ->degraded to be consistent.
         */
+       spin_lock_irqsave(&conf->device_lock, flags);
        for (i = 0; i < conf->raid_disks; i++) {
                struct md_rdev *rdev = conf->mirrors[i].rdev;
                if (rdev
@@ -1302,7 +1306,6 @@ static int raid1_spare_active(struct mddev *mddev)
                        sysfs_notify_dirent_safe(rdev->sysfs_state);
                }
        }
-       spin_lock_irqsave(&conf->device_lock, flags);
        mddev->degraded -= count;
        spin_unlock_irqrestore(&conf->device_lock, flags);
 
@@ -1947,6 +1950,7 @@ static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio
 static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
 {
        int m;
+       bool fail = false;
        for (m = 0; m < conf->raid_disks ; m++)
                if (r1_bio->bios[m] == IO_MADE_GOOD) {
                        struct md_rdev *rdev = conf->mirrors[m].rdev;
@@ -1959,6 +1963,7 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
                         * narrow down and record precise write
                         * errors.
                         */
+                       fail = true;
                        if (!narrow_write_error(r1_bio, m)) {
                                md_error(conf->mddev,
                                         conf->mirrors[m].rdev);
@@ -1968,9 +1973,16 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
                        rdev_dec_pending(conf->mirrors[m].rdev,
                                         conf->mddev);
                }
-       if (test_bit(R1BIO_WriteError, &r1_bio->state))
-               close_write(r1_bio);
-       raid_end_bio_io(r1_bio);
+       if (fail) {
+               spin_lock_irq(&conf->device_lock);
+               list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
+               spin_unlock_irq(&conf->device_lock);
+               md_wakeup_thread(conf->mddev->thread);
+       } else {
+               if (test_bit(R1BIO_WriteError, &r1_bio->state))
+                       close_write(r1_bio);
+               raid_end_bio_io(r1_bio);
+       }
 }
 
 static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
@@ -2073,6 +2085,27 @@ static void raid1d(struct mddev *mddev)
 
        md_check_recovery(mddev);
 
+       if (!list_empty_careful(&conf->bio_end_io_list) &&
+           !test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+               LIST_HEAD(tmp);
+               spin_lock_irqsave(&conf->device_lock, flags);
+               if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+                       list_add(&tmp, &conf->bio_end_io_list);
+                       list_del_init(&conf->bio_end_io_list);
+               }
+               spin_unlock_irqrestore(&conf->device_lock, flags);
+               while (!list_empty(&tmp)) {
+                       r1_bio = list_first_entry(&conf->bio_end_io_list,
+                                                 struct r1bio, retry_list);
+                       list_del(&r1_bio->retry_list);
+                       if (mddev->degraded)
+                               set_bit(R1BIO_Degraded, &r1_bio->state);
+                       if (test_bit(R1BIO_WriteError, &r1_bio->state))
+                               close_write(r1_bio);
+                       raid_end_bio_io(r1_bio);
+               }
+       }
+
        blk_start_plug(&plug);
        for (;;) {
 
@@ -2471,6 +2504,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
        conf->raid_disks = mddev->raid_disks;
        conf->mddev = mddev;
        INIT_LIST_HEAD(&conf->retry_list);
+       INIT_LIST_HEAD(&conf->bio_end_io_list);
 
        spin_lock_init(&conf->resync_lock);
        init_waitqueue_head(&conf->wait_barrier);
index c732b6c..6fbd3a9 100644 (file)
@@ -43,6 +43,11 @@ struct r1conf {
         * block, or anything else.
         */
        struct list_head        retry_list;
+       /* A separate list of r1bio which just need raid_end_bio_io called.
+        * This mustn't happen for writes which had any errors if the superblock
+        * needs to be written.
+        */
+       struct list_head        bio_end_io_list;
 
        /* queue pending writes to be submitted on unplug */
        struct bio_list         pending_bio_list;
index abac83a..922b70b 100644 (file)
@@ -1280,6 +1280,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
        set_bit(Blocked, &rdev->flags);
        set_bit(Faulty, &rdev->flags);
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
+       set_bit(MD_CHANGE_PENDING, &mddev->flags);
        printk(KERN_ALERT
               "md/raid10:%s: Disk failure on %s, disabling device.\n"
               "md/raid10:%s: Operation continuing on %d devices.\n",
@@ -2215,6 +2216,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                }
                put_buf(r10_bio);
        } else {
+               bool fail = false;
                for (m = 0; m < conf->copies; m++) {
                        int dev = r10_bio->devs[m].devnum;
                        struct bio *bio = r10_bio->devs[m].bio;
@@ -2227,6 +2229,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                                rdev_dec_pending(rdev, conf->mddev);
                        } else if (bio != NULL &&
                                   !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+                               fail = true;
                                if (!narrow_write_error(r10_bio, m)) {
                                        md_error(conf->mddev, rdev);
                                        set_bit(R10BIO_Degraded,
@@ -2235,10 +2238,17 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                                rdev_dec_pending(rdev, conf->mddev);
                        }
                }
-               if (test_bit(R10BIO_WriteError,
-                            &r10_bio->state))
-                       close_write(r10_bio);
-               raid_end_bio_io(r10_bio);
+               if (fail) {
+                       spin_lock_irq(&conf->device_lock);
+                       list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
+                       spin_unlock_irq(&conf->device_lock);
+                       md_wakeup_thread(conf->mddev->thread);
+               } else {
+                       if (test_bit(R10BIO_WriteError,
+                                    &r10_bio->state))
+                               close_write(r10_bio);
+                       raid_end_bio_io(r10_bio);
+               }
        }
 }
 
@@ -2252,6 +2262,29 @@ static void raid10d(struct mddev *mddev)
 
        md_check_recovery(mddev);
 
+       if (!list_empty_careful(&conf->bio_end_io_list) &&
+           !test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+               LIST_HEAD(tmp);
+               spin_lock_irqsave(&conf->device_lock, flags);
+               if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+                       list_add(&tmp, &conf->bio_end_io_list);
+                       list_del_init(&conf->bio_end_io_list);
+               }
+               spin_unlock_irqrestore(&conf->device_lock, flags);
+               while (!list_empty(&tmp)) {
+                       r10_bio = list_first_entry(&conf->bio_end_io_list,
+                                                 struct r10bio, retry_list);
+                       list_del(&r10_bio->retry_list);
+                       if (mddev->degraded)
+                               set_bit(R10BIO_Degraded, &r10_bio->state);
+
+                       if (test_bit(R10BIO_WriteError,
+                                    &r10_bio->state))
+                               close_write(r10_bio);
+                       raid_end_bio_io(r10_bio);
+               }
+       }
+
        blk_start_plug(&plug);
        for (;;) {
 
@@ -2860,6 +2893,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
 
        spin_lock_init(&conf->device_lock);
        INIT_LIST_HEAD(&conf->retry_list);
+       INIT_LIST_HEAD(&conf->bio_end_io_list);
 
        spin_lock_init(&conf->resync_lock);
        init_waitqueue_head(&conf->wait_barrier);
index 7facfdf..64b0164 100644 (file)
@@ -40,6 +40,12 @@ struct r10conf {
        sector_t chunk_mask;
 
        struct list_head        retry_list;
+       /* A separate list of r1bio which just need raid_end_bio_io called.
+        * This mustn't happen for writes which had any errors if the superblock
+        * needs to be written.
+        */
+       struct list_head        bio_end_io_list;
+
        /* queue pending writes and submit them on unplug */
        struct bio_list         pending_bio_list;
        int                     pending_count;
index c293d9c..6056ee7 100644 (file)
@@ -1554,7 +1554,8 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 
        conf->slab_cache = sc;
        conf->active_name = 1-conf->active_name;
-       conf->pool_size = newsize;
+       if (!err)
+               conf->pool_size = newsize;
        return err;
 }
 
index ccd0525..4ff6d15 100644 (file)
@@ -963,6 +963,10 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
        struct cx24116_state *state = fe->demodulator_priv;
        int i, ret;
 
+       /* Validate length */
+       if (d->msg_len > sizeof(d->msg))
+                return -EINVAL;
+
        /* Dump DiSEqC message */
        if (debug) {
                printk(KERN_INFO "cx24116: %s(", __func__);
@@ -974,10 +978,6 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
                printk(") toneburst=%d\n", toneburst);
        }
 
-       /* Validate length */
-       if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
-               return -EINVAL;
-
        /* DiSEqC message */
        for (i = 0; i < d->msg_len; i++)
                state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
index 3879d2e..507ccae 100644 (file)
@@ -180,7 +180,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
        int result = 0;
 
        dprintk("enter %s\n", __func__);
-       if (cmd->msg_len > 8)
+       if (cmd->msg_len > sizeof(cmd->msg))
                return -EINVAL;
 
        /* setup for DISEQC */
index a47ba33..2be51c8 100644 (file)
@@ -945,9 +945,6 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 {
        struct rc_dev *dev = to_rc_dev(device);
 
-       if (!dev || !dev->input_dev)
-               return -ENODEV;
-
        if (dev->rc_map.name)
                ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
        if (dev->driver_name)
index 9729b92..f8449d5 100644 (file)
@@ -760,7 +760,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
 
                if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
                        if (msb->data_dir == READ) {
-                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                               for (cnt = 0; cnt < msb->current_seg; cnt++) {
                                        t_len += msb->req_sg[cnt].length
                                                 / msb->page_size;
 
@@ -768,6 +768,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
                                                t_len += msb->current_page - 1;
 
                                        t_len *= msb->page_size;
+                               }
                        }
                } else
                        t_len = blk_rq_bytes(msb->block_req);
index 8f258a1..ef08f7b 100644 (file)
@@ -1273,9 +1273,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                        break;
                case MMC_BLK_CMD_ERR:
                        ret = mmc_blk_cmd_err(md, card, brq, req, ret);
-                       if (!mmc_blk_reset(md, card->host, type))
-                               break;
-                       goto cmd_abort;
+                       if (mmc_blk_reset(md, card->host, type))
+                               goto cmd_abort;
+                       if (!ret)
+                               goto start_new_req;
+                       break;
                case MMC_BLK_RETRY:
                        if (retry++ < 5)
                                break;
index 23d944f..4dd99b2 100644 (file)
@@ -2469,6 +2469,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+       case PM_RESTORE_PREPARE:
 
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 1;
index f43b365..9af1528 100644 (file)
@@ -38,9 +38,9 @@ static void nw_en_write(void)
         * we want to write a bit pattern XXX1 to Xilinx to enable
         * the write gate, which will be open for about the next 2ms.
         */
-       spin_lock_irqsave(&nw_gpio_lock, flags);
+       raw_spin_lock_irqsave(&nw_gpio_lock, flags);
        nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
-       spin_unlock_irqrestore(&nw_gpio_lock, flags);
+       raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 
        /*
         * let the ISA bus to catch on...
index 424ca5f..05613bf 100644 (file)
@@ -213,6 +213,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
        if (!dev)
                return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
+       mutex_lock(&mtd_table_mutex);
        mutex_lock(&dev->lock);
 
        if (dev->open)
@@ -237,6 +238,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 unlock:
        dev->open++;
        mutex_unlock(&dev->lock);
+       mutex_unlock(&mtd_table_mutex);
        blktrans_dev_put(dev);
        return ret;
 
@@ -247,6 +249,7 @@ error_put:
        module_put(dev->tr->owner);
        kref_put(&dev->ref, blktrans_dev_release);
        mutex_unlock(&dev->lock);
+       mutex_unlock(&mtd_table_mutex);
        blktrans_dev_put(dev);
        return ret;
 }
@@ -259,6 +262,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
        if (!dev)
                return ret;
 
+       mutex_lock(&mtd_table_mutex);
        mutex_lock(&dev->lock);
 
        if (--dev->open)
@@ -273,6 +277,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
        }
 unlock:
        mutex_unlock(&dev->lock);
+       mutex_unlock(&mtd_table_mutex);
        blktrans_dev_put(dev);
        return ret;
 }
index 198da0a..3aab083 100644 (file)
@@ -671,8 +671,10 @@ int add_mtd_partitions(struct mtd_info *master,
 
        for (i = 0; i < nbparts; i++) {
                slave = allocate_partition(master, parts + i, i, cur_offset);
-               if (IS_ERR(slave))
+               if (IS_ERR(slave)) {
+                       del_mtd_partitions(master);
                        return PTR_ERR(slave);
+               }
 
                mutex_lock(&mtd_partitions_mutex);
                list_add(&slave->list, &mtd_partitions);
index da13215..1cb642b 100644 (file)
@@ -413,7 +413,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
                second_is_newer = !second_is_newer;
        } else {
                dbg_bld("PEB %d CRC is OK", pnum);
-               bitflips = !!err;
+               bitflips |= !!err;
        }
 
        vfree(buf);
index 175c627..1408b67 100644 (file)
@@ -475,7 +475,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
                /* Validate the request */
                err = -EINVAL;
                if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
-                   req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+                   req.bytes < 0 || req.bytes > vol->usable_leb_size)
                        break;
 
                err = get_exclusive(desc);
index a26d7d2..9ca92fa 100644 (file)
@@ -1254,7 +1254,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                                 * during re-size.
                                 */
                                ubi_move_aeb_to_list(av, aeb, &ai->erase);
-                       vol->eba_tbl[aeb->lnum] = aeb->pnum;
+                       else
+                               vol->eba_tbl[aeb->lnum] = aeb->pnum;
                }
        }
 
index 515d4fd..67f46f8 100644 (file)
@@ -932,6 +932,11 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
                goto bad;
        }
 
+       if (data_size > ubi->leb_size) {
+               ubi_err("bad data_size");
+               goto bad;
+       }
+
        if (vol_type == UBI_VID_STATIC) {
                /*
                 * Although from high-level point of view static volumes may
index f6a7d7a..b14ab43 100644 (file)
@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
        for (i = 0; i < vol->used_ebs; i++) {
                int size;
 
+               cond_resched();
+
                if (i == vol->used_ebs - 1)
                        size = vol->last_eb_bytes;
                else
index 926e3df..dccfced 100644 (file)
@@ -651,6 +651,7 @@ static int init_volumes(struct ubi_device *ubi,
                if (ubi->corr_peb_count)
                        ubi_err("%d PEBs are corrupted and not used",
                                ubi->corr_peb_count);
+               return -ENOSPC;
        }
        ubi->rsvd_pebs += reserved_pebs;
        ubi->avail_pebs -= reserved_pebs;
index 1c7cc88..e8db4cb 100644 (file)
@@ -626,7 +626,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                                int cancel)
 {
        int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
-       int vol_id = -1, uninitialized_var(lnum);
+       int vol_id = -1, lnum = -1;
        struct ubi_wl_entry *e1, *e2;
        struct ubi_vid_hdr *vid_hdr;
 
@@ -1499,6 +1499,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                if (ubi->corr_peb_count)
                        ubi_err("%d PEBs are corrupted and not used",
                                ubi->corr_peb_count);
+               err = -ENOSPC;
                goto out_free;
        }
        ubi->avail_pebs -= WL_RESERVED_PEBS;
index 5af2a8f..9145834 100644 (file)
@@ -861,6 +861,23 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
        }
 }
 
+static struct slave *bond_get_old_active(struct bonding *bond,
+                                        struct slave *new_active)
+{
+       struct slave *slave;
+       int i;
+
+       bond_for_each_slave(bond, slave, i) {
+               if (slave == new_active)
+                       continue;
+
+               if (!compare_ether_addr(bond->dev->dev_addr, slave->dev->dev_addr))
+                       return slave;
+       }
+
+       return NULL;
+}
+
 /*
  * bond_do_fail_over_mac
  *
@@ -898,6 +915,9 @@ static void bond_do_fail_over_mac(struct bonding *bond,
                write_unlock_bh(&bond->curr_slave_lock);
                read_unlock(&bond->lock);
 
+               if (!old_active)
+                       old_active = bond_get_old_active(bond, new_active);
+
                if (old_active) {
                        memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN);
                        memcpy(saddr.sa_data, old_active->dev->dev_addr,
index db9100f..664263a 100644 (file)
@@ -693,7 +693,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
        NLA_PUT_U32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms);
        NLA_PUT(skb, IFLA_CAN_BITTIMING,
                sizeof(priv->bittiming), &priv->bittiming);
-       NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock);
+       NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock);
        if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec))
                NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec);
        if (priv->bittiming_const)
index 6546191..bd4e598 100644 (file)
@@ -149,6 +149,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                                     struct e1000_rx_ring *rx_ring,
                                     int *work_done, int work_to_do);
+static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter,
+                                        struct e1000_rx_ring *rx_ring,
+                                        int cleaned_count)
+{
+}
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
                                   struct e1000_rx_ring *rx_ring,
                                   int cleaned_count);
@@ -3322,8 +3327,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                msleep(1);
        /* e1000_down has a dependency on max_frame_size */
        hw->max_frame_size = max_frame;
-       if (netif_running(netdev))
+       if (netif_running(netdev)) {
+               /* prevent buffers from being reallocated */
+               adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers;
                e1000_down(adapter);
+       }
 
        /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
         * means we reserve 2 more, this pushes us to allocate from the next
index 9820ec8..e93a0bf 100644 (file)
@@ -153,6 +153,8 @@ struct dma_desc {
                        u32 buffer2_size:13;
                        u32 reserved4:3;
                } etx;          /* -- enhanced -- */
+
+               u64 all_flags;
        } des01;
        unsigned int des2;
        unsigned int des3;
index d879763..73e647b 100644 (file)
@@ -232,6 +232,7 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
 {
        int i;
        for (i = 0; i < ring_size; i++) {
+               p->des01.all_flags = 0;
                p->des01.erx.own = 1;
                p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
 
@@ -248,7 +249,7 @@ static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
        int i;
 
        for (i = 0; i < ring_size; i++) {
-               p->des01.etx.own = 0;
+               p->des01.all_flags = 0;
                ehn_desc_tx_set_on_ring_chain(p, (i == ring_size - 1));
                p++;
        }
index fda5d2b..5bf9c37 100644 (file)
@@ -126,6 +126,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
 {
        int i;
        for (i = 0; i < ring_size; i++) {
+               p->des01.all_flags = 0;
                p->des01.rx.own = 1;
                p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
 
@@ -141,7 +142,7 @@ static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
 {
        int i;
        for (i = 0; i < ring_size; i++) {
-               p->des01.tx.own = 0;
+               p->des01.all_flags = 0;
                ndesc_tx_set_on_ring_chain(p, (i == (ring_size - 1)));
                p++;
        }
index d4d2bc1..05852e3 100644 (file)
@@ -441,19 +441,17 @@ static void init_dma_desc_rings(struct net_device *dev)
        priv->rx_skbuff =
            kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL);
        priv->dma_rx =
-           (struct dma_desc *)dma_alloc_coherent(priv->device,
-                                                 rxsize *
-                                                 sizeof(struct dma_desc),
-                                                 &priv->dma_rx_phy,
-                                                 GFP_KERNEL);
+           (struct dma_desc *)dma_zalloc_coherent(priv->device, rxsize *
+                                                  sizeof(struct dma_desc),
+                                                  &priv->dma_rx_phy,
+                                                  GFP_KERNEL);
        priv->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * txsize,
                                       GFP_KERNEL);
        priv->dma_tx =
-           (struct dma_desc *)dma_alloc_coherent(priv->device,
-                                                 txsize *
-                                                 sizeof(struct dma_desc),
-                                                 &priv->dma_tx_phy,
-                                                 GFP_KERNEL);
+           (struct dma_desc *)dma_zalloc_coherent(priv->device, txsize *
+                                                  sizeof(struct dma_desc),
+                                                  &priv->dma_tx_phy,
+                                                  GFP_KERNEL);
 
        if ((priv->dma_rx == NULL) || (priv->dma_tx == NULL)) {
                pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__);
index 73c7081..c646a49 100644 (file)
@@ -6670,10 +6670,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
                struct sk_buff *skb_new;
 
                skb_new = skb_realloc_headroom(skb, len);
-               if (!skb_new) {
-                       rp->tx_errors++;
+               if (!skb_new)
                        goto out_drop;
-               }
                kfree_skb(skb);
                skb = skb_new;
        } else
index 9663e0b..bb335ab 100644 (file)
@@ -42,7 +42,7 @@
 #define PSF_TX         0x1000
 #define EXT_EVENT      1
 #define CAL_EVENT      7
-#define CAL_TRIGGER    7
+#define CAL_TRIGGER    1
 #define PER_TRIGGER    6
 
 /* phyter seems to miss the mark by 16 ns */
index 2f319d1..0f4a04d 100644 (file)
@@ -319,7 +319,6 @@ static void pppoe_flush_dev(struct net_device *dev)
                        if (po->pppoe_dev == dev &&
                            sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                                pppox_unbind_sock(sk);
-                               sk->sk_state = PPPOX_ZOMBIE;
                                sk->sk_state_change(sk);
                                po->pppoe_dev = NULL;
                                dev_put(dev);
@@ -576,7 +575,7 @@ static int pppoe_release(struct socket *sock)
 
        po = pppox_sk(sk);
 
-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+       if (po->pppoe_dev) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }
index fb5e8c3..6b3de64 100644 (file)
@@ -1132,19 +1132,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                return ret;
        }
 
-       ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
-       if (ret < 0)
-               return ret;
-
-       msleep(150);
-
-       ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
-       if (ret < 0)
-               return ret;
-
-       msleep(150);
-
-       ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE);
+       ax88772_reset(dev);
 
        /* Read PHYID register *AFTER* the PHY was reset properly */
        phyid = asix_get_phyid(dev);
@@ -1555,7 +1543,7 @@ static const struct driver_info ax88772_info = {
        .unbind = ax88772_unbind,
        .status = asix_status,
        .link_reset = ax88772_link_reset,
-       .reset = ax88772_reset,
+       .reset = ax88772_link_reset,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
        .rx_fixup = asix_rx_fixup_common,
        .tx_fixup = asix_tx_fixup,
index f13a673..715e5c4 100644 (file)
@@ -981,9 +981,9 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* Do we support "hardware" checksums? */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
                /* This opens up the world of extra features. */
-               dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+               dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
                if (csum)
-                       dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+                       dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
 
                if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
                        dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
index 1355d71..ca60256 100644 (file)
@@ -708,6 +708,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->max_rate_tries = 10;
        hw->sta_data_size = sizeof(struct ath_node);
        hw->vif_data_size = sizeof(struct ath_vif);
+       hw->extra_tx_headroom = 4;
 
        hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
        hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
index ad33126..8d64c16 100644 (file)
@@ -235,7 +235,7 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       bool ret;
+       bool ret = true;
 
        ieee80211_stop_queues(sc->hw);
 
@@ -245,10 +245,13 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
        ath9k_debug_samp_bb_mac(sc);
        ath9k_hw_disable_interrupts(ah);
 
-       ret = ath_drain_all_txq(sc, retry_tx);
-
-       if (!ath_stoprecv(sc))
-               ret = false;
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ret &= ath_stoprecv(sc);
+               ret &= ath_drain_all_txq(sc, retry_tx);
+       } else {
+               ret &= ath_drain_all_txq(sc, retry_tx);
+               ret &= ath_stoprecv(sc);
+       }
 
        if (!flush) {
                if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
index 4a36973..e0b0391 100644 (file)
@@ -2001,7 +2001,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
                        u8 *pn = seq.ccmp.pn;
 
                        ieee80211_get_key_rx_seq(key, i, &seq);
-                       aes_sc->pn = cpu_to_le64(
+                       aes_sc[i].pn = cpu_to_le64(
                                        (u64)pn[5] |
                                        ((u64)pn[4] << 8) |
                                        ((u64)pn[3] << 16) |
index d26a78b..1c0e1a4 100644 (file)
@@ -633,7 +633,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
                (struct mwifiex_private *) file->private_data;
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
        char *buf = (char *) addr;
-       int pos = 0, ret = 0, i;
+       int pos, ret, i;
        u8 value[MAX_EEPROM_DATA];
 
        if (!buf)
@@ -641,7 +641,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
 
        if (saved_offset == -1) {
                /* No command has been given */
-               pos += snprintf(buf, PAGE_SIZE, "0");
+               pos = snprintf(buf, PAGE_SIZE, "0");
                goto done;
        }
 
@@ -650,17 +650,17 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
                                  (u16) saved_bytes, value);
        if (ret) {
                ret = -EINVAL;
-               goto done;
+               goto out_free;
        }
 
-       pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
+       pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
 
        for (i = 0; i < saved_bytes; i++)
-               pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]);
-
-       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+               pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
 
 done:
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+out_free:
        free_page(addr);
        return ret;
 }
index 1644b1f..e813eff 100644 (file)
@@ -313,6 +313,8 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
        {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+       {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/
+       {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
        {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
        {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
        {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
@@ -367,6 +369,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+       {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */
        {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
        {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
        {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
index e5fe956..17e6429 100644 (file)
@@ -117,7 +117,7 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
        reqtype =  REALTEK_USB_VENQT_READ;
 
        status = usb_control_msg(udev, pipe, request, reqtype, value, index,
-                                pdata, len, 0); /* max. timeout */
+                                pdata, len, 1000);
 
        if (status < 0)
                pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
index 1ce729d..b7d782f 100644 (file)
@@ -27,6 +27,8 @@ struct backend_info {
        enum xenbus_state frontend_state;
        struct xenbus_watch hotplug_status_watch;
        u8 have_hotplug_status_watch:1;
+
+       const char *hotplug_script;
 };
 
 static int connect_rings(struct backend_info *);
@@ -45,6 +47,7 @@ static int netback_remove(struct xenbus_device *dev)
                xenvif_disconnect(be->vif);
                be->vif = NULL;
        }
+       kfree(be->hotplug_script);
        kfree(be);
        dev_set_drvdata(&dev->dev, NULL);
        return 0;
@@ -62,6 +65,7 @@ static int netback_probe(struct xenbus_device *dev,
        struct xenbus_transaction xbt;
        int err;
        int sg;
+       const char *script;
        struct backend_info *be = kzalloc(sizeof(struct backend_info),
                                          GFP_KERNEL);
        if (!be) {
@@ -122,6 +126,15 @@ static int netback_probe(struct xenbus_device *dev,
                goto fail;
        }
 
+       script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL);
+       if (IS_ERR(script)) {
+               err = PTR_ERR(script);
+               xenbus_dev_fatal(dev, err, "reading script");
+               goto fail;
+       }
+
+       be->hotplug_script = script;
+
        err = xenbus_switch_state(dev, XenbusStateInitWait);
        if (err)
                goto fail;
@@ -150,22 +163,14 @@ static int netback_uevent(struct xenbus_device *xdev,
                          struct kobj_uevent_env *env)
 {
        struct backend_info *be = dev_get_drvdata(&xdev->dev);
-       char *val;
 
-       val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
-       if (IS_ERR(val)) {
-               int err = PTR_ERR(val);
-               xenbus_dev_fatal(xdev, err, "reading script");
-               return err;
-       } else {
-               if (add_uevent_var(env, "script=%s", val)) {
-                       kfree(val);
-                       return -ENOMEM;
-               }
-               kfree(val);
-       }
+       if (!be)
+               return 0;
+
+       if (add_uevent_var(env, "script=%s", be->hotplug_script))
+               return -ENOMEM;
 
-       if (!be || !be->vif)
+       if (!be->vif)
                return 0;
 
        return add_uevent_var(env, "vif=%s", be->vif->dev->name);
index 53a613f..39016a0 100644 (file)
@@ -604,10 +604,10 @@ struct device_node *of_find_matching_node_by_address(struct device_node *from,
        struct resource res;
 
        while (dn) {
-               if (of_address_to_resource(dn, 0, &res))
-                       continue;
-               if (res.start == base_address)
+               if (!of_address_to_resource(dn, 0, &res) &&
+                   res.start == base_address)
                        return dn;
+
                dn = of_find_matching_node(dn, matches);
        }
 
index 37639a6..2193558 100644 (file)
@@ -761,6 +761,42 @@ int of_property_read_string_index(struct device_node *np, const char *propname,
 }
 EXPORT_SYMBOL_GPL(of_property_read_string_index);
 
+/**
+ * of_property_match_string() - Find string in a list and return index
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ */
+int of_property_match_string(struct device_node *np, const char *propname,
+                            const char *string)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       size_t l;
+       int i;
+       const char *p, *end;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+
+       p = prop->value;
+       end = p + prop->length;
+
+       for (i = 0; p < end; i++, p += l) {
+               l = strlen(p) + 1;
+               if (p + l > end)
+                       return -EILSEQ;
+               pr_debug("comparing %s with %s\n", string, p);
+               if (strcmp(string, p) == 0)
+                       return i; /* Found it; return index */
+       }
+       return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_match_string);
 
 /**
  * of_property_count_strings - Find and return the number of strings from a
index fdaa42a..32785cd 100644 (file)
@@ -355,6 +355,42 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
        .release = pci_vpd_pci22_release,
 };
 
+static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
+                              void *arg)
+{
+       struct pci_dev *tdev = pci_get_slot(dev->bus,
+                                           PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       ssize_t ret;
+
+       if (!tdev)
+               return -ENODEV;
+
+       ret = pci_read_vpd(tdev, pos, count, arg);
+       pci_dev_put(tdev);
+       return ret;
+}
+
+static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
+                               const void *arg)
+{
+       struct pci_dev *tdev = pci_get_slot(dev->bus,
+                                           PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       ssize_t ret;
+
+       if (!tdev)
+               return -ENODEV;
+
+       ret = pci_write_vpd(tdev, pos, count, arg);
+       pci_dev_put(tdev);
+       return ret;
+}
+
+static const struct pci_vpd_ops pci_vpd_f0_ops = {
+       .read = pci_vpd_f0_read,
+       .write = pci_vpd_f0_write,
+       .release = pci_vpd_pci22_release,
+};
+
 int pci_vpd_pci22_init(struct pci_dev *dev)
 {
        struct pci_vpd_pci22 *vpd;
@@ -363,12 +399,16 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
        if (!cap)
                return -ENODEV;
+
        vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
        if (!vpd)
                return -ENOMEM;
 
        vpd->base.len = PCI_VPD_PCI22_SIZE;
-       vpd->base.ops = &pci_vpd_pci22_ops;
+       if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
+               vpd->base.ops = &pci_vpd_f0_ops;
+       else
+               vpd->base.ops = &pci_vpd_pci22_ops;
        mutex_init(&vpd->lock);
        vpd->cap = cap;
        vpd->busy = false;
index 481b184..604ee35 100644 (file)
@@ -1941,6 +1941,31 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
 
+/*
+ * Quirk non-zero PCI functions to route VPD access through function 0 for
+ * devices that share VPD resources between functions.  The functions are
+ * expected to be identical devices.
+ */
+static void quirk_f0_vpd_link(struct pci_dev *dev)
+{
+       struct pci_dev *f0;
+
+       if ((dev->class >> 8) != PCI_CLASS_NETWORK_ETHERNET ||
+           !PCI_FUNC(dev->devfn))
+               return;
+
+       f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       if (!f0)
+               return;
+
+       if (f0->vpd && dev->class == f0->class &&
+           dev->vendor == f0->vendor && dev->device == f0->device)
+               dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+
+       pci_dev_put(f0);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_f0_vpd_link);
+
 static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
 {
        u16 command, pmcsr;
@@ -2875,8 +2900,9 @@ static void __devinit fixup_ti816x_class(struct pci_dev* dev)
 {
        /* TI 816x devices do not have class code set when in PCIe boot mode */
        if (dev->class == PCI_CLASS_NOT_DEFINED) {
-               dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
-               dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+               dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8;
+               dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n",
+                        PCI_CLASS_NOT_DEFINED, dev->class);
        }
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
index 615a45a..582688f 100644 (file)
 #define TOPIC_EXCA_IF_CONTROL          0x3e    /* 8 bit */
 #define TOPIC_EXCA_IFC_33V_ENA         0x01
 
+#define TOPIC_PCI_CFG_PPBCN            0x3e    /* 16-bit */
+#define TOPIC_PCI_CFG_PPBCN_WBEN       0x0400
+
 static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
 {
        struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
@@ -138,6 +141,7 @@ static int topic97_override(struct yenta_socket *socket)
 static int topic95_override(struct yenta_socket *socket)
 {
        u8 fctrl;
+       u16 ppbcn;
 
        /* enable 3.3V support for 16bit cards */
        fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
@@ -146,6 +150,18 @@ static int topic95_override(struct yenta_socket *socket)
        /* tell yenta to use exca registers to power 16bit cards */
        socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
 
+       /* Disable write buffers to prevent lockups under load with numerous
+          Cardbus cards, observed on Tecra 500CDT and reported elsewhere on the
+          net.  This is not a power-on default according to the datasheet
+          but some BIOSes seem to set it. */
+       if (pci_read_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, &ppbcn) == 0
+           && socket->dev->revision <= 7
+           && (ppbcn & TOPIC_PCI_CFG_PPBCN_WBEN)) {
+               ppbcn &= ~TOPIC_PCI_CFG_PPBCN_WBEN;
+               pci_write_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, ppbcn);
+               dev_info(&socket->dev->dev, "Disabled ToPIC95 Cardbus write buffers.\n");
+       }
+
        return 0;
 }
 
index 8877b83..ba3638e 100644 (file)
@@ -1046,7 +1046,14 @@ static int __devinit compal_probe(struct platform_device *pdev)
 
        /* Power supply */
        initialize_power_supply_data(data);
-       power_supply_register(&compal_device->dev, &data->psy);
+       err = power_supply_register(&compal_device->dev, &data->psy);
+       if (err < 0) {
+               hwmon_device_unregister(data->hwmon_dev);
+               sysfs_remove_group(&pdev->dev.kobj,
+                               &compal_attribute_group);
+               kfree(data);
+               return err;
+       }
 
        platform_set_drvdata(pdev, data);
 
index 1d3bcce..e57f5de 100644 (file)
@@ -215,7 +215,6 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {
 };
 
 static struct calling_interface_buffer *buffer;
-static struct page *bufferpage;
 static DEFINE_MUTEX(buffer_mutex);
 
 static int hwswitch_state;
@@ -715,11 +714,10 @@ static int __init dell_init(void)
         * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
         * is passed to SMI handler.
         */
-       bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32);
+       buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
 
-       if (!bufferpage)
+       if (!buffer)
                goto fail_buffer;
-       buffer = page_address(bufferpage);
 
        ret = dell_setup_rfkill();
 
@@ -788,7 +786,7 @@ fail_backlight:
 fail_filter:
        dell_cleanup_rfkill();
 fail_rfkill:
-       free_page((unsigned long)bufferpage);
+       free_page((unsigned long)buffer);
 fail_buffer:
        platform_device_del(platform_device);
 fail_platform_device2:
index a36addf..04a6928 100644 (file)
@@ -407,7 +407,8 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = {
 
 static int ideapad_rfk_set(void *data, bool blocked)
 {
-       unsigned long opcode = (unsigned long)data;
+       unsigned long dev = (unsigned long)data;
+       int opcode = ideapad_rfk_data[dev].opcode;
 
        return write_ec_cmd(ideapad_handle, opcode, !blocked);
 }
index 6cc2ca6..cbee41c 100644 (file)
@@ -557,7 +557,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "SYSLO");
        ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
-                                  IRQF_TRIGGER_RISING, "System power low",
+                                  IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low",
                                   power);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
@@ -567,7 +567,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "PWR SRC");
        ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
-                                  IRQF_TRIGGER_RISING, "Power source",
+                                  IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source",
                                   power);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n",
@@ -578,7 +578,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
        for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
                irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
                ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
-                                          IRQF_TRIGGER_RISING,
+                                          IRQF_TRIGGER_RISING | IRQF_ONESHOT,
                                           wm831x_bat_irqs[i],
                                           power);
                if (ret != 0) {
index adba3d6..2dd9838 100644 (file)
@@ -726,7 +726,7 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
 static void print_constraints(struct regulator_dev *rdev)
 {
        struct regulation_constraints *constraints = rdev->constraints;
-       char buf[80] = "";
+       char buf[160] = "";
        int count = 0;
        int ret;
 
index 3868ab2..d7a90c3 100644 (file)
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
 
 /* Functions */
 
@@ -226,6 +225,17 @@ static const struct file_operations twa_fops = {
        .llseek         = noop_llseek,
 };
 
+/*
+ * The controllers use an inline buffer instead of a mapped SGL for small,
+ * single entry buffers.  Note that we treat a zero-length transfer like
+ * a mapped SGL.
+ */
+static bool twa_command_mapped(struct scsi_cmnd *cmd)
+{
+       return scsi_sg_count(cmd) != 1 ||
+               scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
+}
+
 /* This function will complete an aen request from the isr */
 static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -1352,11 +1362,12 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
                                tw_dev->posted_request_count--;
-                               tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                               twa_unmap_scsi_data(tw_dev, request_id);
                        }
 
                        /* Check for valid status after each drain */
@@ -1414,26 +1425,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
        }
 } /* End twa_load_sgl() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twa_map_scsi_sg_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1612,9 +1603,12 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
                        if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twa_unmap_scsi_data(tw_dev, i);
+                               struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                               cmd->result = (DID_RESET << 16);
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1793,21 +1787,20 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                break;
        case 1:
-               tw_dev->state[request_id] = TW_S_COMPLETED;
-               twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                SCpnt->result = (DID_ERROR << 16);
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                done(SCpnt);
+               tw_dev->state[request_id] = TW_S_COMPLETED;
+               twa_free_request_id(tw_dev, request_id);
                retval = 0;
        }
 out:
@@ -1865,8 +1858,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                /* Map sglist from scsi layer to cmd packet */
 
                if (scsi_sg_count(srb)) {
-                       if ((scsi_sg_count(srb) == 1) &&
-                           (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+                       if (!twa_command_mapped(srb)) {
                                if (srb->sc_data_direction == DMA_TO_DEVICE ||
                                    srb->sc_data_direction == DMA_BIDIRECTIONAL)
                                        scsi_sg_copy_to_buffer(srb,
@@ -1875,8 +1867,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
-                               sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
-                               if (sg_count == 0)
+                               sg_count = scsi_dma_map(srb);
+                               if (sg_count < 0)
                                        goto out;
 
                                scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1939,7 +1931,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 {
        struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 
-       if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+       if (!twa_command_mapped(cmd) &&
            (cmd->sc_data_direction == DMA_FROM_DEVICE ||
             cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
                if (scsi_sg_count(cmd) == 1) {
@@ -1991,15 +1983,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
        return(table[index].text);
 } /* End twa_string_lookup() */
 
-/* This function will perform a pci-dma unmap */
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twa_unmap_scsi_data() */
-
 /* This function gets called when a disk is coming on-line */
 static int twa_slave_configure(struct scsi_device *sdev)
 {
index 040f721..0fdc83c 100644 (file)
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE  1
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_9550SX_DRAIN_COMPLETED            0xFFFF
 #define TW_SECTOR_SIZE                        512
index 13e39e1..c555ccb 100644 (file)
@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
        return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
        if (!sglistarg) {
                /* Map sglist from scsi layer to cmd packet */
                if (scsi_sg_count(srb)) {
-                       sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-                       if (sg_count == 0)
+                       sg_count = scsi_dma_map(srb);
+                       if (sg_count <= 0)
                                goto out;
 
                        scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1116,15 +1096,6 @@ out:
        return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance)
                        }
 
                        /* Now complete the io */
+                       scsi_dma_unmap(cmd);
+                       cmd->scsi_done(cmd);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
                        twl_free_request_id(tw_dev, request_id);
                        tw_dev->posted_request_count--;
-                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                       twl_unmap_scsi_data(tw_dev, request_id);
                }
 
                /* Check for another response interrupt */
@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
                if ((tw_dev->state[i] != TW_S_FINISHED) &&
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
-                       if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twl_unmap_scsi_data(tw_dev, i);
+                       struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                       if (cmd) {
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        if (retval) {
                tw_dev->state[request_id] = TW_S_COMPLETED;
index d474892..fec6449 100644 (file)
@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] =
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_SECTOR_SIZE                        512
 #define TW_MAX_UNITS                         32
index 7fe96ff..86bc5f9 100644 (file)
@@ -1283,32 +1283,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        return 0;
 } /* End tw_initialize_device_extension() */
 
-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int use_sg;
-
-       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-
-       use_sg = scsi_dma_map(cmd);
-       if (use_sg < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End tw_map_scsi_sg_data() */
-
-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End tw_unmap_scsi_data() */
-
 /* This function will reset a device extension */
 static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
 {
@@ -1331,8 +1305,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
                        srb = tw_dev->srb[i];
                        if (srb != NULL) {
                                srb->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
+                               scsi_dma_unmap(srb);
+                               srb->scsi_done(srb);
                        }
                }
        }
@@ -1779,8 +1753,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte8.io.lba = lba;
        command_packet->byte6.block_count = num_sectors;
 
-       use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-       if (!use_sg)
+       use_sg = scsi_dma_map(srb);
+       if (use_sg <= 0)
                return 1;
 
        scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
@@ -1967,9 +1941,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        switch (*command) {
                case READ_10:
                case READ_6:
@@ -2196,12 +2167,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
 
                                /* Now complete the io */
                                if ((error != TW_ISR_DONT_COMPLETE)) {
+                                       scsi_dma_unmap(tw_dev->srb[request_id]);
+                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        tw_dev->state[request_id] = TW_S_COMPLETED;
                                        tw_state_request_finish(tw_dev, request_id);
                                        tw_dev->posted_request_count--;
-                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                                       
-                                       tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
                                }
                        }
                                
index 49dcf03..1d31858 100644 (file)
@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] =
 #define TW_AEN_SMART_FAIL        0x000F
 #define TW_AEN_SBUF_FAIL         0x0024
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE 1
-#define TW_PHASE_SGLIST 2
-
 /* Misc defines */
 #define TW_ALIGNMENT_6000                    64 /* 64 bytes */
 #define TW_ALIGNMENT_7000                     4  /* 4 bytes */
index ac84736..a9932bd 100644 (file)
 #define IPR_RUNTIME_RESET                              0x40000000
 
 #define IPR_IPL_INIT_MIN_STAGE_TIME                    5
-#define IPR_IPL_INIT_DEFAULT_STAGE_TIME                 15
+#define IPR_IPL_INIT_DEFAULT_STAGE_TIME                 30
 #define IPR_IPL_INIT_STAGE_UNKNOWN                     0x0
 #define IPR_IPL_INIT_STAGE_TRANSOP                     0xB0000000
 #define IPR_IPL_INIT_STAGE_MASK                                0xff000000
index 221875e..735b324 100644 (file)
@@ -1029,11 +1029,26 @@ restart:
                fc_fcp_pkt_hold(fsp);
                spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 
-               if (!fc_fcp_lock_pkt(fsp)) {
+               spin_lock_bh(&fsp->scsi_pkt_lock);
+               if (!(fsp->state & FC_SRB_COMPL)) {
+                       fsp->state |= FC_SRB_COMPL;
+                       /*
+                        * TODO: dropping scsi_pkt_lock and then reacquiring
+                        * again around fc_fcp_cleanup_cmd() is required,
+                        * since fc_fcp_cleanup_cmd() calls into
+                        * fc_seq_set_resp() and that func preempts cpu using
+                        * schedule. May be schedule and related code should be
+                        * removed instead of unlocking here to avoid scheduling
+                        * while atomic bug.
+                        */
+                       spin_unlock_bh(&fsp->scsi_pkt_lock);
+
                        fc_fcp_cleanup_cmd(fsp, error);
+
+                       spin_lock_bh(&fsp->scsi_pkt_lock);
                        fc_io_compl(fsp);
-                       fc_fcp_unlock_pkt(fsp);
                }
+               spin_unlock_bh(&fsp->scsi_pkt_lock);
 
                fc_fcp_pkt_release(fsp);
                spin_lock_irqsave(&si->scsi_queue_lock, flags);
index 2794a30..8771c03 100644 (file)
@@ -2906,10 +2906,10 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
 {
        struct iscsi_conn *conn = cls_conn->dd_data;
        struct iscsi_session *session = conn->session;
-       unsigned long flags;
 
        del_timer_sync(&conn->transport_timer);
 
+       mutex_lock(&session->eh_mutex);
        spin_lock_bh(&session->lock);
        conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
        if (session->leadconn == conn) {
@@ -2921,28 +2921,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
        }
        spin_unlock_bh(&session->lock);
 
-       /*
-        * Block until all in-progress commands for this connection
-        * time out or fail.
-        */
-       for (;;) {
-               spin_lock_irqsave(session->host->host_lock, flags);
-               if (!session->host->host_busy) { /* OK for ERL == 0 */
-                       spin_unlock_irqrestore(session->host->host_lock, flags);
-                       break;
-               }
-               spin_unlock_irqrestore(session->host->host_lock, flags);
-               msleep_interruptible(500);
-               iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
-                                 "host_busy %d host_failed %d\n",
-                                 session->host->host_busy,
-                                 session->host->host_failed);
-               /*
-                * force eh_abort() to unblock
-                */
-               wake_up(&conn->ehwait);
-       }
-
        /* flush queued up work because we free the connection below */
        iscsi_suspend_tx(conn);
 
@@ -2955,6 +2933,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
        if (session->leadconn == conn)
                session->leadconn = NULL;
        spin_unlock_bh(&session->lock);
+       mutex_unlock(&session->eh_mutex);
 
        iscsi_destroy_conn(cls_conn);
 }
index 049c22f..458fb34 100644 (file)
@@ -300,6 +300,8 @@ enum MR_EVT_ARGS {
        MR_EVT_ARGS_GENERIC,
 };
 
+
+#define SGE_BUFFER_SIZE        4096
 /*
  * define constants for device list query options
  */
index e45c865..3b1ba10 100644 (file)
@@ -3636,7 +3636,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
        }
 
        instance->max_sectors_per_req = instance->max_num_sge *
-                                               PAGE_SIZE / 512;
+                                               SGE_BUFFER_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
@@ -5083,6 +5083,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
        int i;
        int error = 0;
        compat_uptr_t ptr;
+       unsigned long local_raw_ptr;
+       u32 local_sense_off;
+       u32 local_sense_len;
 
        if (clear_user(ioc, sizeof(*ioc)))
                return -EFAULT;
@@ -5100,9 +5103,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
         * sense_len is not null, so prepare the 64bit value under
         * the same condition.
         */
-       if (ioc->sense_len) {
+       if (get_user(local_raw_ptr, ioc->frame.raw) ||
+               get_user(local_sense_off, &ioc->sense_off) ||
+               get_user(local_sense_len, &ioc->sense_len))
+               return -EFAULT;
+
+
+       if (local_sense_len) {
                void __user **sense_ioc_ptr =
-                       (void __user **)(ioc->frame.raw + ioc->sense_off);
+                       (void __user **)((u8*)local_raw_ptr + local_sense_off);
                compat_uptr_t *sense_cioc_ptr =
                        (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
                if (get_user(ptr, sense_cioc_ptr) ||
index bfd87fa..3e0f71c 100644 (file)
@@ -1426,11 +1426,11 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                        fp_possible = io_info.fpOkForIo;
        }
 
-       /* Use smp_processor_id() for now until cmd->request->cpu is CPU
+       /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
           id by default, not CPU group id, otherwise all MSI-X queues won't
           be utilized */
        cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
-               smp_processor_id() % instance->msix_vectors : 0;
+               raw_smp_processor_id() % instance->msix_vectors : 0;
 
        if (fp_possible) {
                megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
index c6ad694..28b105c 100644 (file)
@@ -991,6 +991,8 @@ static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
 static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
                          struct mvs_slot_info *slot, u32 slot_idx)
 {
+       if (!slot)
+               return;
        if (!slot->task)
                return;
        if (!sas_protocol_ata(task->task_proto))
index 88bc82e..d76c347 100644 (file)
@@ -788,7 +788,7 @@ sdev_store_queue_ramp_up_period(struct device *dev,
                return -EINVAL;
 
        sdev->queue_ramp_up_period = msecs_to_jiffies(period);
-       return period;
+       return count;
 }
 
 static struct device_attribute sdev_attr_queue_ramp_up_period =
@@ -1029,31 +1029,23 @@ static void __scsi_remove_target(struct scsi_target *starget)
 void scsi_remove_target(struct device *dev)
 {
        struct Scsi_Host *shost = dev_to_shost(dev->parent);
-       struct scsi_target *starget, *last = NULL;
+       struct scsi_target *starget;
        unsigned long flags;
 
-       /* remove targets being careful to lookup next entry before
-        * deleting the last
-        */
+restart:
        spin_lock_irqsave(shost->host_lock, flags);
        list_for_each_entry(starget, &shost->__targets, siblings) {
                if (starget->state == STARGET_DEL)
                        continue;
                if (starget->dev.parent == dev || &starget->dev == dev) {
-                       /* assuming new targets arrive at the end */
                        kref_get(&starget->reap_ref);
                        spin_unlock_irqrestore(shost->host_lock, flags);
-                       if (last)
-                               scsi_target_reap(last);
-                       last = starget;
                        __scsi_remove_target(starget);
-                       spin_lock_irqsave(shost->host_lock, flags);
+                       scsi_target_reap(starget);
+                       goto restart;
                }
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
-
-       if (last)
-               scsi_target_reap(last);
 }
 EXPORT_SYMBOL(scsi_remove_target);
 
index 5c6b5f5..a50825b 100644 (file)
@@ -1338,6 +1338,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
 {
        u64 start_lba = blk_rq_pos(scmd->request);
        u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
+       u64 factor = scmd->device->sector_size / 512;
        u64 bad_lba;
        int info_valid;
        /*
@@ -1359,16 +1360,9 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
        if (scsi_bufflen(scmd) <= scmd->device->sector_size)
                return 0;
 
-       if (scmd->device->sector_size < 512) {
-               /* only legitimate sector_size here is 256 */
-               start_lba <<= 1;
-               end_lba <<= 1;
-       } else {
-               /* be careful ... don't want any overflows */
-               u64 factor = scmd->device->sector_size / 512;
-               do_div(start_lba, factor);
-               do_div(end_lba, factor);
-       }
+       /* be careful ... don't want any overflows */
+       do_div(start_lba, factor);
+       do_div(end_lba, factor);
 
        /* The bad lba was reported incorrectly, we have no idea where
         * the error is.
@@ -1895,8 +1889,7 @@ got_data:
        if (sector_size != 512 &&
            sector_size != 1024 &&
            sector_size != 2048 &&
-           sector_size != 4096 &&
-           sector_size != 256) {
+           sector_size != 4096) {
                sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n",
                          sector_size);
                /*
@@ -1945,8 +1938,6 @@ got_data:
                sdkp->capacity <<= 2;
        else if (sector_size == 1024)
                sdkp->capacity <<= 1;
-       else if (sector_size == 256)
-               sdkp->capacity >>= 1;
 
        blk_queue_physical_block_size(sdp->request_queue,
                                      sdkp->physical_block_size);
index 2d25616..b4cac39 100644 (file)
@@ -1687,6 +1687,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
                        md->from_user = 0;
        }
 
+       if (unlikely(iov_count > UIO_MAXIOV))
+               return -EINVAL;
+
        if (iov_count) {
                int len, size = sizeof(struct sg_iovec) * iov_count;
                struct iovec *iov;
index dc25bee..2ecc2d6 100644 (file)
@@ -799,6 +799,10 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
        if (!(sccr1_reg & SSCR1_TIE))
                mask &= ~SSSR_TFS;
 
+       /* Ignore RX timeout interrupt if it is disabled */
+       if (!(sccr1_reg & SSCR1_TINTE))
+               mask &= ~SSSR_TINT;
+
        if (!(status & mask))
                return IRQ_NONE;
 
index c43a9e8..54ef3d4 100644 (file)
@@ -940,23 +940,24 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
                        if (bounce_sgl[j].length == PAGE_SIZE) {
                                /* full..move to next entry */
                                kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+                               bounce_addr = 0;
                                j++;
+                       }
 
-                               /* if we need to use another bounce buffer */
-                               if (srclen || i != orig_sgl_count - 1)
-                                       bounce_addr =
+                       /* if we need to use another bounce buffer */
+                       if (srclen && bounce_addr == 0)
+                               bounce_addr =
                                        (unsigned long)kmap_atomic(
                                        sg_page((&bounce_sgl[j])), KM_IRQ0);
 
-                       } else if (srclen == 0 && i == orig_sgl_count - 1) {
-                               /* unmap the last bounce that is < PAGE_SIZE */
-                               kunmap_atomic((void *)bounce_addr, KM_IRQ0);
-                       }
                }
 
                kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
        }
 
+       if (bounce_addr)
+               kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+
        local_irq_restore(flags);
 
        return total_copied;
index 4a9a01d..9e86c1c 100644 (file)
@@ -120,7 +120,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
        if (ret)
                goto error_ret;
 
-       for (i = 0; i < num_read; i++)
+       for (i = 0; i < num_read / sizeof(u16); i++)
                *(((u16 *)rx) + i) = be16_to_cpup((u16 *)rx + i);
 
        if (copy_to_user(buf, rx, num_read))
index 284d879..8e81fce 100644 (file)
@@ -49,7 +49,7 @@ static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
 };
 
 static int ad5624r_spi_write(struct spi_device *spi,
-                            u8 cmd, u8 addr, u16 val, u8 len)
+                            u8 cmd, u8 addr, u16 val, u8 shift)
 {
        u32 data;
        u8 msg[3];
@@ -62,7 +62,7 @@ static int ad5624r_spi_write(struct spi_device *spi,
         * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits,
         * for the AD5664R, AD5644R, and AD5624R, respectively.
         */
-       data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len));
+       data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift);
        msg[0] = data >> 16;
        msg[1] = data >> 8;
        msg[2] = data;
index 2d3a420..955c6de 100644 (file)
@@ -88,10 +88,13 @@ static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
 
 int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
 {
-       unsigned long flags_old =
-           __sync_fetch_and_or(&line6pcm->flags, channels);
-       unsigned long flags_new = flags_old | channels;
-       int err = 0;
+       unsigned long flags_old, flags_new;
+       int err;
+
+       do {
+               flags_old = ACCESS_ONCE(line6pcm->flags);
+               flags_new = flags_old | channels;
+       } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
 
 #if LINE6_BACKUP_MONITOR_SIGNAL
        if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {
@@ -133,10 +136,8 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
                line6pcm->prev_fsize = 0;
                err = line6_submit_audio_in_all_urbs(line6pcm);
 
-               if (err < 0) {
-                       __sync_fetch_and_and(&line6pcm->flags, ~channels);
-                       return err;
-               }
+               if (err < 0)
+                       goto fail;
        }
 
        if (((flags_old & MASK_PLAYBACK) == 0) &&
@@ -160,20 +161,29 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
                line6pcm->count_out = 0;
                err = line6_submit_audio_out_all_urbs(line6pcm);
 
-               if (err < 0) {
-                       __sync_fetch_and_and(&line6pcm->flags, ~channels);
-                       return err;
-               }
+               if (err < 0)
+                       goto fail;
        }
 
        return 0;
+
+fail:
+       do {
+               flags_old = ACCESS_ONCE(line6pcm->flags);
+               flags_new = flags_old & ~channels;
+       } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
+
+       return err;
 }
 
 int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
 {
-       unsigned long flags_old =
-           __sync_fetch_and_and(&line6pcm->flags, ~channels);
-       unsigned long flags_new = flags_old & ~channels;
+       unsigned long flags_old, flags_new;
+
+       do {
+               flags_old = ACCESS_ONCE(line6pcm->flags);
+               flags_new = flags_old & ~channels;
+       } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
 
        if (((flags_old & MASK_CAPTURE) != 0) &&
            ((flags_new & MASK_CAPTURE) == 0)) {
index 4683d5f..9a584da 100644 (file)
@@ -274,11 +274,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
  * LCD types
  */
 #define LCD_TYPE_NONE          0
-#define LCD_TYPE_OLD           1
-#define LCD_TYPE_KS0074                2
-#define LCD_TYPE_HANTRONIX     3
-#define LCD_TYPE_NEXCOM                4
-#define LCD_TYPE_CUSTOM                5
+#define LCD_TYPE_CUSTOM                1
+#define LCD_TYPE_OLD           2
+#define LCD_TYPE_KS0074                3
+#define LCD_TYPE_HANTRONIX     4
+#define LCD_TYPE_NEXCOM                5
 
 /*
  * keypad types
@@ -456,8 +456,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-                "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-                "3=hantronix //, 4=nexcom //, 5=compiled-in");
+                "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
index 6d69265..a33bece 100644 (file)
@@ -1076,7 +1076,8 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
                /* for first fragment packet, driver need allocate 1536 +
                 * drvinfo_sz + RXDESC_SIZE to defrag packet. */
                if ((mf == 1) && (frag == 0))
-                       alloc_sz = 1658;/*1658+6=1664, 1664 is 128 alignment.*/
+                       /*1658+6=1664, 1664 is 128 alignment.*/
+                       alloc_sz = max_t(u16, tmp_len, 1658);
                else
                        alloc_sz = tmp_len;
                /* 2 is for IP header 4 bytes alignment in QoS packet case.
index a74e83d..6381393 100644 (file)
@@ -147,6 +147,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
        {USB_DEVICE(0x0DF6, 0x0058)},
        {USB_DEVICE(0x0DF6, 0x0049)},
        {USB_DEVICE(0x0DF6, 0x004C)},
+       {USB_DEVICE(0x0DF6, 0x006C)},
        {USB_DEVICE(0x0DF6, 0x0064)},
        /* Skyworth */
        {USB_DEVICE(0x14b2, 0x3300)},
index d540a06..077c506 100644 (file)
@@ -1602,6 +1602,10 @@ static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) {
 //        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works);
         if (works++>15)
             break;
+
+        if (!pRD->pRDInfo->skb)
+            break;
+
         if (device_receive_frame(pDevice, pRD)) {
             if (!device_alloc_rx_buf(pDevice,pRD)) {
                     DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
index ae4e7da..7c33cbb 100644 (file)
@@ -979,7 +979,7 @@ static int iscsit_handle_scsi_cmd(
                if (cmd->targ_xfer_tag == 0xFFFFFFFF)
                        cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
                spin_unlock_bh(&conn->sess->ttt_lock);
-       } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
+       } else
                cmd->targ_xfer_tag = 0xFFFFFFFF;
        cmd->cmd_sn             = hdr->cmdsn;
        cmd->exp_stat_sn        = hdr->exp_statsn;
@@ -4509,6 +4509,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
        struct iscsi_session *sess;
        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
        struct se_session *se_sess, *se_sess_tmp;
+       LIST_HEAD(free_list);
        int session_count = 0;
 
        spin_lock_bh(&se_tpg->session_lock);
@@ -4530,14 +4531,17 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
                }
                atomic_set(&sess->session_reinstatement, 1);
                spin_unlock(&sess->conn_lock);
-               spin_unlock_bh(&se_tpg->session_lock);
 
-               iscsit_free_session(sess);
-               spin_lock_bh(&se_tpg->session_lock);
+               list_move_tail(&se_sess->sess_list, &free_list);
+       }
+       spin_unlock_bh(&se_tpg->session_lock);
 
+       list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
+               sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+
+               iscsit_free_session(sess);
                session_count++;
        }
-       spin_unlock_bh(&se_tpg->session_lock);
 
        pr_debug("Released %d iSCSI Session(s) from Target Portal"
                        " Group: %hu\n", session_count, tpg->tpgt);
index 6993961..c3cf95e 100644 (file)
@@ -668,11 +668,8 @@ int target_report_luns(struct se_task *se_task)
         * coming via a target_core_mod PASSTHROUGH op, and not through
         * a $FABRIC_MOD.  In that case, report LUN=0 only.
         */
-       if (!se_sess) {
-               int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
-               lun_count = 1;
+       if (!se_sess)
                goto done;
-       }
 
        spin_lock_irq(&se_sess->se_node_acl->device_list_lock);
        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
@@ -699,6 +696,14 @@ int target_report_luns(struct se_task *se_task)
         * See SPC3 r07, page 159.
         */
 done:
+       /*
+        * If no LUNs are accessible, report virtual LUN 0.
+        */
+       if (lun_count == 0) {
+               int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
+               lun_count = 1;
+       }
+
        lun_count *= 8;
        buf[0] = ((lun_count >> 24) & 0xff);
        buf[1] = ((lun_count >> 16) & 0xff);
index ebf9b60..1fb9e58 100644 (file)
@@ -569,6 +569,7 @@ static struct se_device *pscsi_create_virtdevice(
                                        " pdv_host_id: %d\n", pdv->pdv_host_id);
                                return ERR_PTR(-EINVAL);
                        }
+                       pdv->pdv_lld_host = sh;
                }
        } else {
                if (phv->phv_mode == PHV_VIRUTAL_HOST_ID) {
@@ -655,6 +656,8 @@ static void pscsi_free_device(void *p)
                if ((phv->phv_mode == PHV_LLD_SCSI_HOST_NO) &&
                    (phv->phv_lld_host != NULL))
                        scsi_host_put(phv->phv_lld_host);
+               else if (pdv->pdv_lld_host)
+                       scsi_host_put(pdv->pdv_lld_host);
 
                if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
                        scsi_device_put(sd);
index fdc17b6..8b0a336 100644 (file)
@@ -46,6 +46,7 @@ struct pscsi_dev_virt {
        struct block_device *pdv_bd;
        struct scsi_device *pdv_sd;
        struct se_hba *pdv_se_hba;
+       struct Scsi_Host *pdv_lld_host;
 } ____cacheline_aligned;
 
 typedef enum phv_modes {
index 52fdf60..df8f8e0 100644 (file)
@@ -167,7 +167,7 @@ static int __init xen_hvc_init(void)
 
        if (xen_initial_domain()) {
                ops = &dom0_hvc_ops;
-               xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
+               xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
        } else {
                if (!xen_start_info->console.domU.evtchn)
                        return -ENODEV;
index bac83d8..4671f8d 100644 (file)
@@ -1298,8 +1298,7 @@ handle_newline:
                        tty->canon_data++;
                        spin_unlock_irqrestore(&tty->read_lock, flags);
                        kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-                       if (waitqueue_active(&tty->read_wait))
-                               wake_up_interruptible(&tty->read_wait);
+                       wake_up_interruptible(&tty->read_wait);
                        return;
                }
        }
@@ -1422,8 +1421,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
                L_EXTPROC(tty)) {
                kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-               if (waitqueue_active(&tty->read_wait))
-                       wake_up_interruptible(&tty->read_wait);
+               wake_up_interruptible(&tty->read_wait);
        }
 
        /*
index a2f2365..add2096 100644 (file)
@@ -42,6 +42,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
        {       "AEI1240",              0       },
        /* Rockwell 56K ACF II Fax+Data+Voice Modem */
        {       "AKY1021",              0 /*SPCI_FL_NO_SHIRQ*/  },
+       /*
+        * ALi Fast Infrared Controller
+        * Native driver (ali-ircc) is broken so at least
+        * it can be used with irtty-sir.
+        */
+       {       "ALI5123",              0       },
        /* AZT3005 PnP SOUND DEVICE */
        {       "AZT4001",              0       },
        /* Best Data Products Inc. Smart One 336F PnP Modem */
index 99fcb8c..9645186 100644 (file)
@@ -229,8 +229,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
        if (rs485conf->flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
                atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-               if ((rs485conf->delay_rts_after_send) > 0)
-                       UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+               UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
                dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -305,9 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if ((atmel_port->rs485.delay_rts_after_send) > 0)
-                       UART_PUT_TTGR(port,
-                                       atmel_port->rs485.delay_rts_after_send);
+               UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
                dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -1229,9 +1226,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if ((atmel_port->rs485.delay_rts_after_send) > 0)
-                       UART_PUT_TTGR(port,
-                                       atmel_port->rs485.delay_rts_after_send);
+               UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
                dev_dbg(port->dev, "Setting UART to RS232\n");
index 6563cad..746e771 100644 (file)
@@ -192,7 +192,6 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
 #endif
-       { .type = "serial",         .data = (void *)PORT_UNKNOWN, },
        { /* end of list */ },
 };
 
index 6cd4143..d9706e7 100644 (file)
@@ -573,7 +573,8 @@ MODULE_DEVICE_TABLE(of, ulite_of_match);
 
 static int __devinit ulite_probe(struct platform_device *pdev)
 {
-       struct resource *res, *res2;
+       struct resource *res;
+       int irq;
        int id = pdev->id;
 #ifdef CONFIG_OF
        const __be32 *prop;
@@ -587,11 +588,11 @@ static int __devinit ulite_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
 
-       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res2)
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return -ENXIO;
 
-       return ulite_assign(&pdev->dev, id, res->start, res2->start);
+       return ulite_assign(&pdev->dev, id, res->start, irq);
 }
 
 static int __devexit ulite_remove(struct platform_device *pdev)
index b627363..778c39a 100644 (file)
@@ -941,9 +941,9 @@ static struct uart_driver xuartps_uart_driver = {
  **/
 static int __devinit xuartps_probe(struct platform_device *pdev)
 {
-       int rc;
+       int rc, irq;
        struct uart_port *port;
-       struct resource *res, *res2;
+       struct resource *res;
        int clk = 0;
 
 #ifdef CONFIG_OF
@@ -964,9 +964,9 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
 
-       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res2)
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return -ENXIO;
 
        /* Initialize the port structure */
        port = xuartps_get_port();
@@ -980,7 +980,7 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
                 * and triggers invocation of the config_port() entry point.
                 */
                port->mapbase = res->start;
-               port->irq = res2->start;
+               port->irq = irq;
                port->dev = &pdev->dev;
                port->uartclk = clk;
                dev_set_drvdata(&pdev->dev, port);
index fa59fbe..6ab0322 100644 (file)
@@ -1985,8 +1985,24 @@ got_driver:
        if (!noctty &&
            current->signal->leader &&
            !current->signal->tty &&
-           tty->session == NULL)
-               __proc_set_tty(current, tty);
+           tty->session == NULL) {
+               /*
+                * Don't let a process that only has write access to the tty
+                * obtain the privileges associated with having a tty as
+                * controlling terminal (being able to reopen it with full
+                * access through /dev/tty, being able to perform pushback).
+                * Many distributions set the group of all ttys to "tty" and
+                * grant write-only access to all terminals for setgid tty
+                * binaries, which should not imply full privileges on all ttys.
+                *
+                * This could theoretically break old code that performs open()
+                * on a write-only file descriptor. In that case, it might be
+                * necessary to also permit this if
+                * inode_permission(inode, MAY_READ) == 0.
+                */
+               if (filp->f_mode & FMODE_READ)
+                       __proc_set_tty(current, tty);
+       }
        spin_unlock_irq(&current->sighand->siglock);
        tty_unlock();
        mutex_unlock(&tty_mutex);
@@ -2266,7 +2282,7 @@ static int fionbio(struct file *file, int __user *p)
  *             Takes ->siglock() when updating signal->tty
  */
 
-static int tiocsctty(struct tty_struct *tty, int arg)
+static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
 {
        int ret = 0;
        if (current->signal->leader && (task_session(current) == tty->session))
@@ -2299,6 +2315,13 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                        goto unlock;
                }
        }
+
+       /* See the comment in tty_open(). */
+       if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        proc_set_tty(current, tty);
 unlock:
        mutex_unlock(&tty_mutex);
@@ -2653,7 +2676,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                no_tty();
                return 0;
        case TIOCSCTTY:
-               return tiocsctty(tty, arg);
+               return tiocsctty(tty, file, arg);
        case TIOCGPGRP:
                return tiocgpgrp(tty, real_tty, p);
        case TIOCSPGRP:
index 360ddb5..ca666d0 100644 (file)
@@ -947,11 +947,16 @@ static int acm_probe(struct usb_interface *intf,
        }
 
        while (buflen > 0) {
+               elength = buffer[0];
+               if (!elength) {
+                       dev_err(&intf->dev, "skipping garbage byte\n");
+                       elength = 1;
+                       goto next_desc;
+               }
                if (buffer[1] != USB_DT_CS_INTERFACE) {
                        dev_err(&intf->dev, "skipping garbage\n");
                        goto next_desc;
                }
-               elength = buffer[0];
 
                switch (buffer[2]) {
                case USB_CDC_UNION_TYPE: /* we've found it */
@@ -1290,6 +1295,11 @@ skip_countries:
 
        acm_table[minor] = acm;
 
+       if (quirks & CLEAR_HALT_CONDITIONS) {
+               usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress));
+               usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress));
+       }
+
        return 0;
 alloc_fail7:
        for (i = 0; i < ACM_NW; i++)
@@ -1569,6 +1579,10 @@ static const struct usb_device_id acm_ids[] = {
        .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
        },
 
+       { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
+       .driver_info = CLEAR_HALT_CONDITIONS,
+       },
+
        /* Nokia S60 phones expose two ACM channels. The first is
         * a modem and is picked up by the standard AT-command
         * information below. The second is 'vendor-specific' but
index c3f1b36..7aa5e9a 100644 (file)
@@ -127,3 +127,4 @@ struct acm {
 #define NO_CAP_LINE                    4
 #define NOT_A_MODEM                    8
 #define NO_DATA_INTERFACE              16
+#define CLEAR_HALT_CONDITIONS          BIT(7)
index 06dfb4f..d34005b 100644 (file)
@@ -224,7 +224,7 @@ static void wdm_int_callback(struct urb *urb)
        case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
                dev_dbg(&desc->intf->dev,
                        "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
-                       dr->wIndex, dr->wLength);
+                       le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength));
                break;
 
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -237,14 +237,16 @@ static void wdm_int_callback(struct urb *urb)
                clear_bit(WDM_POLL_RUNNING, &desc->flags);
                dev_err(&desc->intf->dev,
                        "unknown notification %d received: index %d len %d\n",
-                       dr->bNotificationType, dr->wIndex, dr->wLength);
+                       dr->bNotificationType,
+                       le16_to_cpu(dr->wIndex),
+                       le16_to_cpu(dr->wLength));
                goto exit;
        }
 
        req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
        req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
        req->wValue = 0;
-       req->wIndex = desc->inum;
+       req->wIndex = desc->inum; /* already converted */
        req->wLength = cpu_to_le16(desc->wMaxCommand);
 
        usb_fill_control_urb(
@@ -401,7 +403,7 @@ static ssize_t wdm_write
                             USB_RECIP_INTERFACE);
        req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
        req->wValue = 0;
-       req->wIndex = desc->inum;
+       req->wIndex = desc->inum; /* already converted */
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
        desc->outbuf = buf;
@@ -414,7 +416,7 @@ static ssize_t wdm_write
                dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
        } else {
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
-                       req->wIndex);
+                       le16_to_cpu(req->wIndex));
        }
 out:
        usb_autopm_put_interface(desc->intf);
index 0276db3..478d71b 100644 (file)
@@ -114,7 +114,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
                                cfgno, inum, asnum, ep->desc.bEndpointAddress);
                ep->ss_ep_comp.bmAttributes = 16;
        } else if (usb_endpoint_xfer_isoc(&ep->desc) &&
-                       desc->bmAttributes > 2) {
+                  USB_SS_MULT(desc->bmAttributes) > 3) {
                dev_warn(ddev, "Isoc endpoint has Mult of %d in "
                                "config %d interface %d altsetting %d ep %d: "
                                "setting to 3\n", desc->bmAttributes + 1,
@@ -123,7 +123,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
        }
 
        if (usb_endpoint_xfer_isoc(&ep->desc))
-               max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
+               max_tx = (desc->bMaxBurst + 1) *
+                       (USB_SS_MULT(desc->bmAttributes)) *
                        usb_endpoint_maxp(&ep->desc);
        else if (usb_endpoint_xfer_int(&ep->desc))
                max_tx = usb_endpoint_maxp(&ep->desc) *
index 18286ce..7cfe286 100644 (file)
@@ -2157,9 +2157,6 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 #define HUB_LONG_RESET_TIME    200
 #define HUB_RESET_TIMEOUT      800
 
-static int hub_port_reset(struct usb_hub *hub, int port1,
-                       struct usb_device *udev, unsigned int delay, bool warm);
-
 /* Is a USB 3.0 port in the Inactive or Complinance Mode state?
  * Port worm reset is required to recover
  */
@@ -2239,44 +2236,6 @@ delay:
        return -EBUSY;
 }
 
-static void hub_port_finish_reset(struct usb_hub *hub, int port1,
-                       struct usb_device *udev, int *status)
-{
-       switch (*status) {
-       case 0:
-               /* TRSTRCY = 10 ms; plus some extra */
-               msleep(10 + 40);
-               if (udev) {
-                       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
-
-                       update_devnum(udev, 0);
-                       /* The xHC may think the device is already reset,
-                        * so ignore the status.
-                        */
-                       if (hcd->driver->reset_device)
-                               hcd->driver->reset_device(hcd, udev);
-               }
-               /* FALL THROUGH */
-       case -ENOTCONN:
-       case -ENODEV:
-               clear_port_feature(hub->hdev,
-                               port1, USB_PORT_FEAT_C_RESET);
-               if (hub_is_superspeed(hub->hdev)) {
-                       clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_BH_PORT_RESET);
-                       clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_PORT_LINK_STATE);
-                       clear_port_feature(hub->hdev, port1,
-                                       USB_PORT_FEAT_C_CONNECTION);
-               }
-               if (udev)
-                       usb_set_device_state(udev, *status
-                                       ? USB_STATE_NOTATTACHED
-                                       : USB_STATE_DEFAULT);
-               break;
-       }
-}
-
 /* Handle port reset and port warm(BH) reset (for USB3 protocol ports) */
 static int hub_port_reset(struct usb_hub *hub, int port1,
                        struct usb_device *udev, unsigned int delay, bool warm)
@@ -2299,13 +2258,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                 * If the caller hasn't explicitly requested a warm reset,
                 * double check and see if one is needed.
                 */
-               status = hub_port_status(hub, port1,
-                                       &portstatus, &portchange);
-               if (status < 0)
-                       goto done;
-
-               if (hub_port_warm_reset_required(hub, portstatus))
-                       warm = true;
+               if (hub_port_status(hub, port1, &portstatus, &portchange) == 0)
+                       if (hub_port_warm_reset_required(hub, portstatus))
+                               warm = true;
        }
 
        /* Reset the port */
@@ -2328,11 +2283,19 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 
                /* Check for disconnect or reset */
                if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
-                       hub_port_finish_reset(hub, port1, udev, &status);
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_RESET);
 
                        if (!hub_is_superspeed(hub->hdev))
                                goto done;
 
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_BH_PORT_RESET);
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_PORT_LINK_STATE);
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_CONNECTION);
+
                        /*
                         * If a USB 3.0 device migrates from reset to an error
                         * state, re-issue the warm reset.
@@ -2366,6 +2329,26 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                port1);
 
 done:
+       if (status == 0) {
+               /* TRSTRCY = 10 ms; plus some extra */
+               msleep(10 + 40);
+               if (udev) {
+                       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+                       update_devnum(udev, 0);
+                       /* The xHC may think the device is already reset,
+                        * so ignore the status.
+                        */
+                       if (hcd->driver->reset_device)
+                               hcd->driver->reset_device(hcd, udev);
+
+                       usb_set_device_state(udev, USB_STATE_DEFAULT);
+               }
+       } else {
+               if (udev)
+                       usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+       }
+
        if (!hub_is_superspeed(hub->hdev))
                up_read(&ehci_cf_port_reset_rwsem);
 
index ad4540e..1353326 100644 (file)
@@ -53,6 +53,13 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
 
+       /* Logitech ConferenceCam CC3000e */
+       { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x046d, 0x0848), .driver_info = USB_QUIRK_DELAY_INIT },
+
+       /* Logitech PTZ Pro Camera */
+       { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT },
+
        /* Logitech Quickcam Fusion */
        { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -77,6 +84,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Philips PSC805 audio device */
        { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Plantronic Audio 655 DSP */
+       { USB_DEVICE(0x047f, 0xc008), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Plantronic Audio 648 USB */
+       { USB_DEVICE(0x047f, 0xc013), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Artisman Watchdog Dongle */
        { USB_DEVICE(0x04b4, 0x0526), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index c4134e8..24864d4 100644 (file)
@@ -498,6 +498,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n");
                ret = dwc3_ep0_set_config(dwc, ctrl);
                break;
+       case USB_REQ_SET_INTERFACE:
+               dev_vdbg(dwc->dev ,"USB_REQ_SET_INTERFACE");
+               dwc->start_config_issued = false;
+               /* Fall through */
        default:
                dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
index 5f2e3d0..b4623f1 100644 (file)
@@ -171,6 +171,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
                if (!(reg & DWC3_DEPCMD_CMDACT)) {
                        dev_vdbg(dwc->dev, "Command Complete --> %d\n",
                                        DWC3_DEPCMD_STATUS(reg));
+                       if (DWC3_DEPCMD_STATUS(reg))
+                               return -EINVAL;
                        return 0;
                }
 
index 9aa1cbb..9716d61 100644 (file)
@@ -1052,7 +1052,7 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                                tmp = m66592_read(m66592, M66592_INTSTS0) &
                                                                M66592_CTSQ;
                                udelay(1);
-                       } while (tmp != M66592_CS_IDST || timeout-- > 0);
+                       } while (tmp != M66592_CS_IDST && timeout-- > 0);
 
                        if (tmp == M66592_CS_IDST)
                                m66592_bset(m66592,
index da487fd..cf995d4 100644 (file)
@@ -272,6 +272,10 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
        out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
 #endif
 
+       /* Deal with USB erratum A-005275 */
+       if (pdata->has_fsl_erratum_a005275 == 1)
+               ehci->has_fsl_hs_errata = 1;
+
        if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
                        (pdata->operating_mode == FSL_USB2_DR_OTG))
                ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
index 4527b90..313a47d 100644 (file)
@@ -1049,6 +1049,13 @@ static int ehci_hub_control (
                                 */
                                ehci->reset_done [wIndex] = jiffies
                                                + msecs_to_jiffies (50);
+
+                               /*
+                                * Force full-speed connect for FSL high-speed
+                                * erratum; disable HS Chirp by setting PFSC bit
+                                */
+                               if (ehci_has_fsl_hs_errata(ehci))
+                                       temp |= (1 << PORTSC_FSL_PFSC);
                        }
                        ehci_writel(ehci, temp, status_reg);
                        break;
index 14ced00..ddaaead 100644 (file)
@@ -29,7 +29,7 @@ static ssize_t show_companion(struct device *dev,
        int                     count = PAGE_SIZE;
        char                    *ptr = buf;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        nports = HCS_N_PORTS(ehci->hcs_params);
 
        for (index = 0; index < nports; ++index) {
@@ -54,7 +54,7 @@ static ssize_t store_companion(struct device *dev,
        struct ehci_hcd         *ehci;
        int                     portnum, new_owner;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        new_owner = PORT_OWNER;         /* Owned by companion */
        if (sscanf(buf, "%d", &portnum) != 1)
                return -EINVAL;
@@ -85,7 +85,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
        struct ehci_hcd         *ehci;
        int                     n;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
        return n;
 }
@@ -102,7 +102,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
        unsigned long           flags;
        ssize_t                 ret;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
                return -EINVAL;
 
@@ -167,6 +167,9 @@ static inline int create_sysfs_files(struct ehci_hcd *ehci)
        struct device   *controller = ehci_to_hcd(ehci)->self.controller;
        int     i = 0;
 
+       if (dev_get_drvdata(controller) != ehci_to_hcd(ehci))
+               return 0;
+
        /* with integrated TT there is no companion! */
        if (!ehci_is_TDI(ehci))
                i = device_create_file(controller, &dev_attr_companion);
@@ -182,6 +185,9 @@ static inline void remove_sysfs_files(struct ehci_hcd *ehci)
 {
        struct device   *controller = ehci_to_hcd(ehci)->self.controller;
 
+       if (dev_get_drvdata(controller) != ehci_to_hcd(ehci))
+               return;
+
        /* with integrated TT there is no companion! */
        if (!ehci_is_TDI(ehci))
                device_remove_file(controller, &dev_attr_companion);
index b65912d..bd8adbb 100644 (file)
@@ -136,6 +136,7 @@ struct ehci_hcd {                   /* one per controller */
        /* SILICON QUIRKS */
        unsigned                no_selective_suspend:1;
        unsigned                has_fsl_port_bug:1; /* FreeScale */
+       unsigned                has_fsl_hs_errata:1;    /* Freescale HS quirk */
        unsigned                big_endian_mmio:1;
        unsigned                big_endian_desc:1;
        unsigned                big_endian_capbase:1;
@@ -612,6 +613,17 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define        ehci_has_fsl_portno_bug(e)              (0)
 #endif
 
+#define PORTSC_FSL_PFSC        24      /* Port Force Full-Speed Connect */
+
+#if defined(CONFIG_PPC_85xx)
+/* Some Freescale processors have an erratum (USB A-005275) in which
+ * incoming packets get corrupted in HS mode
+ */
+#define ehci_has_fsl_hs_errata(e)      ((e)->has_fsl_hs_errata)
+#else
+#define ehci_has_fsl_hs_errata(e)      (0)
+#endif
+
 /*
  * While most USB host controllers implement their registers in
  * little-endian format, a minority (celleb companion chip) implement
index 5a42cf0..ac19ee5 100644 (file)
@@ -166,6 +166,10 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
 
        prop = of_get_property(np, "phy_type", NULL);
        pdata->phy_mode = determine_usb_phy(prop);
+       if (of_get_property(np, "fsl,usb-erratum-a005275", NULL))
+               pdata->has_fsl_erratum_a005275 = 1;
+       else
+               pdata->has_fsl_erratum_a005275 = 0;
 
        for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
                if (!dev_data->drivers[i])
index c1fa92e..8605813 100644 (file)
@@ -449,10 +449,13 @@ static void xhci_hub_report_link_state(struct xhci_hcd *xhci,
        u32 pls = status_reg & PORT_PLS_MASK;
 
        /* resume state is a xHCI internal state.
-        * Do not report it to usb core.
+        * Do not report it to usb core, instead, pretend to be U3,
+        * thus usb core knows it's not ready for transfer
         */
-       if (pls == XDEV_RESUME)
+       if (pls == XDEV_RESUME) {
+               *status |= USB_SS_PORT_LS_U3;
                return;
+       }
 
        /* When the CAS bit is set then warm reset
         * should be performed on port
@@ -592,7 +595,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        status |= USB_PORT_STAT_C_RESET << 16;
                /* USB3.0 only */
                if (hcd->speed == HCD_USB3) {
-                       if ((temp & PORT_PLC))
+                       /* Port link change with port in resume state should not be
+                        * reported to usbcore, as this is an internal state to be
+                        * handled by xhci driver. Reporting PLC to usbcore may
+                        * cause usbcore clearing PLC first and port change event
+                        * irq won't be generated.
+                        */
+                       if ((temp & PORT_PLC) &&
+                               (temp & PORT_PLS_MASK) != XDEV_RESUME)
                                status |= USB_PORT_STAT_C_LINK_STATE << 16;
                        if ((temp & PORT_WRC))
                                status |= USB_PORT_STAT_C_BH_RESET << 16;
index 0f4a41d..ab023b1 100644 (file)
@@ -1330,10 +1330,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
                /* Attempt to use the ring cache */
                if (virt_dev->num_rings_cached == 0)
                        return -ENOMEM;
+               virt_dev->num_rings_cached--;
                virt_dev->eps[ep_index].new_ring =
                        virt_dev->ring_cache[virt_dev->num_rings_cached];
                virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
-               virt_dev->num_rings_cached--;
                xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
                        usb_endpoint_xfer_isoc(&ep->desc) ? true : false);
        }
@@ -1403,10 +1403,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
         * use Event Data TRBs, and we don't chain in a link TRB on short
         * transfers, we're basically dividing by 1.
         *
-        * xHCI 1.0 specification indicates that the Average TRB Length should
-        * be set to 8 for control endpoints.
+        * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
+        * should be set to 8 for control endpoints.
         */
-       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
+       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
        else
                ep_ctx->tx_info |=
index a30f9e5..a42ef09 100644 (file)
@@ -122,6 +122,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 */
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+               pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
+               xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+       }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
index 25e9eb4..9f57111 100644 (file)
@@ -85,7 +85,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
                return 0;
        /* offset in TRBs */
        segment_offset = trb - seg->trbs;
-       if (segment_offset > TRBS_PER_SEGMENT)
+       if (segment_offset >= TRBS_PER_SEGMENT)
                return 0;
        return seg->dma + (segment_offset * sizeof(*trb));
 }
@@ -350,6 +350,15 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
        ret = handshake(xhci, &xhci->op_regs->cmd_ring,
                        CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
        if (ret < 0) {
+               /* we are about to kill xhci, give it one more chance */
+               xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
+                             &xhci->op_regs->cmd_ring);
+               udelay(1000);
+               ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+                               CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
+               if (ret == 0)
+                       return 0;
+
                xhci_err(xhci, "Stopped the command ring failed, "
                                "maybe the host is dead\n");
                xhci->xhc_state |= XHCI_STATE_DYING;
@@ -2060,8 +2069,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
                break;
        case COMP_DEV_ERR:
        case COMP_STALL:
+               frame->status = -EPROTO;
+               skip_td = true;
+               break;
        case COMP_TX_ERR:
                frame->status = -EPROTO;
+               if (event_trb != td->last_trb)
+                       return 0;
                skip_td = true;
                break;
        case COMP_STOP:
@@ -2173,6 +2187,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
        /* Fast path - was this the last TRB in the TD for this URB? */
        if (event_trb == td->last_trb) {
+               if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+                       return finish_td(xhci, td, event_trb, event, ep,
+                                        status, false);
+
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
@@ -2224,6 +2242,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        td->urb->actual_length +=
                                TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               if (trb_comp_code == COMP_SHORT_TX) {
+                       xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+                       td->urb_length_set = true;
+                       return 0;
+               }
        }
 
        return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2254,6 +2278,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        u32 trb_comp_code;
        int ret = 0;
        int td_num = 0;
+       bool handling_skipped_tds = false;
 
        slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
        xdev = xhci->devs[slot_id];
@@ -2367,6 +2392,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                ep->skip = true;
                xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
                goto cleanup;
+       case COMP_PING_ERR:
+               ep->skip = true;
+               xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+               goto cleanup;
        default:
                if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
                        status = 0;
@@ -2498,13 +2527,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                                 ep, &status);
 
 cleanup:
+
+
+               handling_skipped_tds = ep->skip &&
+                       trb_comp_code != COMP_MISSED_INT &&
+                       trb_comp_code != COMP_PING_ERR;
+
                /*
-                * Do not update event ring dequeue pointer if ep->skip is set.
-                * Will roll back to continue process missed tds.
+                * Do not update event ring dequeue pointer if we're in a loop
+                * processing missed tds.
                 */
-               if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+               if (!handling_skipped_tds)
                        inc_deq(xhci, xhci->event_ring, true);
-               }
 
                if (ret) {
                        urb = td->urb;
@@ -2539,7 +2573,7 @@ cleanup:
         * Process them as short transfer until reach the td pointed by
         * the event.
         */
-       } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+       } while (handling_skipped_tds);
 
        return 0;
 }
@@ -2646,7 +2680,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
                xhci_halt(xhci);
 hw_died:
                spin_unlock(&xhci->lock);
-               return -ESHUTDOWN;
+               return IRQ_HANDLED;
        }
 
        /*
@@ -3418,8 +3452,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        if (start_cycle == 0)
                field |= 0x1;
 
-       /* xHCI 1.0 6.4.1.2.1: Transfer Type field */
-       if (xhci->hci_version == 0x100) {
+       /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
+       if (xhci->hci_version >= 0x100) {
                if (urb->transfer_buffer_length > 0) {
                        if (setup->bRequestType & USB_DIR_IN)
                                field |= TRB_TX_TYPE(TRB_DATA_IN);
index 5c535a8..2f51dec 100644 (file)
@@ -141,7 +141,8 @@ static int xhci_start(struct xhci_hcd *xhci)
                                "waited %u microseconds.\n",
                                XHCI_MAX_HALT_USEC);
        if (!ret)
-               xhci->xhc_state &= ~XHCI_STATE_HALTED;
+               xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING);
+
        return ret;
 }
 
@@ -3361,6 +3362,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
                        return -EINVAL;
        }
 
+       if (virt_dev->tt_info)
+               old_active_eps = virt_dev->tt_info->active_eps;
+
        if (virt_dev->udev != udev) {
                /* If the virt_dev and the udev does not match, this virt_dev
                 * may belong to another udev.
index efbdf83..d676ae0 100644 (file)
@@ -1231,7 +1231,7 @@ union xhci_trb {
  * since the command ring is 64-byte aligned.
  * It must also be greater than 16.
  */
-#define TRBS_PER_SEGMENT       64
+#define TRBS_PER_SEGMENT       256
 /* Allow two commands + a link TRB, along with any reserved command TRBs */
 #define MAX_RSVD_CMD_TRBS      (TRBS_PER_SEGMENT - 3)
 #define SEGMENT_SIZE           (TRBS_PER_SEGMENT*16)
index ccb198c..9231aa6 100644 (file)
@@ -1571,16 +1571,30 @@ irqreturn_t musb_interrupt(struct musb *musb)
                (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
                musb->int_usb, musb->int_tx, musb->int_rx);
 
-       /* the core can interrupt us for multiple reasons; docs have
-        * a generic interrupt flowchart to follow
+       /**
+        * According to Mentor Graphics' documentation, flowchart on page 98,
+        * IRQ should be handled as follows:
+        *
+        * . Resume IRQ
+        * . Session Request IRQ
+        * . VBUS Error IRQ
+        * . Suspend IRQ
+        * . Connect IRQ
+        * . Disconnect IRQ
+        * . Reset/Babble IRQ
+        * . SOF IRQ (we're not using this one)
+        * . Endpoint 0 IRQ
+        * . TX Endpoints
+        * . RX Endpoints
+        *
+        * We will be following that flowchart in order to avoid any problems
+        * that might arise with internal Finite State Machine.
         */
+
        if (musb->int_usb)
                retval |= musb_stage0_irq(musb, musb->int_usb,
                                devctl, power);
 
-       /* "stage 1" is handling endpoint irqs */
-
-       /* handle endpoint 0 first */
        if (musb->int_tx & 1) {
                if (devctl & MUSB_DEVCTL_HM)
                        retval |= musb_h_ep0_irq(musb);
@@ -1588,43 +1602,37 @@ irqreturn_t musb_interrupt(struct musb *musb)
                        retval |= musb_g_ep0_irq(musb);
        }
 
-       /* RX on endpoints 1-15 */
-       reg = musb->int_rx >> 1;
+       reg = musb->int_tx >> 1;
        ep_num = 1;
        while (reg) {
                if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
-                       /* REVISIT just retval = ep->rx_irq(...) */
                        retval = IRQ_HANDLED;
                        if (devctl & MUSB_DEVCTL_HM) {
                                if (is_host_capable())
-                                       musb_host_rx(musb, ep_num);
+                                       musb_host_tx(musb, ep_num);
                        } else {
                                if (is_peripheral_capable())
-                                       musb_g_rx(musb, ep_num);
+                                       musb_g_tx(musb, ep_num);
                        }
                }
-
                reg >>= 1;
                ep_num++;
        }
 
-       /* TX on endpoints 1-15 */
-       reg = musb->int_tx >> 1;
+       reg = musb->int_rx >> 1;
        ep_num = 1;
        while (reg) {
                if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
-                       /* REVISIT just retval |= ep->tx_irq(...) */
                        retval = IRQ_HANDLED;
                        if (devctl & MUSB_DEVCTL_HM) {
                                if (is_host_capable())
-                                       musb_host_tx(musb, ep_num);
+                                       musb_host_rx(musb, ep_num);
                        } else {
                                if (is_peripheral_capable())
-                                       musb_g_tx(musb, ep_num);
+                                       musb_g_rx(musb, ep_num);
                        }
                }
+
                reg >>= 1;
                ep_num++;
        }
index 7f32c74..1a19724 100644 (file)
@@ -133,6 +133,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
        { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */
+       { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
+       { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
@@ -191,6 +193,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
        { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
        { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
+       { USB_DEVICE(0x2626, 0xEA60) }, /* Aruba Networks 7xxx USB Serial Console */
        { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
        { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
        { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
index e13ebb0..4ffaa9d 100644 (file)
@@ -629,6 +629,10 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) },
        /*
         * ELV devices:
         */
@@ -723,6 +727,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
index 361192c..7d11642 100644 (file)
 #define XSENS_AWINDA_STATION_PID 0x0101
 #define XSENS_AWINDA_DONGLE_PID 0x0102
 #define XSENS_MTW_PID          0x0200  /* Xsens MTw */
+#define XSENS_MTDEVBOARD_PID   0x0300  /* Motion Tracker Development Board */
 #define XSENS_CONVERTER_PID    0xD00D  /* Xsens USB-serial converter */
 
 /* Xsens devices using FTDI VID */
  */
 #define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */
 
+/*
+ * CustomWare / ShipModul NMEA multiplexers product ids (FTDI_VID)
+ */
+#define FTDI_CUSTOMWARE_MINIPLEX_PID   0xfd48  /* MiniPlex first generation NMEA Multiplexer */
+#define FTDI_CUSTOMWARE_MINIPLEX2_PID  0xfd49  /* MiniPlex-USB and MiniPlex-2 series */
+#define FTDI_CUSTOMWARE_MINIPLEX2WI_PID        0xfd4a  /* MiniPlex-2Wi */
+#define FTDI_CUSTOMWARE_MINIPLEX3_PID  0xfd4b  /* MiniPlex-3 series */
+
 
 /********************************/
 /** third-party VID/PID combos **/
index 64ea95d..7e6d2ec 100644 (file)
@@ -276,6 +276,10 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF622                      0x0001
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
+#define ZTE_PRODUCT_ZM8620_X                   0x0396
+#define ZTE_PRODUCT_ME3620_MBIM                        0x0426
+#define ZTE_PRODUCT_ME3620_X                   0x1432
+#define ZTE_PRODUCT_ME3620_L                   0x1433
 #define ZTE_PRODUCT_CDMA_TECH                  0xfffe
 #define ZTE_PRODUCT_AC8710                     0xfff1
 #define ZTE_PRODUCT_AC2726                     0xfff5
@@ -547,6 +551,18 @@ static const struct option_blacklist_info zte_mc2716_z_blacklist = {
        .sendsetup = BIT(1) | BIT(2) | BIT(3),
 };
 
+static const struct option_blacklist_info zte_me3620_mbim_blacklist = {
+       .reserved = BIT(2) | BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info zte_me3620_xl_blacklist = {
+       .reserved = BIT(3) | BIT(4) | BIT(5),
+};
+
+static const struct option_blacklist_info zte_zm8620_x_blacklist = {
+       .reserved = BIT(3) | BIT(4) | BIT(5),
+};
+
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -1578,6 +1594,14 @@ static const struct usb_device_id option_ids[] = {
         .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L),
+        .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM),
+        .driver_info = (kernel_ulong_t)&zte_me3620_mbim_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_X),
+        .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ZM8620_X),
+        .driver_info = (kernel_ulong_t)&zte_zm8620_x_blacklist },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
index 7ba38ea..a440387 100644 (file)
@@ -67,7 +67,6 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
        { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
-       { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
index 71fd9da..e3b7af8 100644 (file)
 #define ALCATEL_VENDOR_ID      0x11f7
 #define ALCATEL_PRODUCT_ID     0x02df
 
-/* Samsung I330 phone cradle */
-#define SAMSUNG_VENDOR_ID      0x04e8
-#define SAMSUNG_PRODUCT_ID     0x8001
-
 #define SIEMENS_VENDOR_ID      0x11f5
 #define SIEMENS_PRODUCT_ID_SX1 0x0001
 #define SIEMENS_PRODUCT_ID_X65 0x0003
index db9e54a..f34c0dd 100644 (file)
@@ -303,6 +303,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
+       { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */
        /* AT&T Direct IP LTE modems */
        { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
index 5481809..75670b5 100644 (file)
@@ -143,6 +143,8 @@ static int  whiteheat_firmware_download(struct usb_serial *serial,
 static int  whiteheat_firmware_attach(struct usb_serial *serial);
 
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int whiteheat_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id);
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
 static int  whiteheat_open(struct tty_struct *tty,
@@ -188,6 +190,7 @@ static struct usb_serial_driver whiteheat_device = {
        .usb_driver =           &whiteheat_driver,
        .id_table =             id_table_std,
        .num_ports =            4,
+       .probe =                whiteheat_probe,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
        .open =                 whiteheat_open,
@@ -387,6 +390,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
 /*****************************************************************************
  * Connect Tech's White Heat serial driver functions
  *****************************************************************************/
+
+static int whiteheat_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id)
+{
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       size_t num_bulk_in = 0;
+       size_t num_bulk_out = 0;
+       size_t min_num_bulk;
+       unsigned int i;
+
+       iface_desc = serial->interface->cur_altsetting;
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (usb_endpoint_is_bulk_in(endpoint))
+                       ++num_bulk_in;
+               if (usb_endpoint_is_bulk_out(endpoint))
+                       ++num_bulk_out;
+       }
+
+       min_num_bulk = COMMAND_PORT + 1;
+       if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
index 0e2c2de..a0c4cc4 100644 (file)
@@ -752,6 +752,13 @@ UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_GO_SLOW ),
 
+/* Reported by Christian Schaller <cschalle@redhat.com> */
+UNUSUAL_DEV(  0x059f, 0x0651, 0x0000, 0x0000,
+               "LaCie",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_WP_DETECT ),
+
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
  * Some versions of this device need the SubClass and Protocol overrides
  * while others don't.
@@ -2012,6 +2019,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_READ_DISC_INFO ),
 
+/* Reported by Oliver Neukum <oneukum@suse.com>
+ * This device morphes spontaneously into another device if the access
+ * pattern of Windows isn't followed. Thus writable media would be dirty
+ * if the initial instance is used. So the device is limited to its
+ * virtual CD.
+ * And yes, the concept that BCD goes up to 9 is not heeded */
+UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff,
+               "ZTE,Incorporated",
+               "ZTE WCDMA Technologies MSM",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
+
 /* Reported by Sven Geggus <sven-usbst@geggus.net>
  * This encrypted pen drive returns bogus data for the initial READ(10).
  */
index be32b1b..738707a 100644 (file)
@@ -883,6 +883,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
                }
                if (eventfp != d->log_file) {
                        filep = d->log_file;
+                       d->log_file = eventfp;
                        ctx = d->log_ctx;
                        d->log_ctx = eventfp ?
                                eventfd_ctx_fileget(eventfp) : NULL;
index 2b4acb8..8a93753 100644 (file)
@@ -150,6 +150,13 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
 
        pm_runtime_get_sync(wdev->dev);
 
+       /*
+        * Make sure the watchdog is disabled. This is unfortunately required
+        * because writing to various registers with the watchdog running has no
+        * effect.
+        */
+       omap_wdt_disable(wdev);
+
        /* initialize prescaler */
        while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
                cpu_relax();
index f6227cc..bcf7711 100644 (file)
@@ -895,7 +895,7 @@ static int find_virq(unsigned int virq, unsigned int cpu)
        return rc;
 }
 
-int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu)
 {
        struct evtchn_bind_virq bind_virq;
        int evtchn, irq, ret;
@@ -909,8 +909,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
                if (irq == -1)
                        goto out;
 
-               irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
-                                             handle_percpu_irq, "virq");
+               if (percpu)
+                       irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
+                                                     handle_percpu_irq, "virq");
+               else
+                       irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
+                                                     handle_edge_irq, "virq");
 
                bind_virq.virq = virq;
                bind_virq.vcpu = cpu;
@@ -1023,7 +1027,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
 {
        int irq, retval;
 
-       irq = bind_virq_to_irq(virq, cpu);
+       irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU);
        if (irq < 0)
                return irq;
        retval = request_irq(irq, handler, irqflags, devname, dev_id);
index 080b186..5027662 100644 (file)
@@ -60,7 +60,7 @@ static int use_ptemod;
 struct gntdev_priv {
        struct list_head maps;
        /* lock protects maps from concurrent changes */
-       spinlock_t lock;
+       struct mutex lock;
        struct mm_struct *mm;
        struct mmu_notifier mn;
 };
@@ -395,7 +395,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
        unsigned long mstart, mend;
        int err;
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
        list_for_each_entry(map, &priv->maps, next) {
                if (!map->vma)
                        continue;
@@ -414,7 +414,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
                                        (mend - mstart) >> PAGE_SHIFT);
                WARN_ON(err);
        }
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
 }
 
 static void mn_invl_page(struct mmu_notifier *mn,
@@ -431,7 +431,7 @@ static void mn_release(struct mmu_notifier *mn,
        struct grant_map *map;
        int err;
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
        list_for_each_entry(map, &priv->maps, next) {
                if (!map->vma)
                        continue;
@@ -441,7 +441,7 @@ static void mn_release(struct mmu_notifier *mn,
                err = unmap_grant_pages(map, /* offset */ 0, map->count);
                WARN_ON(err);
        }
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
 }
 
 struct mmu_notifier_ops gntdev_mmu_ops = {
@@ -462,7 +462,7 @@ static int gntdev_open(struct inode *inode, struct file *flip)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&priv->maps);
-       spin_lock_init(&priv->lock);
+       mutex_init(&priv->lock);
 
        if (use_ptemod) {
                priv->mm = get_task_mm(current);
@@ -493,11 +493,13 @@ static int gntdev_release(struct inode *inode, struct file *flip)
 
        pr_debug("priv %p\n", priv);
 
+       mutex_lock(&priv->lock);
        while (!list_empty(&priv->maps)) {
                map = list_entry(priv->maps.next, struct grant_map, next);
                list_del(&map->next);
                gntdev_put_map(map);
        }
+       mutex_unlock(&priv->lock);
 
        if (use_ptemod)
                mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -535,10 +537,10 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
                return err;
        }
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
        gntdev_add_map(priv, map);
        op.index = map->index << PAGE_SHIFT;
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
 
        if (copy_to_user(u, &op, sizeof(op)) != 0)
                return -EFAULT;
@@ -557,13 +559,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
                return -EFAULT;
        pr_debug("priv %p, del %d+%d\n", priv, (int)op.index, (int)op.count);
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
        map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
        if (map) {
                list_del(&map->next);
                err = 0;
        }
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
        if (map)
                gntdev_put_map(map);
        return err;
@@ -608,7 +610,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
        if (op.action & ~(UNMAP_NOTIFY_CLEAR_BYTE|UNMAP_NOTIFY_SEND_EVENT))
                return -EINVAL;
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
 
        list_for_each_entry(map, &priv->maps, next) {
                uint64_t begin = map->index << PAGE_SHIFT;
@@ -631,7 +633,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
        map->notify.event = op.event_channel_port;
        rc = 0;
  unlock_out:
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
        return rc;
 }
 
@@ -676,7 +678,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        pr_debug("map %d+%d at %lx (pgoff %lx)\n",
                        index, count, vma->vm_start, vma->vm_pgoff);
 
-       spin_lock(&priv->lock);
+       mutex_lock(&priv->lock);
        map = gntdev_find_map_index(priv, index, count);
        if (!map)
                goto unlock_out;
@@ -711,7 +713,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
                        map->flags |= GNTMAP_readonly;
        }
 
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
 
        if (use_ptemod) {
                err = apply_to_page_range(vma->vm_mm, vma->vm_start,
@@ -739,11 +741,11 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        return 0;
 
 unlock_out:
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
        return err;
 
 out_unlock_put:
-       spin_unlock(&priv->lock);
+       mutex_unlock(&priv->lock);
 out_put_map:
        if (use_ptemod)
                map->vma = NULL;
index 82ab1c3..bb8cb69 100644 (file)
@@ -16,8 +16,8 @@
 #include "conf_space.h"
 #include "conf_space_quirks.h"
 
-bool permissive;
-module_param(permissive, bool, 0644);
+bool xen_pcibk_permissive;
+module_param_named(permissive, xen_pcibk_permissive, bool, 0644);
 
 /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
  * xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
@@ -262,7 +262,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
                 * This means that some fields may still be read-only because
                 * they have entries in the config_field list that intercept
                 * the write and do nothing. */
-               if (dev_data->permissive || permissive) {
+               if (dev_data->permissive || xen_pcibk_permissive) {
                        switch (size) {
                        case 1:
                                err = pci_write_config_byte(dev, offset,
index 2e1d73d..62461a8 100644 (file)
@@ -64,7 +64,7 @@ struct config_field_entry {
        void *data;
 };
 
-extern bool permissive;
+extern bool xen_pcibk_permissive;
 
 #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
 
index a5bb81a..1667a90 100644 (file)
@@ -105,7 +105,7 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
 
        cmd->val = value;
 
-       if (!permissive && (!dev_data || !dev_data->permissive))
+       if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive))
                return 0;
 
        /* Only allow the guest to control certain bits. */
index cf38e15..08d90e2 100644 (file)
@@ -86,6 +86,7 @@ int main(int argc, char **argv)
                case 'j':
                        include_jump = 1;
                        break;
+               default:
                        return usage();
                }
        }
index 879ed88..bf1df72 100644 (file)
@@ -527,8 +527,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
        unlock_new_inode(inode);
        return inode;
 error:
-       unlock_new_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        return ERR_PTR(retval);
 
 }
index 30d4fa8..dbbc83f 100644 (file)
@@ -169,8 +169,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
        unlock_new_inode(inode);
        return inode;
 error:
-       unlock_new_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        return ERR_PTR(retval);
 
 }
index 2aed667..0f3bbea 100644 (file)
@@ -671,16 +671,16 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         */
                        would_dump(bprm, interpreter);
 
-                       retval = kernel_read(interpreter, 0, bprm->buf,
-                                            BINPRM_BUF_SIZE);
-                       if (retval != BINPRM_BUF_SIZE) {
+                       /* Get the exec headers */
+                       retval = kernel_read(interpreter, 0,
+                                            (void *)&loc->interp_elf_ex,
+                                            sizeof(loc->interp_elf_ex));
+                       if (retval != sizeof(loc->interp_elf_ex)) {
                                if (retval >= 0)
                                        retval = -EIO;
                                goto out_free_dentry;
                        }
 
-                       /* Get the exec headers */
-                       loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
                        break;
                }
                elf_ppnt++;
@@ -746,6 +746,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
            i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
                int elf_prot = 0, elf_flags;
                unsigned long k, vaddr;
+               unsigned long total_size = 0;
 
                if (elf_ppnt->p_type != PT_LOAD)
                        continue;
@@ -809,10 +810,16 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 #else
                        load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 #endif
+                       total_size = total_mapping_size(elf_phdata,
+                                                       loc->elf_ex.e_phnum);
+                       if (!total_size) {
+                               retval = -EINVAL;
+                               goto out_free_dentry;
+                       }
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-                               elf_prot, elf_flags, 0);
+                               elf_prot, elf_flags, total_size);
                if (BAD_ADDR(error)) {
                        send_sig(SIGKILL, current, 0);
                        retval = IS_ERR((void *)error) ?
index 83a871f..0d9228b 100644 (file)
@@ -2174,15 +2174,6 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
 BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
                   other_encoding, 16);
 
-/* this returns the number of file bytes represented by the inline item.
- * If an item is compressed, this is the uncompressed size
- */
-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-                                              struct btrfs_file_extent_item *e)
-{
-       return btrfs_file_extent_ram_bytes(eb, e);
-}
-
 /*
  * this returns the number of bytes used by the item on disk, minus the
  * size of any extent headers.  If a file is compressed on disk, this is
@@ -2196,6 +2187,29 @@ static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
        return btrfs_item_size(eb, e) - offset;
 }
 
+/* this returns the number of file bytes represented by the inline item.
+ * If an item is compressed, this is the uncompressed size
+ */
+static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
+                                              int slot,
+                                              struct btrfs_file_extent_item *fi)
+{
+       /*
+        * return the space used on disk if this item isn't
+        * compressed or encoded
+        */
+       if (btrfs_file_extent_compression(eb, fi) == 0 &&
+           btrfs_file_extent_encryption(eb, fi) == 0 &&
+           btrfs_file_extent_other_encoding(eb, fi) == 0) {
+               return btrfs_file_extent_inline_item_len(eb,
+                                                        btrfs_item_nr(eb, slot));
+       }
+
+       /* otherwise use the ram bytes field */
+       return btrfs_file_extent_ram_bytes(eb, fi);
+}
+
+
 static inline struct btrfs_root *btrfs_sb(struct super_block *sb)
 {
        return sb->s_fs_info;
@@ -2482,6 +2496,13 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 }
 
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
+static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
+{
+       ++p->slots[0];
+       if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
+               return btrfs_next_leaf(root, p);
+       return 0;
+}
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
 void btrfs_drop_snapshot(struct btrfs_root *root,
index a694317..da528f8 100644 (file)
@@ -5678,12 +5678,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                return -ENOSPC;
        }
 
-       if (btrfs_test_opt(root, DISCARD))
-               ret = btrfs_discard_extent(root, start, len, NULL);
-
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
        }
index 05937a8..9a837a8 100644 (file)
@@ -2444,7 +2444,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
                              bio_end_io_t end_io_func,
                              int mirror_num,
                              unsigned long prev_bio_flags,
-                             unsigned long bio_flags)
+                             unsigned long bio_flags,
+                             bool force_bio_submit)
 {
        int ret = 0;
        struct bio *bio;
@@ -2463,6 +2464,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
                                sector;
 
                if (prev_bio_flags != bio_flags || !contig ||
+                   force_bio_submit ||
                    (tree->ops && tree->ops->merge_bio_hook &&
                     tree->ops->merge_bio_hook(page, offset, page_size, bio,
                                               bio_flags)) ||
@@ -2519,7 +2521,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                                   struct page *page,
                                   get_extent_t *get_extent,
                                   struct bio **bio, int mirror_num,
-                                  unsigned long *bio_flags)
+                                  unsigned long *bio_flags,
+                                  u64 *prev_em_start)
 {
        struct inode *inode = page->mapping->host;
        u64 start = (u64)page->index << PAGE_CACHE_SHIFT;
@@ -2575,6 +2578,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                }
        }
        while (cur <= end) {
+               bool force_bio_submit = false;
+
                if (cur >= last_byte) {
                        char *userpage;
                        struct extent_state *cached = NULL;
@@ -2621,6 +2626,49 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                block_start = em->block_start;
                if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
                        block_start = EXTENT_MAP_HOLE;
+
+               /*
+                * If we have a file range that points to a compressed extent
+                * and it's followed by a consecutive file range that points to
+                * to the same compressed extent (possibly with a different
+                * offset and/or length, so it either points to the whole extent
+                * or only part of it), we must make sure we do not submit a
+                * single bio to populate the pages for the 2 ranges because
+                * this makes the compressed extent read zero out the pages
+                * belonging to the 2nd range. Imagine the following scenario:
+                *
+                *  File layout
+                *  [0 - 8K]                     [8K - 24K]
+                *    |                               |
+                *    |                               |
+                * points to extent X,         points to extent X,
+                * offset 4K, length of 8K     offset 0, length 16K
+                *
+                * [extent X, compressed length = 4K uncompressed length = 16K]
+                *
+                * If the bio to read the compressed extent covers both ranges,
+                * it will decompress extent X into the pages belonging to the
+                * first range and then it will stop, zeroing out the remaining
+                * pages that belong to the other range that points to extent X.
+                * So here we make sure we submit 2 bios, one for the first
+                * range and another one for the third range. Both will target
+                * the same physical extent from disk, but we can't currently
+                * make the compressed bio endio callback populate the pages
+                * for both ranges because each compressed bio is tightly
+                * coupled with a single extent map, and each range can have
+                * an extent map with a different offset value relative to the
+                * uncompressed data of our extent and different lengths. This
+                * is a corner case so we prioritize correctness over
+                * non-optimal behavior (submitting 2 bios for the same extent).
+                */
+               if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) &&
+                   prev_em_start && *prev_em_start != (u64)-1 &&
+                   *prev_em_start != em->orig_start)
+                       force_bio_submit = true;
+
+               if (prev_em_start)
+                       *prev_em_start = em->orig_start;
+
                free_extent_map(em);
                em = NULL;
 
@@ -2675,7 +2723,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                                         bdev, bio, pnr,
                                         end_bio_extent_readpage, mirror_num,
                                         *bio_flags,
-                                        this_bio_flag);
+                                        this_bio_flag,
+                                        force_bio_submit);
                        nr++;
                        *bio_flags = this_bio_flag;
                }
@@ -2701,7 +2750,7 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
        int ret;
 
        ret = __extent_read_full_page(tree, page, get_extent, &bio, mirror_num,
-                                     &bio_flags);
+                                     &bio_flags, NULL);
        if (bio)
                ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
        return ret;
@@ -2960,7 +3009,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
                                                 sector, iosize, pg_offset,
                                                 bdev, &epd->bio, max_nr,
                                                 end_bio_extent_writepage,
-                                                0, 0, 0);
+                                                0, 0, 0, false);
                        if (ret)
                                SetPageError(page);
                }
@@ -3219,6 +3268,7 @@ int extent_readpages(struct extent_io_tree *tree,
        struct bio *bio = NULL;
        unsigned page_idx;
        unsigned long bio_flags = 0;
+       u64 prev_em_start = (u64)-1;
 
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
                struct page *page = list_entry(pages->prev, struct page, lru);
@@ -3228,7 +3278,8 @@ int extent_readpages(struct extent_io_tree *tree,
                if (!add_to_page_cache_lru(page, mapping,
                                        page->index, GFP_NOFS)) {
                        __extent_read_full_page(tree, page, get_extent,
-                                               &bio, 0, &bio_flags);
+                                               &bio, 0, &bio_flags,
+                                               &prev_em_start);
                }
                page_cache_release(page);
        }
@@ -3998,6 +4049,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
        unsigned long num_pages;
        struct bio *bio = NULL;
        unsigned long bio_flags = 0;
+       u64 prev_em_start = (u64)-1;
 
        if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
                return 0;
@@ -4053,7 +4105,8 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
                        ClearPageError(page);
                        err = __extent_read_full_page(tree, page,
                                                      get_extent, &bio,
-                                                     mirror_num, &bio_flags);
+                                                     mirror_num, &bio_flags,
+                                                     &prev_em_start);
                        if (err)
                                ret = err;
                } else {
index 97fbe93..a1da0ab 100644 (file)
@@ -605,8 +605,15 @@ next_slot:
                }
 
                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
-               if (key.objectid > ino ||
-                   key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+
+               if (key.objectid > ino)
+                       break;
+               if (WARN_ON_ONCE(key.objectid < ino) ||
+                   key.type < BTRFS_EXTENT_DATA_KEY) {
+                       path->slots[0]++;
+                       goto next_slot;
+               }
+               if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
                        break;
 
                fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -622,10 +629,11 @@ next_slot:
                                btrfs_file_extent_num_bytes(leaf, fi);
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        extent_end = key.offset +
-                               btrfs_file_extent_inline_len(leaf, fi);
+                               btrfs_file_extent_inline_len(leaf,
+                                                    path->slots[0], fi);
                } else {
-                       WARN_ON(1);
-                       extent_end = search_start;
+                       /* can't happen */
+                       BUG();
                }
 
                if (extent_end <= search_start) {
index a1fee6f..b3d1efe 100644 (file)
@@ -244,6 +244,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
 {
        struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
        struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset;
+       spinlock_t *rbroot_lock = &root->free_ino_pinned->tree_lock;
        struct btrfs_free_space *info;
        struct rb_node *n;
        u64 count;
@@ -252,24 +253,30 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
                return;
 
        while (1) {
+               bool add_to_ctl = true;
+
+               spin_lock(rbroot_lock);
                n = rb_first(rbroot);
-               if (!n)
+               if (!n) {
+                       spin_unlock(rbroot_lock);
                        break;
+               }
 
                info = rb_entry(n, struct btrfs_free_space, offset_index);
                BUG_ON(info->bitmap);
 
                if (info->offset > root->cache_progress)
-                       goto free;
+                       add_to_ctl = false;
                else if (info->offset + info->bytes > root->cache_progress)
                        count = root->cache_progress - info->offset + 1;
                else
                        count = info->bytes;
 
-               __btrfs_add_free_space(ctl, info->offset, count);
-free:
                rb_erase(&info->offset_index, rbroot);
-               kfree(info);
+               spin_unlock(rbroot_lock);
+               if (add_to_ctl)
+                       __btrfs_add_free_space(ctl, info->offset, count);
+               kmem_cache_free(btrfs_free_space_cachep, info);
        }
 }
 
index 622d322..e4c38d4 100644 (file)
@@ -88,6 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
 };
 
 static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_truncate_page(struct address_space *mapping, loff_t from);
 static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
 static noinline int cow_file_range(struct inode *inode,
@@ -1126,8 +1127,14 @@ next_slot:
                num_bytes = 0;
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 
-               if (found_key.objectid > ino ||
-                   found_key.type > BTRFS_EXTENT_DATA_KEY ||
+               if (found_key.objectid > ino)
+                       break;
+               if (WARN_ON_ONCE(found_key.objectid < ino) ||
+                   found_key.type < BTRFS_EXTENT_DATA_KEY) {
+                       path->slots[0]++;
+                       goto next_slot;
+               }
+               if (found_key.type > BTRFS_EXTENT_DATA_KEY ||
                    found_key.offset > end)
                        break;
 
@@ -1178,7 +1185,8 @@ next_slot:
                        nocow = 1;
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        extent_end = found_key.offset +
-                               btrfs_file_extent_inline_len(leaf, fi);
+                               btrfs_file_extent_inline_len(leaf,
+                                                    path->slots[0], fi);
                        extent_end = ALIGN(extent_end, root->sectorsize);
                } else {
                        BUG_ON(1);
@@ -2991,6 +2999,47 @@ out:
        return err;
 }
 
+static int truncate_inline_extent(struct btrfs_trans_handle *trans,
+                                 struct inode *inode,
+                                 struct btrfs_path *path,
+                                 struct btrfs_key *found_key,
+                                 const u64 item_end,
+                                 const u64 new_size)
+{
+       struct extent_buffer *leaf = path->nodes[0];
+       int slot = path->slots[0];
+       struct btrfs_file_extent_item *fi;
+       u32 size = (u32)(new_size - found_key->offset);
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+
+       fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+       if (btrfs_file_extent_compression(leaf, fi) != BTRFS_COMPRESS_NONE) {
+               loff_t offset = new_size;
+
+               /*
+                * Zero out the remaining of the last page of our inline extent,
+                * instead of directly truncating our inline extent here - that
+                * would be much more complex (decompressing all the data, then
+                * compressing the truncated data, which might be bigger than
+                * the size of the inline extent, resize the extent, etc).
+                * We release the path because to get the page we might need to
+                * read the extent item from disk (data not in the page cache).
+                */
+               btrfs_release_path(path);
+               return btrfs_truncate_page(inode->i_mapping, offset);
+       }
+
+       btrfs_set_file_extent_ram_bytes(leaf, fi, size);
+       size = btrfs_file_extent_calc_inline_size(size);
+       btrfs_truncate_item(trans, root, path, size, 1);
+
+       if (root->ref_cows)
+               inode_sub_bytes(inode, item_end + 1 - new_size);
+
+       return 0;
+}
+
 /*
  * this can truncate away extent items, csum items and directory items.
  * It starts at a high offset and removes keys until it can't find
@@ -3095,7 +3144,7 @@ search_again:
                                    btrfs_file_extent_num_bytes(leaf, fi);
                        } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                item_end += btrfs_file_extent_inline_len(leaf,
-                                                                        fi);
+                                                        path->slots[0], fi);
                        }
                        item_end--;
                }
@@ -3152,22 +3201,30 @@ search_again:
                         * special encodings
                         */
                        if (!del_item &&
-                           btrfs_file_extent_compression(leaf, fi) == 0 &&
                            btrfs_file_extent_encryption(leaf, fi) == 0 &&
                            btrfs_file_extent_other_encoding(leaf, fi) == 0) {
-                               u32 size = new_size - found_key.offset;
 
-                               if (root->ref_cows) {
-                                       inode_sub_bytes(inode, item_end + 1 -
-                                                       new_size);
+                               /*
+                                * Need to release path in order to truncate a
+                                * compressed extent. So delete any accumulated
+                                * extent items so far.
+                                */
+                               if (btrfs_file_extent_compression(leaf, fi) !=
+                                   BTRFS_COMPRESS_NONE && pending_del_nr) {
+                                       err = btrfs_del_items(trans, root, path,
+                                                             pending_del_slot,
+                                                             pending_del_nr);
+                                       BUG_ON(err);
+                                       pending_del_nr = 0;
                                }
-                               size =
-                                   btrfs_file_extent_calc_inline_size(size);
-                               ret = btrfs_truncate_item(trans, root, path,
-                                                         size, 1);
+
+                               err = truncate_inline_extent(trans, inode,
+                                                            path, &found_key,
+                                                            item_end,
+                                                            new_size);
+                               BUG_ON(err);
                        } else if (root->ref_cows) {
-                               inode_sub_bytes(inode, item_end + 1 -
-                                               found_key.offset);
+                               inode_sub_bytes(inode, item_end + 1 - new_size);
                        }
                }
 delete:
@@ -3518,7 +3575,8 @@ void btrfs_evict_inode(struct inode *inode)
                goto no_delete;
        }
        /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */
-       btrfs_wait_ordered_range(inode, 0, (u64)-1);
+       if (!special_file(inode->i_mode))
+               btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
        if (root->fs_info->log_root_recovering) {
                BUG_ON(!list_empty(&BTRFS_I(inode)->i_orphan));
@@ -5035,7 +5093,7 @@ again:
                       btrfs_file_extent_num_bytes(leaf, item);
        } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
                size_t size;
-               size = btrfs_file_extent_inline_len(leaf, item);
+               size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
                extent_end = (extent_start + size + root->sectorsize - 1) &
                        ~((u64)root->sectorsize - 1);
        }
@@ -5102,7 +5160,7 @@ again:
                        goto out;
                }
 
-               size = btrfs_file_extent_inline_len(leaf, item);
+               size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
                extent_offset = page_offset(page) + pg_offset - extent_start;
                copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
                                size - extent_offset);
index 7cbe2f8..f1ca909 100644 (file)
@@ -2164,6 +2164,151 @@ out:
        return ret;
 }
 
+/*
+ * Make sure we do not end up inserting an inline extent into a file that has
+ * already other (non-inline) extents. If a file has an inline extent it can
+ * not have any other extents and the (single) inline extent must start at the
+ * file offset 0. Failing to respect these rules will lead to file corruption,
+ * resulting in EIO errors on read/write operations, hitting BUG_ON's in mm, etc
+ *
+ * We can have extents that have been already written to disk or we can have
+ * dirty ranges still in delalloc, in which case the extent maps and items are
+ * created only when we run delalloc, and the delalloc ranges might fall outside
+ * the range we are currently locking in the inode's io tree. So we check the
+ * inode's i_size because of that (i_size updates are done while holding the
+ * i_mutex, which we are holding here).
+ * We also check to see if the inode has a size not greater than "datal" but has
+ * extents beyond it, due to an fallocate with FALLOC_FL_KEEP_SIZE (and we are
+ * protected against such concurrent fallocate calls by the i_mutex).
+ *
+ * If the file has no extents but a size greater than datal, do not allow the
+ * copy because we would need turn the inline extent into a non-inline one (even
+ * with NO_HOLES enabled). If we find our destination inode only has one inline
+ * extent, just overwrite it with the source inline extent if its size is less
+ * than the source extent's size, or we could copy the source inline extent's
+ * data into the destination inode's inline extent if the later is greater then
+ * the former.
+ */
+static int clone_copy_inline_extent(struct inode *src,
+                                   struct inode *dst,
+                                   struct btrfs_trans_handle *trans,
+                                   struct btrfs_path *path,
+                                   struct btrfs_key *new_key,
+                                   const u64 drop_start,
+                                   const u64 datal,
+                                   const u64 skip,
+                                   const u64 size,
+                                   char *inline_data)
+{
+       struct btrfs_root *root = BTRFS_I(dst)->root;
+       const u64 aligned_end = ALIGN(new_key->offset + datal,
+                                     root->sectorsize);
+       int ret;
+       struct btrfs_key key;
+       u64 hint_byte;
+
+       if (new_key->offset > 0)
+               return -EOPNOTSUPP;
+
+       key.objectid = btrfs_ino(dst);
+       key.type = BTRFS_EXTENT_DATA_KEY;
+       key.offset = 0;
+       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+       if (ret < 0) {
+               return ret;
+       } else if (ret > 0) {
+               if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret < 0)
+                               return ret;
+                       else if (ret > 0)
+                               goto copy_inline_extent;
+               }
+               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+               if (key.objectid == btrfs_ino(dst) &&
+                   key.type == BTRFS_EXTENT_DATA_KEY) {
+                       return -EOPNOTSUPP;
+               }
+       } else if (i_size_read(dst) <= datal) {
+               struct btrfs_file_extent_item *ei;
+               u64 ext_len;
+
+               /*
+                * If the file size is <= datal, make sure there are no other
+                * extents following (can happen do to an fallocate call with
+                * the flag FALLOC_FL_KEEP_SIZE).
+                */
+               ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                   struct btrfs_file_extent_item);
+               /*
+                * If it's an inline extent, it can not have other extents
+                * following it.
+                */
+               if (btrfs_file_extent_type(path->nodes[0], ei) ==
+                   BTRFS_FILE_EXTENT_INLINE)
+                       goto copy_inline_extent;
+
+               ext_len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
+               if (ext_len > aligned_end)
+                       return -EOPNOTSUPP;
+
+               ret = btrfs_next_item(root, path);
+               if (ret < 0) {
+                       return ret;
+               } else if (ret == 0) {
+                       btrfs_item_key_to_cpu(path->nodes[0], &key,
+                                             path->slots[0]);
+                       if (key.objectid == btrfs_ino(dst) &&
+                           key.type == BTRFS_EXTENT_DATA_KEY)
+                               return -EOPNOTSUPP;
+               }
+       }
+
+copy_inline_extent:
+       /*
+        * We have no extent items, or we have an extent at offset 0 which may
+        * or may not be inlined. All these cases are dealt the same way.
+        */
+       if (i_size_read(dst) > datal) {
+               /*
+                * If the destination inode has an inline extent...
+                * This would require copying the data from the source inline
+                * extent into the beginning of the destination's inline extent.
+                * But this is really complex, both extents can be compressed
+                * or just one of them, which would require decompressing and
+                * re-compressing data (which could increase the new compressed
+                * size, not allowing the compressed data to fit anymore in an
+                * inline extent).
+                * So just don't support this case for now (it should be rare,
+                * we are not really saving space when cloning inline extents).
+                */
+               return -EOPNOTSUPP;
+       }
+
+       btrfs_release_path(path);
+       ret = btrfs_drop_extents(trans, dst, drop_start, aligned_end,
+                                &hint_byte, 1);
+       if (ret)
+               return ret;
+       ret = btrfs_insert_empty_item(trans, root, path, new_key, size);
+       if (ret)
+               return ret;
+
+       if (skip) {
+               const u32 start = btrfs_file_extent_calc_inline_size(0);
+
+               memmove(inline_data + start, inline_data + start + skip, datal);
+       }
+
+       write_extent_buffer(path->nodes[0], inline_data,
+                           btrfs_item_ptr_offset(path->nodes[0],
+                                                 path->slots[0]),
+                           size);
+       inode_add_bytes(dst, datal);
+
+       return 0;
+}
+
 static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                       u64 off, u64 olen, u64 destoff)
 {
@@ -2263,6 +2408,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        if (off + len == src->i_size)
                len = ALIGN(src->i_size, bs) - off;
 
+       if (len == 0) {
+               ret = 0;
+               goto out_unlock;
+       }
+
        /* verify the end result is block aligned */
        if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
            !IS_ALIGNED(destoff, bs))
@@ -2454,29 +2604,20 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                size -= skip + trim;
                                datal -= skip + trim;
 
-                               ret = btrfs_drop_extents(trans, inode,
-                                                        new_key.offset,
-                                                        new_key.offset + datal,
-                                                        &hint_byte, 1);
-                               BUG_ON(ret);
-
-                               ret = btrfs_insert_empty_item(trans, root, path,
-                                                             &new_key, size);
-                               BUG_ON(ret);
-
-                               if (skip) {
-                                       u32 start =
-                                         btrfs_file_extent_calc_inline_size(0);
-                                       memmove(buf+start, buf+start+skip,
-                                               datal);
+                               ret = clone_copy_inline_extent(src, inode,
+                                                              trans, path,
+                                                              &new_key,
+                                                              new_key.offset,
+                                                              datal,
+                                                              skip, size, buf);
+                               if (ret) {
+                                       BUG_ON(ret != -EOPNOTSUPP);
+                                       btrfs_end_transaction(trans, root);
+                                       goto out;
                                }
 
                                leaf = path->nodes[0];
                                slot = path->slots[0];
-                               write_extent_buffer(leaf, buf,
-                                           btrfs_item_ptr_offset(leaf, slot),
-                                           size);
-                               inode_add_bytes(inode, datal);
                        }
 
                        btrfs_mark_buffer_dirty(leaf);
index f38e452..f8224fb 100644 (file)
@@ -240,7 +240,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
                            BTRFS_FILE_EXTENT_INLINE) {
                                printk(KERN_INFO "\t\tinline extent data "
                                       "size %u\n",
-                                      btrfs_file_extent_inline_len(l, fi));
+                                      btrfs_file_extent_inline_len(l, i, fi));
                                break;
                        }
                        printk(KERN_INFO "\t\textent data disk bytenr %llu "
index 21faa12..c658e7b 100644 (file)
@@ -537,7 +537,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
                        nbytes = 0;
        } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
-               size = btrfs_file_extent_inline_len(eb, item);
+               size = btrfs_file_extent_inline_len(eb, slot, item);
                nbytes = btrfs_file_extent_ram_bytes(eb, item);
                extent_end = (start + size + mask) & ~mask;
        } else {
index 3848b04..9d3d74f 100644 (file)
@@ -259,8 +259,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                /* check to make sure this item is what we want */
                if (found_key.objectid != key.objectid)
                        break;
-               if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
+               if (found_key.type > BTRFS_XATTR_ITEM_KEY)
                        break;
+               if (found_key.type < BTRFS_XATTR_ITEM_KEY)
+                       goto next;
 
                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
                if (verify_dir_item(root, leaf, di))
@@ -310,21 +312,40 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
 /*
  * Check if the attribute is in a supported namespace.
  *
- * This applied after the check for the synthetic attributes in the system
+ * This is applied after the check for the synthetic attributes in the system
  * namespace.
  */
-static bool btrfs_is_valid_xattr(const char *name)
+static int btrfs_is_valid_xattr(const char *name)
 {
-       return !strncmp(name, XATTR_SECURITY_PREFIX,
-                       XATTR_SECURITY_PREFIX_LEN) ||
-              !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
-              !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
-              !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+       int len = strlen(name);
+       int prefixlen = 0;
+
+       if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                       XATTR_SECURITY_PREFIX_LEN))
+               prefixlen = XATTR_SECURITY_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               prefixlen = XATTR_SYSTEM_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+               prefixlen = XATTR_TRUSTED_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+               prefixlen = XATTR_USER_PREFIX_LEN;
+       else
+               return -EOPNOTSUPP;
+
+       /*
+        * The name cannot consist of just prefix
+        */
+       if (len <= prefixlen)
+               return -EINVAL;
+
+       return 0;
 }
 
 ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
                       void *buffer, size_t size)
 {
+       int ret;
+
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -333,8 +354,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_getxattr(dentry, name, buffer, size);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
        return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
 }
 
@@ -342,6 +364,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                   size_t size, int flags)
 {
        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -358,8 +381,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_setxattr(dentry, name, value, size, flags);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
@@ -371,6 +395,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 int btrfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -387,8 +412,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_removexattr(dentry, name);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
                                XATTR_REPLACE);
index c457f84..7eb4da4 100644 (file)
@@ -1002,7 +1002,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
  */
 static int
 grow_dev_page(struct block_device *bdev, sector_t block,
-               pgoff_t index, int size, int sizebits)
+             pgoff_t index, int size, int sizebits, gfp_t gfp)
 {
        struct inode *inode = bdev->bd_inode;
        struct page *page;
@@ -1011,7 +1011,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        int ret = 0;            /* Will call free_more_memory() */
 
        page = find_or_create_page(inode->i_mapping, index,
-               (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
+               (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS) | gfp);
        if (!page)
                return ret;
 
@@ -1059,7 +1059,7 @@ failed:
  * that page was dirty, the buffers are set dirty also.
  */
 static int
-grow_buffers(struct block_device *bdev, sector_t block, int size)
+grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
 {
        pgoff_t index;
        int sizebits;
@@ -1086,11 +1086,12 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
        }
 
        /* Create a page with the proper size buffers.. */
-       return grow_dev_page(bdev, block, index, size, sizebits);
+       return grow_dev_page(bdev, block, index, size, sizebits, gfp);
 }
 
-static struct buffer_head *
-__getblk_slow(struct block_device *bdev, sector_t block, int size)
+struct buffer_head *
+__getblk_slow(struct block_device *bdev, sector_t block,
+            unsigned size, gfp_t gfp)
 {
        /* Size must be multiple of hard sectorsize */
        if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
@@ -1112,13 +1113,14 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
                if (bh)
                        return bh;
 
-               ret = grow_buffers(bdev, block, size);
+               ret = grow_buffers(bdev, block, size, gfp);
                if (ret < 0)
                        return NULL;
                if (ret == 0)
                        free_more_memory();
        }
 }
+EXPORT_SYMBOL(__getblk_slow);
 
 /*
  * The relationship between dirty buffers and dirty pages:
@@ -1369,24 +1371,25 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)
 EXPORT_SYMBOL(__find_get_block);
 
 /*
- * __getblk will locate (and, if necessary, create) the buffer_head
+ * __getblk_gfp() will locate (and, if necessary, create) the buffer_head
  * which corresponds to the passed block_device, block and size. The
  * returned buffer has its reference count incremented.
  *
- * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
- * attempt is failing.  FIXME, perhaps?
+ * __getblk_gfp() will lock up the machine if grow_dev_page's
+ * try_to_free_buffers() attempt is failing.  FIXME, perhaps?
  */
 struct buffer_head *
-__getblk(struct block_device *bdev, sector_t block, unsigned size)
+__getblk_gfp(struct block_device *bdev, sector_t block,
+            unsigned size, gfp_t gfp)
 {
        struct buffer_head *bh = __find_get_block(bdev, block, size);
 
        might_sleep();
        if (bh == NULL)
-               bh = __getblk_slow(bdev, block, size);
+               bh = __getblk_slow(bdev, block, size, gfp);
        return bh;
 }
-EXPORT_SYMBOL(__getblk);
+EXPORT_SYMBOL(__getblk_gfp);
 
 /*
  * Do async read-ahead on a buffer..
@@ -1402,24 +1405,28 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
 EXPORT_SYMBOL(__breadahead);
 
 /**
- *  __bread() - reads a specified block and returns the bh
+ *  __bread_gfp() - reads a specified block and returns the bh
  *  @bdev: the block_device to read from
  *  @block: number of block
  *  @size: size (in bytes) to read
- * 
+ *  @gfp: page allocation flag
+ *
  *  Reads a specified block, and returns buffer head that contains it.
+ *  The page cache can be allocated from non-movable area
+ *  not to prevent page migration if you set gfp to zero.
  *  It returns NULL if the block was unreadable.
  */
 struct buffer_head *
-__bread(struct block_device *bdev, sector_t block, unsigned size)
+__bread_gfp(struct block_device *bdev, sector_t block,
+                  unsigned size, gfp_t gfp)
 {
-       struct buffer_head *bh = __getblk(bdev, block, size);
+       struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
 
        if (likely(bh) && !buffer_uptodate(bh))
                bh = __bread_slow(bh);
        return bh;
 }
-EXPORT_SYMBOL(__bread);
+EXPORT_SYMBOL(__bread_gfp);
 
 /*
  * invalidate_bh_lrus() is called rarely - but not only at unmount.
index b4d2438..00d9425 100644 (file)
@@ -914,6 +914,15 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        cache = container_of(object->fscache.cache,
                             struct cachefiles_cache, cache);
 
+       pos = (loff_t)page->index << PAGE_SHIFT;
+
+       /* We mustn't write more data than we have, so we have to beware of a
+        * partial page at EOF.
+        */
+       eof = object->fscache.store_limit_l;
+       if (pos >= eof)
+               goto error;
+
        /* write the page to the backing filesystem and let it store it in its
         * own time */
        dget(object->backer);
@@ -922,47 +931,46 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
                           cache->cache_cred);
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
-       } else {
+               goto error_2;
+       }
+       if (!file->f_op->write) {
                ret = -EIO;
-               if (file->f_op->write) {
-                       pos = (loff_t) page->index << PAGE_SHIFT;
-
-                       /* we mustn't write more data than we have, so we have
-                        * to beware of a partial page at EOF */
-                       eof = object->fscache.store_limit_l;
-                       len = PAGE_SIZE;
-                       if (eof & ~PAGE_MASK) {
-                               ASSERTCMP(pos, <, eof);
-                               if (eof - pos < PAGE_SIZE) {
-                                       _debug("cut short %llx to %llx",
-                                              pos, eof);
-                                       len = eof - pos;
-                                       ASSERTCMP(pos + len, ==, eof);
-                               }
-                       }
+               goto error_2;
+       }
 
-                       data = kmap(page);
-                       old_fs = get_fs();
-                       set_fs(KERNEL_DS);
-                       ret = file->f_op->write(
-                               file, (const void __user *) data, len, &pos);
-                       set_fs(old_fs);
-                       kunmap(page);
-                       if (ret != len)
-                               ret = -EIO;
+       len = PAGE_SIZE;
+       if (eof & ~PAGE_MASK) {
+               if (eof - pos < PAGE_SIZE) {
+                       _debug("cut short %llx to %llx",
+                              pos, eof);
+                       len = eof - pos;
+                       ASSERTCMP(pos + len, ==, eof);
                }
-               fput(file);
        }
 
-       if (ret < 0) {
-               if (ret == -EIO)
-                       cachefiles_io_error_obj(
-                               object, "Write page to backing file failed");
-               ret = -ENOBUFS;
-       }
+       data = kmap(page);
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = file->f_op->write(
+               file, (const void __user *) data, len, &pos);
+       set_fs(old_fs);
+       kunmap(page);
+       fput(file);
+       if (ret != len)
+               goto error_eio;
+
+       _leave(" = 0");
+       return 0;
 
-       _leave(" = %d", ret);
-       return ret;
+error_eio:
+       ret = -EIO;
+error_2:
+       if (ret == -EIO)
+               cachefiles_io_error_obj(object,
+                                       "Write page to backing file failed");
+error:
+       _leave(" = -ENOBUFS [%d]", ret);
+       return -ENOBUFS;
 }
 
 /*
index 3c981db..8bfafe5 100644 (file)
@@ -361,8 +361,10 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
        if (opt->flags & CEPH_OPT_NOCRC)
                seq_puts(m, ",nocrc");
 
-       if (opt->name)
-               seq_printf(m, ",name=%s", opt->name);
+       if (opt->name) {
+               seq_puts(m, ",name=");
+               seq_escape(m, opt->name, ", \t\n\\");
+       }
        if (opt->key)
                seq_puts(m, ",secret=<hidden>");
 
@@ -405,7 +407,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
        if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
                seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
        if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
-               seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
+               seq_show_option(m, "snapdirname", fsopt->snapdir_name);
        return 0;
 }
 
index b4675bd..af95386 100644 (file)
@@ -388,6 +388,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
        return 0;
 }
 
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find the server given timestamp
+ * as part of ntlmv2 authentication (or local current time as
+ * default in case of failure)
+ */
+static __le64
+find_timestamp(struct cifs_ses *ses)
+{
+       unsigned int attrsize;
+       unsigned int type;
+       unsigned int onesize = sizeof(struct ntlmssp2_name);
+       unsigned char *blobptr;
+       unsigned char *blobend;
+       struct ntlmssp2_name *attrptr;
+
+       if (!ses->auth_key.len || !ses->auth_key.response)
+               return 0;
+
+       blobptr = ses->auth_key.response;
+       blobend = blobptr + ses->auth_key.len;
+
+       while (blobptr + onesize < blobend) {
+               attrptr = (struct ntlmssp2_name *) blobptr;
+               type = le16_to_cpu(attrptr->type);
+               if (type == NTLMSSP_AV_EOL)
+                       break;
+               blobptr += 2; /* advance attr type */
+               attrsize = le16_to_cpu(attrptr->length);
+               blobptr += 2; /* advance attr size */
+               if (blobptr + attrsize > blobend)
+                       break;
+               if (type == NTLMSSP_AV_TIMESTAMP) {
+                       if (attrsize == sizeof(u64))
+                               return *((__le64 *)blobptr);
+               }
+               blobptr += attrsize; /* advance attr value */
+       }
+
+       return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+}
+
 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                            const struct nls_table *nls_cp)
 {
@@ -544,6 +586,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
        struct ntlmv2_resp *buf;
        char ntlmv2_hash[16];
        unsigned char *tiblob = NULL; /* target info blob */
+       __le64 rsp_timestamp;
 
        if (ses->server->secType == RawNTLMSSP) {
                if (!ses->domainName) {
@@ -561,6 +604,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
                }
        }
 
+       /* Must be within 5 minutes of the server (or in range +/-2h
+        * in case of Mac OS X), so simply carry over server timestamp
+        * (as Windows 7 does)
+        */
+       rsp_timestamp = find_timestamp(ses);
+
        baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
        tilen = ses->auth_key.len;
        tiblob = ses->auth_key.response;
@@ -578,7 +627,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
                        (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
        buf->blob_signature = cpu_to_le32(0x00000101);
        buf->reserved = 0;
-       buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+       buf->time = rsp_timestamp;
+
        get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
        buf->reserved2 = 0;
 
index a5c996f..1d480aa 100644 (file)
@@ -383,10 +383,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
                seq_printf(s, ",multiuser");
        else if (tcon->ses->user_name)
-               seq_printf(s, ",username=%s", tcon->ses->user_name);
+               seq_show_option(s, "username", tcon->ses->user_name);
 
        if (tcon->ses->domainName)
-               seq_printf(s, ",domain=%s", tcon->ses->domainName);
+               seq_show_option(s, "domain", tcon->ses->domainName);
 
        if (srcaddr->sa_family != AF_UNSPEC) {
                struct sockaddr_in *saddr4;
index 710dd05..1dc0af7 100644 (file)
@@ -1873,7 +1873,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = NULL;
        struct cifs_tcon *pTcon = NULL;
-       struct cifs_io_parms io_parms;
 
        /*
         * To avoid spurious oplock breaks from server, in the case of
@@ -1893,18 +1892,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                                        npid, false);
                cifsFileInfo_put(open_file);
                cFYI(1, "SetFSize for attrs rc = %d", rc);
-               if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-                       unsigned int bytes_written;
-
-                       io_parms.netfid = nfid;
-                       io_parms.pid = npid;
-                       io_parms.tcon = pTcon;
-                       io_parms.offset = 0;
-                       io_parms.length = attrs->ia_size;
-                       rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
-                                         NULL, NULL, 1);
-                       cFYI(1, "Wrt seteof rc %d", rc);
-               }
        } else
                rc = -EINVAL;
 
@@ -1925,31 +1912,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                                   cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
                cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
-               if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-                       __u16 netfid;
-                       int oplock = 0;
-
-                       rc = SMBLegacyOpen(xid, pTcon, full_path,
-                               FILE_OPEN, GENERIC_WRITE,
-                               CREATE_NOT_DIR, &netfid, &oplock, NULL,
-                               cifs_sb->local_nls,
-                               cifs_sb->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
-                       if (rc == 0) {
-                               unsigned int bytes_written;
-
-                               io_parms.netfid = netfid;
-                               io_parms.pid = current->tgid;
-                               io_parms.tcon = pTcon;
-                               io_parms.offset = 0;
-                               io_parms.length = attrs->ia_size;
-                               rc = CIFSSMBWrite(xid, &io_parms,
-                                                 &bytes_written,
-                                                 NULL, NULL,  1);
-                               cFYI(1, "wrt seteof rc %d", rc);
-                               CIFSSMBClose(xid, pTcon, netfid);
-                       }
-               }
+
                if (tlink)
                        cifs_put_tlink(tlink);
        }
index 8bc98af..46265f5 100644 (file)
@@ -1016,13 +1016,13 @@ ascend:
                /* might go back up the wrong parent if we have had a rename */
                if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_child.next;
-               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+               /* go into the first sibling still alive */
+               do {
+                       next = child->d_child.next;
                        if (next == &this_parent->d_subdirs)
                                goto ascend;
                        child = list_entry(next, struct dentry, d_child);
-                       next = next->next;
-               }
+               } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
                rcu_read_unlock();
                goto resume;
        }
@@ -1142,13 +1142,13 @@ ascend:
                /* might go back up the wrong parent if we have had a rename */
                if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_child.next;
-               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+               /* go into the first sibling still alive */
+               do {
+                       next = child->d_child.next;
                        if (next == &this_parent->d_subdirs)
                                goto ascend;
                        child = list_entry(next, struct dentry, d_child);
-                       next = next->next;
-               }
+               } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
                rcu_read_unlock();
                goto resume;
        }
@@ -2452,6 +2452,8 @@ static int prepend_path(const struct path *path,
 {
        struct dentry *dentry = path->dentry;
        struct vfsmount *vfsmnt = path->mnt;
+       char *orig_buffer = *buffer;
+       int orig_len = *buflen;
        bool slash = false;
        int error = 0;
 
@@ -2459,6 +2461,14 @@ static int prepend_path(const struct path *path,
                struct dentry * parent;
 
                if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+                       /* Escaped? */
+                       if (dentry != vfsmnt->mnt_root) {
+                               *buffer = orig_buffer;
+                               *buflen = orig_len;
+                               slash = false;
+                               error = 3;
+                               goto global_root;
+                       }
                        /* Global root? */
                        if (vfsmnt->mnt_parent == vfsmnt) {
                                goto global_root;
@@ -2938,13 +2948,13 @@ ascend:
                /* might go back up the wrong parent if we have had a rename */
                if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_child.next;
-               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+               /* go into the first sibling still alive */
+               do {
+                       next = child->d_child.next;
                        if (next == &this_parent->d_subdirs)
                                goto ascend;
                        child = list_entry(next, struct dentry, d_child);
-                       next = next->next;
-               }
+               } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
                rcu_read_unlock();
                goto resume;
        }
index 3e01f8e..5ccce85 100644 (file)
@@ -135,6 +135,7 @@ static void debugfs_evict_inode(struct inode *inode)
 
 static const struct super_operations debugfs_super_operations = {
        .evict_inode    = debugfs_evict_inode,
+       .statfs         = simple_statfs,
 };
 
 static int debug_fill_super(struct super_block *sb, void *data, int silent)
index 534c1d4..eba8f1d 100644 (file)
@@ -55,26 +55,26 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
-               goto out;
-       if (nd) {
-               dentry_save = nd->path.dentry;
-               vfsmount_save = nd->path.mnt;
-               nd->path.dentry = lower_dentry;
-               nd->path.mnt = lower_mnt;
-       }
-       rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
-       if (nd) {
-               nd->path.dentry = dentry_save;
-               nd->path.mnt = vfsmount_save;
+       if (lower_dentry->d_op && lower_dentry->d_op->d_revalidate) {
+               if (nd) {
+                       dentry_save = nd->path.dentry;
+                       vfsmount_save = nd->path.mnt;
+                       nd->path.dentry = lower_dentry;
+                       nd->path.mnt = lower_mnt;
+               }
+               rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
+               if (nd) {
+                       nd->path.dentry = dentry_save;
+                       nd->path.mnt = vfsmount_save;
+               }
        }
        if (dentry->d_inode) {
-               struct inode *lower_inode =
-                       ecryptfs_inode_to_lower(dentry->d_inode);
+               struct inode *inode = dentry->d_inode;
 
-               fsstack_copy_attr_all(dentry->d_inode, lower_inode);
+               fsstack_copy_attr_all(inode, ecryptfs_inode_to_lower(inode));
+               if (!inode->i_nlink)
+                       return 0;
        }
-out:
        return rc;
 }
 
index 4b72a99..cadb627 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2134,8 +2134,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        const struct cred *old_cred;
        struct cred *cred;
        int retval = 0;
-       int flag = 0;
        int ispipe;
+       /* require nonrelative corefile path and be extra careful */
+       bool need_suid_safe = false;
        static atomic_t core_dump_count = ATOMIC_INIT(0);
        struct coredump_params cprm = {
                .signr = signr,
@@ -2161,14 +2162,15 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        if (!cred)
                goto fail;
        /*
-        *      We cannot trust fsuid as being the "true" uid of the
-        *      process nor do we know its entire history. We only know it
-        *      was tainted so we dump it as root in mode 2.
+        * We cannot trust fsuid as being the "true" uid of the process
+        * nor do we know its entire history. We only know it was tainted
+        * so we dump it as root in mode 2, and only into a controlled
+        * environment (pipe handler or fully qualified path).
         */
        if (__get_dumpable(cprm.mm_flags) == 2) {
                /* Setuid core dump mode */
-               flag = O_EXCL;          /* Stop rewrite attacks */
                cred->fsuid = 0;        /* Dump root private */
+               need_suid_safe = true;
        }
 
        retval = coredump_wait(exit_code, &core_state);
@@ -2248,8 +2250,43 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
                if (cprm.limit < binfmt->min_coredump)
                        goto fail_unlock;
 
+               if (need_suid_safe && cn.corename[0] != '/') {
+                       printk(KERN_WARNING "Pid %d(%s) can only dump core "\
+                               "to fully qualified path!\n",
+                               task_tgid_vnr(current), current->comm);
+                       printk(KERN_WARNING "Skipping core dump\n");
+                       goto fail_unlock;
+               }
+
+               /*
+                * Unlink the file if it exists unless this is a SUID
+                * binary - in that case, we're running around with root
+                * privs and don't want to unlink another user's coredump.
+                */
+               if (!need_suid_safe) {
+                       mm_segment_t old_fs;
+
+                       old_fs = get_fs();
+                       set_fs(KERNEL_DS);
+                       /*
+                        * If it doesn't exist, that's fine. If there's some
+                        * other problem, we'll catch it at the filp_open().
+                        */
+                       (void) sys_unlink((const char __user *)cn.corename);
+                       set_fs(old_fs);
+               }
+
+               /*
+                * There is a race between unlinking and creating the
+                * file, but if that causes an EEXIST here, that's
+                * fine - another process raced with us while creating
+                * the corefile, and the other process won. To userspace,
+                * what matters is that at least one of the two processes
+                * writes its coredump successfully, not which one.
+                */
                cprm.file = filp_open(cn.corename,
-                                O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
+                                O_CREAT | 2 | O_NOFOLLOW |
+                                O_LARGEFILE | O_EXCL,
                                 0600);
                if (IS_ERR(cprm.file))
                        goto fail_unlock;
index 834d9a1..e3d65ab 100644 (file)
@@ -321,7 +321,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
        ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
        ext4_lblk_t last = lblock + len - 1;
 
-       if (lblock > last)
+       if (len == 0 || lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -700,7 +700,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
                path[ppos].p_depth = i;
                path[ppos].p_ext = NULL;
 
-               bh = sb_getblk(inode->i_sb, path[ppos].p_block);
+               bh = sb_getblk_gfp(inode->i_sb, path[ppos].p_block,
+                                  __GFP_MOVABLE | GFP_NOFS);
                if (unlikely(!bh)) {
                        ret = -ENOMEM;
                        goto err;
@@ -905,7 +906,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                err = -EIO;
                goto cleanup;
        }
-       bh = sb_getblk(inode->i_sb, newblock);
+       bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS);
        if (!bh) {
                err = -ENOMEM;
                goto cleanup;
@@ -1089,7 +1090,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
        if (newblock == 0)
                return err;
 
-       bh = sb_getblk(inode->i_sb, newblock);
+       bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS);
        if (!bh)
                return -ENOMEM;
        lock_buffer(bh);
@@ -4470,13 +4471,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        struct ext4_map_blocks map;
        unsigned int credits, blkbits = inode->i_blkbits;
 
-       /*
-        * currently supporting (pre)allocate mode for extent-based
-        * files _only_
-        */
-       if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
-               return -EOPNOTSUPP;
-
        /* Return error if mode is not supported */
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
@@ -4497,6 +4491,15 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         */
        credits = ext4_chunk_trans_blocks(inode, max_blocks);
        mutex_lock(&inode->i_mutex);
+
+       /*
+        * We only support preallocation for extent-based files only
+        */
+       if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
        ret = inode_newsize_ok(inode, (len + offset));
        if (ret) {
                mutex_unlock(&inode->i_mutex);
@@ -4553,6 +4556,7 @@ retry:
                ret = 0;
                goto retry;
        }
+out:
        mutex_unlock(&inode->i_mutex);
        trace_ext4_fallocate_exit(inode, offset, max_blocks,
                                ret > 0 ? ret2 : ret);
index 26d6dbf..ae1425a 100644 (file)
@@ -706,7 +706,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
                                       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
                EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
                                 "non-extent mapped inodes with bigalloc");
-               return -ENOSPC;
+               return -EUCLEAN;
        }
 
        goal = ext4_find_goal(inode, map->m_lblk, partial);
index f06857b..0610766 100644 (file)
@@ -1849,18 +1849,31 @@ static int __ext4_journalled_writepage(struct page *page,
        page_bufs = page_buffers(page);
        BUG_ON(!page_bufs);
        walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one);
-       /* As soon as we unlock the page, it can go away, but we have
-        * references to buffers so we are safe */
+       /*
+        * We need to release the page lock before we start the
+        * journal, so grab a reference so the page won't disappear
+        * out from under us.
+        */
+       get_page(page);
        unlock_page(page);
 
        handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
-               goto out;
+               put_page(page);
+               goto out_no_pagelock;
        }
-
        BUG_ON(!ext4_handle_valid(handle));
 
+       lock_page(page);
+       put_page(page);
+       if (page->mapping != mapping) {
+               /* The page got truncated from under us */
+               ext4_journal_stop(handle);
+               ret = 0;
+               goto out;
+       }
+
        ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
                                do_journal_get_write_access);
 
@@ -1876,6 +1889,8 @@ static int __ext4_journalled_writepage(struct page *page,
        walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 out:
+       unlock_page(page);
+out_no_pagelock:
        return ret;
 }
 
index 5baa7ba..7c03826 100644 (file)
@@ -4720,18 +4720,12 @@ do_more:
                /*
                 * blocks being freed are metadata. these blocks shouldn't
                 * be used until this transaction is committed
+                *
+                * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed
+                * to fail.
                 */
-       retry:
-               new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
-               if (!new_entry) {
-                       /*
-                        * We use a retry loop because
-                        * ext4_free_blocks() is not allowed to fail.
-                        */
-                       cond_resched();
-                       congestion_wait(BLK_RW_ASYNC, HZ/50);
-                       goto retry;
-               }
+               new_entry = kmem_cache_alloc(ext4_free_ext_cachep,
+                               GFP_NOFS|__GFP_NOFAIL);
                new_entry->start_cluster = bit;
                new_entry->group  = block_group;
                new_entry->count = count_clusters;
index c9f2e3d..cd1dd49 100644 (file)
@@ -1456,7 +1456,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                          struct inode *inode)
 {
        struct inode *dir = dentry->d_parent->d_inode;
-       struct buffer_head *bh;
+       struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
        int     retval;
@@ -1471,7 +1471,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        if (is_dx(dir)) {
                retval = ext4_dx_add_entry(handle, dentry, inode);
                if (!retval || (retval != ERR_BAD_DX_DIR))
-                       return retval;
+                       goto out;
                ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
                dx_fallback++;
                ext4_mark_inode_dirty(handle, dir);
@@ -1482,14 +1482,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                if(!bh)
                        return retval;
                retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-               if (retval != -ENOSPC) {
-                       brelse(bh);
-                       return retval;
-               }
+               if (retval != -ENOSPC)
+                       goto out;
 
                if (blocks == 1 && !dx_fallback &&
-                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
-                       return make_indexed_dir(handle, dentry, inode, bh);
+                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+                       retval = make_indexed_dir(handle, dentry, inode, bh);
+                       bh = NULL; /* make_indexed_dir releases bh */
+                       goto out;
+               }
                brelse(bh);
        }
        bh = ext4_append(handle, dir, &block, &retval);
@@ -1499,6 +1500,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        de->inode = 0;
        de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
        retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+out:
        brelse(bh);
        if (retval == 0)
                ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
index 422be11..52b8ac7 100644 (file)
@@ -463,9 +463,13 @@ static void ext4_handle_error(struct super_block *sb)
                ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
                sb->s_flags |= MS_RDONLY;
        }
-       if (test_opt(sb, ERRORS_PANIC))
+       if (test_opt(sb, ERRORS_PANIC)) {
+               if (EXT4_SB(sb)->s_journal &&
+                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
+                       return;
                panic("EXT4-fs (device %s): panic forced after error\n",
                        sb->s_id);
+       }
 }
 
 void __ext4_error(struct super_block *sb, const char *function,
@@ -628,8 +632,12 @@ void __ext4_abort(struct super_block *sb, const char *function,
                        jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
                save_error_info(sb, function, line);
        }
-       if (test_opt(sb, ERRORS_PANIC))
+       if (test_opt(sb, ERRORS_PANIC)) {
+               if (EXT4_SB(sb)->s_journal &&
+                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
+                       return;
                panic("EXT4-fs panic from previous error\n");
+       }
 }
 
 void ext4_msg(struct super_block *sb, const char *prefix, const char *fmt, ...)
@@ -857,6 +865,7 @@ static void ext4_put_super(struct super_block *sb)
                dump_orphan_list(sb, sbi);
        J_ASSERT(list_empty(&sbi->s_orphan));
 
+       sync_blockdev(sb->s_bdev);
        invalidate_bdev(sb->s_bdev);
        if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
                /*
@@ -1017,10 +1026,10 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
        }
 
        if (sbi->s_qf_names[USRQUOTA])
-               seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+               seq_show_option(seq, "usrjquota", sbi->s_qf_names[USRQUOTA]);
 
        if (sbi->s_qf_names[GRPQUOTA])
-               seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+               seq_show_option(seq, "grpjquota", sbi->s_qf_names[GRPQUOTA]);
 
        if (test_opt(sb, USRQUOTA))
                seq_puts(seq, ",usrquota");
index 6b08864..c9e18f3 100644 (file)
@@ -196,8 +196,9 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
                goto out_err;
        }
        /* copy the full handle */
-       if (copy_from_user(handle, ufh,
-                          sizeof(struct file_handle) +
+       *handle = f_handle;
+       if (copy_from_user(&handle->f_handle,
+                          &ufh->f_handle,
                           f_handle.handle_bytes)) {
                retval = -EFAULT;
                goto out_handle;
index e028b8e..6f4e4ed 100644 (file)
@@ -22,6 +22,7 @@ static LIST_HEAD(fscache_netfs_list);
 int __fscache_register_netfs(struct fscache_netfs *netfs)
 {
        struct fscache_netfs *ptr;
+       struct fscache_cookie *cookie;
        int ret;
 
        _enter("{%s}", netfs->name);
@@ -29,27 +30,23 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
        INIT_LIST_HEAD(&netfs->link);
 
        /* allocate a cookie for the primary index */
-       netfs->primary_index =
-               kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
+       cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
 
-       if (!netfs->primary_index) {
+       if (!cookie) {
                _leave(" = -ENOMEM");
                return -ENOMEM;
        }
 
        /* initialise the primary index cookie */
-       atomic_set(&netfs->primary_index->usage, 1);
-       atomic_set(&netfs->primary_index->n_children, 0);
+       atomic_set(&cookie->usage, 1);
+       atomic_set(&cookie->n_children, 0);
 
-       netfs->primary_index->def               = &fscache_fsdef_netfs_def;
-       netfs->primary_index->parent            = &fscache_fsdef_index;
-       netfs->primary_index->netfs_data        = netfs;
+       cookie->def             = &fscache_fsdef_netfs_def;
+       cookie->parent          = &fscache_fsdef_index;
+       cookie->netfs_data      = netfs;
 
-       atomic_inc(&netfs->primary_index->parent->usage);
-       atomic_inc(&netfs->primary_index->parent->n_children);
-
-       spin_lock_init(&netfs->primary_index->lock);
-       INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
+       spin_lock_init(&cookie->lock);
+       INIT_HLIST_HEAD(&cookie->backing_objects);
 
        /* check the netfs type is not already present */
        down_write(&fscache_addremove_sem);
@@ -60,6 +57,10 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
                        goto already_registered;
        }
 
+       atomic_inc(&cookie->parent->usage);
+       atomic_inc(&cookie->parent->n_children);
+
+       netfs->primary_index = cookie;
        list_add(&netfs->link, &fscache_netfs_list);
        ret = 0;
 
@@ -69,11 +70,8 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
 already_registered:
        up_write(&fscache_addremove_sem);
 
-       if (ret < 0) {
-               netfs->primary_index->parent = NULL;
-               __fscache_cookie_put(netfs->primary_index);
-               netfs->primary_index = NULL;
-       }
+       if (ret < 0)
+               kmem_cache_free(fscache_cookie_jar, cookie);
 
        _leave(" = %d", ret);
        return ret;
index 3f7a59b..c9d52e1 100644 (file)
@@ -676,7 +676,7 @@ static void fscache_write_op(struct fscache_operation *_op)
                goto superseded;
        page = results[0];
        _debug("gang %d [%lx]", n, page->index);
-       if (page->index > op->store_limit) {
+       if (page->index >= op->store_limit) {
                fscache_stat(&fscache_n_store_pages_over_limit);
                goto superseded;
        }
index afc0f70..e613870 100644 (file)
@@ -993,6 +993,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
                goto err_fput;
 
        fuse_conn_init(fc);
+       fc->release = fuse_free_conn;
 
        fc->dev = sb->s_dev;
        fc->sb = sb;
@@ -1007,7 +1008,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
                fc->dont_mask = 1;
        sb->s_flags |= MS_POSIXACL;
 
-       fc->release = fuse_free_conn;
        fc->flags = d.flags;
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
index 71e4209..be2ece5 100644 (file)
@@ -1298,11 +1298,11 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir))
                seq_printf(s, ",meta");
        if (args->ar_lockproto[0])
-               seq_printf(s, ",lockproto=%s", args->ar_lockproto);
+               seq_show_option(s, "lockproto", args->ar_lockproto);
        if (args->ar_locktable[0])
-               seq_printf(s, ",locktable=%s", args->ar_locktable);
+               seq_show_option(s, "locktable", args->ar_locktable);
        if (args->ar_hostdata[0])
-               seq_printf(s, ",hostdata=%s", args->ar_hostdata);
+               seq_show_option(s, "hostdata", args->ar_hostdata);
        if (args->ar_spectator)
                seq_printf(s, ",spectator");
        if (args->ar_localflocks)
index cdb41a1..8daea16 100644 (file)
@@ -287,7 +287,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
                        page_cache_release(page);
                        goto fail;
                }
-               page_cache_release(page);
                node->page[i] = page;
        }
 
@@ -397,11 +396,11 @@ node_error:
 
 void hfs_bnode_free(struct hfs_bnode *node)
 {
-       //int i;
+       int i;
 
-       //for (i = 0; i < node->tree->pages_per_bnode; i++)
-       //      if (node->page[i])
-       //              page_cache_release(node->page[i]);
+       for (i = 0; i < node->tree->pages_per_bnode; i++)
+               if (node->page[i])
+                       page_cache_release(node->page[i]);
        kfree(node);
 }
 
index 92fb358..db240c5 100644 (file)
@@ -132,13 +132,16 @@ skip:
        hfs_bnode_write(node, entry, data_off + key_len, entry_len);
        hfs_bnode_dump(node);
 
-       if (new_node) {
-               /* update parent key if we inserted a key
-                * at the start of the first node
-                */
-               if (!rec && new_node != node)
-                       hfs_brec_update_parent(fd);
+       /*
+        * update parent key if we inserted a key
+        * at the start of the node and it is not the new node
+        */
+       if (!rec && new_node != node) {
+               hfs_bnode_read_key(node, fd->search_key, data_off + size);
+               hfs_brec_update_parent(fd);
+       }
 
+       if (new_node) {
                hfs_bnode_put(fd->bnode);
                if (!new_node->parent) {
                        hfs_btree_inc_height(tree);
@@ -167,9 +170,6 @@ skip:
                goto again;
        }
 
-       if (!rec)
-               hfs_brec_update_parent(fd);
-
        return 0;
 }
 
@@ -366,6 +366,8 @@ again:
        if (IS_ERR(parent))
                return PTR_ERR(parent);
        __hfs_brec_find(parent, fd);
+       if (fd->record < 0)
+               return -ENOENT;
        hfs_bnode_dump(parent);
        rec = fd->record;
 
index 1b55f70..cac813d 100644 (file)
@@ -138,9 +138,9 @@ static int hfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
        struct hfs_sb_info *sbi = HFS_SB(mnt->mnt_sb);
 
        if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f))
-               seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator);
+               seq_show_option_n(seq, "creator", (char *)&sbi->s_creator, 4);
        if (sbi->s_type != cpu_to_be32(0x3f3f3f3f))
-               seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type);
+               seq_show_option_n(seq, "type", (char *)&sbi->s_type, 4);
        seq_printf(seq, ",uid=%u,gid=%u", sbi->s_uid, sbi->s_gid);
        if (sbi->s_file_umask != 0133)
                seq_printf(seq, ",file_umask=%o", sbi->s_file_umask);
index 1c42cc5..a1e9109 100644 (file)
@@ -454,7 +454,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
                        page_cache_release(page);
                        goto fail;
                }
-               page_cache_release(page);
                node->page[i] = page;
        }
 
@@ -566,13 +565,11 @@ node_error:
 
 void hfs_bnode_free(struct hfs_bnode *node)
 {
-#if 0
        int i;
 
        for (i = 0; i < node->tree->pages_per_bnode; i++)
                if (node->page[i])
                        page_cache_release(node->page[i]);
-#endif
        kfree(node);
 }
 
index bb62a58..c8d6b4f 100644 (file)
@@ -211,9 +211,9 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb);
 
        if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
-               seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
+               seq_show_option_n(seq, "creator", (char *)&sbi->creator, 4);
        if (sbi->type != HFSPLUS_DEF_CR_TYPE)
-               seq_printf(seq, ",type=%.4s", (char *)&sbi->type);
+               seq_show_option_n(seq, "type", (char *)&sbi->type, 4);
        seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask,
                sbi->uid, sbi->gid);
        if (sbi->part >= 0)
index 2f72da5..104e4d9 100644 (file)
@@ -265,7 +265,7 @@ static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
        size_t offset = strlen(root_ino) + 1;
 
        if (strlen(root_path) > offset)
-               seq_printf(seq, ",%s", root_path + offset);
+               seq_show_option(seq, root_path + offset, NULL);
 
        return 0;
 }
index 16a698b..e84393f 100644 (file)
@@ -478,80 +478,28 @@ out:
 
 int jbd2_cleanup_journal_tail(journal_t *journal)
 {
-       transaction_t * transaction;
        tid_t           first_tid;
-       unsigned long   blocknr, freed;
+       unsigned long   blocknr;
 
        if (is_journal_aborted(journal))
-               return 1;
-
-       /* OK, work out the oldest transaction remaining in the log, and
-        * the log block it starts at.
-        *
-        * If the log is now empty, we need to work out which is the
-        * next transaction ID we will write, and where it will
-        * start. */
+               return -EIO;
 
-       write_lock(&journal->j_state_lock);
-       spin_lock(&journal->j_list_lock);
-       transaction = journal->j_checkpoint_transactions;
-       if (transaction) {
-               first_tid = transaction->t_tid;
-               blocknr = transaction->t_log_start;
-       } else if ((transaction = journal->j_committing_transaction) != NULL) {
-               first_tid = transaction->t_tid;
-               blocknr = transaction->t_log_start;
-       } else if ((transaction = journal->j_running_transaction) != NULL) {
-               first_tid = transaction->t_tid;
-               blocknr = journal->j_head;
-       } else {
-               first_tid = journal->j_transaction_sequence;
-               blocknr = journal->j_head;
-       }
-       spin_unlock(&journal->j_list_lock);
-       J_ASSERT(blocknr != 0);
-
-       /* If the oldest pinned transaction is at the tail of the log
-           already then there's not much we can do right now. */
-       if (journal->j_tail_sequence == first_tid) {
-               write_unlock(&journal->j_state_lock);
+       if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr))
                return 1;
-       }
-
-       /* OK, update the superblock to recover the freed space.
-        * Physical blocks come first: have we wrapped beyond the end of
-        * the log?  */
-       freed = blocknr - journal->j_tail;
-       if (blocknr < journal->j_tail)
-               freed = freed + journal->j_last - journal->j_first;
-
-       trace_jbd2_cleanup_journal_tail(journal, first_tid, blocknr, freed);
-       jbd_debug(1,
-                 "Cleaning journal tail from %d to %d (offset %lu), "
-                 "freeing %lu\n",
-                 journal->j_tail_sequence, first_tid, blocknr, freed);
-
-       journal->j_free += freed;
-       journal->j_tail_sequence = first_tid;
-       journal->j_tail = blocknr;
-       write_unlock(&journal->j_state_lock);
+       J_ASSERT(blocknr != 0);
 
        /*
-        * If there is an external journal, we need to make sure that
-        * any data blocks that were recently written out --- perhaps
-        * by jbd2_log_do_checkpoint() --- are flushed out before we
-        * drop the transactions from the external journal.  It's
-        * unlikely this will be necessary, especially with a
-        * appropriately sized journal, but we need this to guarantee
-        * correctness.  Fortunately jbd2_cleanup_journal_tail()
-        * doesn't get called all that often.
+        * We need to make sure that any blocks that were recently written out
+        * --- perhaps by jbd2_log_do_checkpoint() --- are flushed out before
+        * we drop the transactions from the journal. It's unlikely this will
+        * be necessary, especially with an appropriately sized journal, but we
+        * need this to guarantee correctness.  Fortunately
+        * jbd2_cleanup_journal_tail() doesn't get called all that often.
         */
-       if ((journal->j_fs_dev != journal->j_dev) &&
-           (journal->j_flags & JBD2_BARRIER))
-               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
-       if (!(journal->j_flags & JBD2_ABORT))
-               jbd2_journal_update_superblock(journal, 1);
-       return 0;
+       if (journal->j_flags & JBD2_BARRIER)
+               blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
+
+       return __jbd2_update_log_tail(journal, first_tid, blocknr);
 }
 
 
@@ -561,14 +509,15 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
  * journal_clean_one_cp_list
  *
  * Find all the written-back checkpoint buffers in the given list and
- * release them.
+ * release them. If 'destroy' is set, clean all buffers unconditionally.
  *
  * Called with the journal locked.
  * Called with j_list_lock held.
  * Returns number of bufers reaped (for debug)
  */
 
-static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy,
+                                    int *released)
 {
        struct journal_head *last_jh;
        struct journal_head *next_jh = jh;
@@ -584,7 +533,10 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
                next_jh = jh->b_cpnext;
                /* Use trylock because of the ranking */
                if (jbd_trylock_bh_state(jh2bh(jh))) {
-                       ret = __try_to_free_cp_buf(jh);
+                       if (!destroy)
+                               ret = __try_to_free_cp_buf(jh);
+                       else
+                               ret = __jbd2_journal_remove_checkpoint(jh) + 1;
                        if (ret) {
                                freed++;
                                if (ret == 2) {
@@ -610,13 +562,14 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
  * journal_clean_checkpoint_list
  *
  * Find all the written-back checkpoint buffers in the journal and release them.
+ * If 'destroy' is set, release all buffers unconditionally.
  *
  * Called with the journal locked.
  * Called with j_list_lock held.
  * Returns number of buffers reaped (for debug)
  */
 
-int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
+int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
        int ret = 0;
@@ -632,7 +585,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
                ret += journal_clean_one_cp_list(transaction->
-                               t_checkpoint_list, &released);
+                               t_checkpoint_list, destroy, &released);
                /*
                 * This function only frees up some memory if possible so we
                 * dont have an obligation to finish processing. Bail out if
@@ -648,7 +601,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
                 * we can possibly see not yet submitted buffers on io_list
                 */
                ret += journal_clean_one_cp_list(transaction->
-                               t_checkpoint_io_list, &released);
+                               t_checkpoint_io_list, destroy, &released);
                if (need_resched())
                        goto out;
        } while (transaction != last_transaction);
@@ -656,6 +609,28 @@ out:
        return ret;
 }
 
+/*
+ * Remove buffers from all checkpoint lists as journal is aborted and we just
+ * need to free memory
+ */
+void jbd2_journal_destroy_checkpoint(journal_t *journal)
+{
+       /*
+        * We loop because __jbd2_journal_clean_checkpoint_list() may abort
+        * early due to a need of rescheduling.
+        */
+       while (1) {
+               spin_lock(&journal->j_list_lock);
+               if (!journal->j_checkpoint_transactions) {
+                       spin_unlock(&journal->j_list_lock);
+                       break;
+               }
+               __jbd2_journal_clean_checkpoint_list(journal, true);
+               spin_unlock(&journal->j_list_lock);
+               cond_resched();
+       }
+}
+
 /*
  * journal_remove_checkpoint: called after a buffer has been committed
  * to disk (either by being write-back flushed to disk, or being
index ab9463a..45ae6ec 100644 (file)
@@ -340,7 +340,18 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        /* Do we need to erase the effects of a prior jbd2_journal_flush? */
        if (journal->j_flags & JBD2_FLUSHED) {
                jbd_debug(3, "super block updated\n");
-               jbd2_journal_update_superblock(journal, 1);
+               mutex_lock(&journal->j_checkpoint_mutex);
+               /*
+                * We hold j_checkpoint_mutex so tail cannot change under us.
+                * We don't need any special data guarantees for writing sb
+                * since journal is empty and it is ok for write to be
+                * flushed only with transaction commit.
+                */
+               jbd2_journal_update_sb_log_tail(journal,
+                                               journal->j_tail_sequence,
+                                               journal->j_tail,
+                                               WRITE_SYNC);
+               mutex_unlock(&journal->j_checkpoint_mutex);
        } else {
                jbd_debug(3, "superblock not updated\n");
        }
@@ -424,7 +435,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
         * frees some memory
         */
        spin_lock(&journal->j_list_lock);
-       __jbd2_journal_clean_checkpoint_list(journal);
+       __jbd2_journal_clean_checkpoint_list(journal, false);
        spin_unlock(&journal->j_list_lock);
 
        jbd_debug(3, "JBD2: commit phase 1\n");
index 17b04fc..c19b8ce 100644 (file)
@@ -775,6 +775,92 @@ struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal)
        return jbd2_journal_add_journal_head(bh);
 }
 
+/*
+ * Return tid of the oldest transaction in the journal and block in the journal
+ * where the transaction starts.
+ *
+ * If the journal is now empty, return which will be the next transaction ID
+ * we will write and where will that transaction start.
+ *
+ * The return value is 0 if journal tail cannot be pushed any further, 1 if
+ * it can.
+ */
+int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid,
+                             unsigned long *block)
+{
+       transaction_t *transaction;
+       int ret;
+
+       read_lock(&journal->j_state_lock);
+       spin_lock(&journal->j_list_lock);
+       transaction = journal->j_checkpoint_transactions;
+       if (transaction) {
+               *tid = transaction->t_tid;
+               *block = transaction->t_log_start;
+       } else if ((transaction = journal->j_committing_transaction) != NULL) {
+               *tid = transaction->t_tid;
+               *block = transaction->t_log_start;
+       } else if ((transaction = journal->j_running_transaction) != NULL) {
+               *tid = transaction->t_tid;
+               *block = journal->j_head;
+       } else {
+               *tid = journal->j_transaction_sequence;
+               *block = journal->j_head;
+       }
+       ret = tid_gt(*tid, journal->j_tail_sequence);
+       spin_unlock(&journal->j_list_lock);
+       read_unlock(&journal->j_state_lock);
+
+       return ret;
+}
+
+/*
+ * Update information in journal structure and in on disk journal superblock
+ * about log tail. This function does not check whether information passed in
+ * really pushes log tail further. It's responsibility of the caller to make
+ * sure provided log tail information is valid (e.g. by holding
+ * j_checkpoint_mutex all the time between computing log tail and calling this
+ * function as is the case with jbd2_cleanup_journal_tail()).
+ *
+ * Requires j_checkpoint_mutex
+ */
+int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
+{
+       unsigned long freed;
+       int ret;
+
+       BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
+
+       /*
+        * We cannot afford for write to remain in drive's caches since as
+        * soon as we update j_tail, next transaction can start reusing journal
+        * space and if we lose sb update during power failure we'd replay
+        * old transaction with possibly newly overwritten data.
+        */
+       ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA);
+       if (ret)
+               goto out;
+
+       write_lock(&journal->j_state_lock);
+       freed = block - journal->j_tail;
+       if (block < journal->j_tail)
+               freed += journal->j_last - journal->j_first;
+
+       trace_jbd2_update_log_tail(journal, tid, block, freed);
+       jbd_debug(1,
+                 "Cleaning journal tail from %d to %d (offset %lu), "
+                 "freeing %lu\n",
+                 journal->j_tail_sequence, tid, block, freed);
+
+       journal->j_free += freed;
+       journal->j_tail_sequence = tid;
+       journal->j_tail = block;
+       write_unlock(&journal->j_state_lock);
+
+out:
+       return ret;
+}
+
 struct jbd2_stats_proc_session {
        journal_t *journal;
        struct transaction_stats_s *stats;
@@ -1143,40 +1229,44 @@ static int journal_reset(journal_t *journal)
 
        journal->j_max_transaction_buffers = journal->j_maxlen / 4;
 
-       /* Add the dynamic fields and write it to disk. */
-       jbd2_journal_update_superblock(journal, 1);
-       return jbd2_journal_start_thread(journal);
-}
-
-/**
- * void jbd2_journal_update_superblock() - Update journal sb on disk.
- * @journal: The journal to update.
- * @wait: Set to '0' if you don't want to wait for IO completion.
- *
- * Update a journal's dynamic superblock fields and write it to disk,
- * optionally waiting for the IO to complete.
- */
-void jbd2_journal_update_superblock(journal_t *journal, int wait)
-{
-       journal_superblock_t *sb = journal->j_superblock;
-       struct buffer_head *bh = journal->j_sb_buffer;
-
        /*
         * As a special case, if the on-disk copy is already marked as needing
-        * no recovery (s_start == 0) and there are no outstanding transactions
-        * in the filesystem, then we can safely defer the superblock update
-        * until the next commit by setting JBD2_FLUSHED.  This avoids
+        * no recovery (s_start == 0), then we can safely defer the superblock
+        * update until the next commit by setting JBD2_FLUSHED.  This avoids
         * attempting a write to a potential-readonly device.
         */
-       if (sb->s_start == 0 && journal->j_tail_sequence ==
-                               journal->j_transaction_sequence) {
+       if (sb->s_start == 0) {
                jbd_debug(1, "JBD2: Skipping superblock update on recovered sb "
                        "(start %ld, seq %d, errno %d)\n",
                        journal->j_tail, journal->j_tail_sequence,
                        journal->j_errno);
-               goto out;
+               journal->j_flags |= JBD2_FLUSHED;
+       } else {
+               /* Lock here to make assertions happy... */
+               mutex_lock(&journal->j_checkpoint_mutex);
+               /*
+                * Update log tail information. We use WRITE_FUA since new
+                * transaction will start reusing journal space and so we
+                * must make sure information about current log tail is on
+                * disk before that.
+                */
+               jbd2_journal_update_sb_log_tail(journal,
+                                               journal->j_tail_sequence,
+                                               journal->j_tail,
+                                               WRITE_FUA);
+               mutex_unlock(&journal->j_checkpoint_mutex);
        }
+       return jbd2_journal_start_thread(journal);
+}
+
+static int jbd2_write_superblock(journal_t *journal, int write_op)
+{
+       struct buffer_head *bh = journal->j_sb_buffer;
+       int ret;
 
+       if (!(journal->j_flags & JBD2_BARRIER))
+               write_op &= ~(REQ_FUA | REQ_FLUSH);
+       lock_buffer(bh);
        if (buffer_write_io_error(bh)) {
                /*
                 * Oh, dear.  A previous attempt to write the journal
@@ -1192,48 +1282,114 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
                clear_buffer_write_io_error(bh);
                set_buffer_uptodate(bh);
        }
+       get_bh(bh);
+       bh->b_end_io = end_buffer_write_sync;
+       ret = submit_bh(write_op, bh);
+       wait_on_buffer(bh);
+       if (buffer_write_io_error(bh)) {
+               clear_buffer_write_io_error(bh);
+               set_buffer_uptodate(bh);
+               ret = -EIO;
+       }
+       if (ret) {
+               printk(KERN_ERR "JBD2: Error %d detected when updating "
+                      "journal superblock for %s.\n", ret,
+                      journal->j_devname);
+               jbd2_journal_abort(journal, ret);
+       }
 
+       return ret;
+}
+
+/**
+ * jbd2_journal_update_sb_log_tail() - Update log tail in journal sb on disk.
+ * @journal: The journal to update.
+ * @tail_tid: TID of the new transaction at the tail of the log
+ * @tail_block: The first block of the transaction at the tail of the log
+ * @write_op: With which operation should we write the journal sb
+ *
+ * Update a journal's superblock information about log tail and write it to
+ * disk, waiting for the IO to complete.
+ */
+int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
+                                    unsigned long tail_block, int write_op)
+{
+       journal_superblock_t *sb = journal->j_superblock;
+       int ret;
+
+       BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
+       jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
+                 tail_block, tail_tid);
+
+       sb->s_sequence = cpu_to_be32(tail_tid);
+       sb->s_start    = cpu_to_be32(tail_block);
+
+       ret = jbd2_write_superblock(journal, write_op);
+       if (ret)
+               goto out;
+       /* Log is no longer empty */
+       write_lock(&journal->j_state_lock);
+       WARN_ON(!sb->s_sequence);
+       journal->j_flags &= ~JBD2_FLUSHED;
+       write_unlock(&journal->j_state_lock);
+
+out:
+       return ret;
+}
+
+/**
+ * jbd2_mark_journal_empty() - Mark on disk journal as empty.
+ * @journal: The journal to update.
+ *
+ * Update a journal's dynamic superblock fields to show that journal is empty.
+ * Write updated superblock to disk waiting for IO to complete.
+ */
+static void jbd2_mark_journal_empty(journal_t *journal)
+{
+       journal_superblock_t *sb = journal->j_superblock;
+
+       BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
        read_lock(&journal->j_state_lock);
-       jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d, errno %d)\n",
-                 journal->j_tail, journal->j_tail_sequence, journal->j_errno);
+       jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
+                 journal->j_tail_sequence);
 
        sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
-       sb->s_start    = cpu_to_be32(journal->j_tail);
-       sb->s_errno    = cpu_to_be32(journal->j_errno);
+       sb->s_start    = cpu_to_be32(0);
        read_unlock(&journal->j_state_lock);
 
-       BUFFER_TRACE(bh, "marking dirty");
-       mark_buffer_dirty(bh);
-       if (wait) {
-               sync_dirty_buffer(bh);
-               if (buffer_write_io_error(bh)) {
-                       printk(KERN_ERR "JBD2: I/O error detected "
-                              "when updating journal superblock for %s.\n",
-                              journal->j_devname);
-                       clear_buffer_write_io_error(bh);
-                       set_buffer_uptodate(bh);
-               }
-       } else
-               write_dirty_buffer(bh, WRITE);
-
-out:
-       /* If we have just flushed the log (by marking s_start==0), then
-        * any future commit will have to be careful to update the
-        * superblock again to re-record the true start of the log. */
+       jbd2_write_superblock(journal, WRITE_FUA);
 
+       /* Log is no longer empty */
        write_lock(&journal->j_state_lock);
-       if (sb->s_start)
-               journal->j_flags &= ~JBD2_FLUSHED;
-       else
-               journal->j_flags |= JBD2_FLUSHED;
+       journal->j_flags |= JBD2_FLUSHED;
        write_unlock(&journal->j_state_lock);
 }
 
+
+/**
+ * jbd2_journal_update_sb_errno() - Update error in the journal.
+ * @journal: The journal to update.
+ *
+ * Update a journal's errno.  Write updated superblock to disk waiting for IO
+ * to complete.
+ */
+static void jbd2_journal_update_sb_errno(journal_t *journal)
+{
+       journal_superblock_t *sb = journal->j_superblock;
+
+       read_lock(&journal->j_state_lock);
+       jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
+                 journal->j_errno);
+       sb->s_errno    = cpu_to_be32(journal->j_errno);
+       read_unlock(&journal->j_state_lock);
+
+       jbd2_write_superblock(journal, WRITE_SYNC);
+}
+
 /*
  * Read the superblock for a given journal, performing initial
  * validation of the format.
  */
-
 static int journal_get_superblock(journal_t *journal)
 {
        struct buffer_head *bh;
@@ -1415,8 +1571,17 @@ int jbd2_journal_destroy(journal_t *journal)
        while (journal->j_checkpoint_transactions != NULL) {
                spin_unlock(&journal->j_list_lock);
                mutex_lock(&journal->j_checkpoint_mutex);
-               jbd2_log_do_checkpoint(journal);
+               err = jbd2_log_do_checkpoint(journal);
                mutex_unlock(&journal->j_checkpoint_mutex);
+               /*
+                * If checkpointing failed, just free the buffers to avoid
+                * looping forever
+                */
+               if (err) {
+                       jbd2_journal_destroy_checkpoint(journal);
+                       spin_lock(&journal->j_list_lock);
+                       break;
+               }
                spin_lock(&journal->j_list_lock);
        }
 
@@ -1427,14 +1592,11 @@ int jbd2_journal_destroy(journal_t *journal)
 
        if (journal->j_sb_buffer) {
                if (!is_journal_aborted(journal)) {
-                       /* We can now mark the journal as empty. */
-                       journal->j_tail = 0;
-                       journal->j_tail_sequence =
-                               ++journal->j_transaction_sequence;
-                       jbd2_journal_update_superblock(journal, 1);
-               } else {
+                       mutex_lock(&journal->j_checkpoint_mutex);
+                       jbd2_mark_journal_empty(journal);
+                       mutex_unlock(&journal->j_checkpoint_mutex);
+               } else
                        err = -EIO;
-               }
                brelse(journal->j_sb_buffer);
        }
 
@@ -1648,7 +1810,6 @@ int jbd2_journal_flush(journal_t *journal)
 {
        int err = 0;
        transaction_t *transaction = NULL;
-       unsigned long old_tail;
 
        write_lock(&journal->j_state_lock);
 
@@ -1683,28 +1844,32 @@ int jbd2_journal_flush(journal_t *journal)
        if (is_journal_aborted(journal))
                return -EIO;
 
-       jbd2_cleanup_journal_tail(journal);
+       mutex_lock(&journal->j_checkpoint_mutex);
+       if (!err) {
+               err = jbd2_cleanup_journal_tail(journal);
+               if (err < 0) {
+                       mutex_unlock(&journal->j_checkpoint_mutex);
+                       goto out;
+               }
+               err = 0;
+       }
 
        /* Finally, mark the journal as really needing no recovery.
         * This sets s_start==0 in the underlying superblock, which is
         * the magic code for a fully-recovered superblock.  Any future
         * commits of data to the journal will restore the current
         * s_start value. */
+       jbd2_mark_journal_empty(journal);
+       mutex_unlock(&journal->j_checkpoint_mutex);
        write_lock(&journal->j_state_lock);
-       old_tail = journal->j_tail;
-       journal->j_tail = 0;
-       write_unlock(&journal->j_state_lock);
-       jbd2_journal_update_superblock(journal, 1);
-       write_lock(&journal->j_state_lock);
-       journal->j_tail = old_tail;
-
        J_ASSERT(!journal->j_running_transaction);
        J_ASSERT(!journal->j_committing_transaction);
        J_ASSERT(!journal->j_checkpoint_transactions);
        J_ASSERT(journal->j_head == journal->j_tail);
        J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
        write_unlock(&journal->j_state_lock);
-       return 0;
+out:
+       return err;
 }
 
 /**
@@ -1737,8 +1902,12 @@ int jbd2_journal_wipe(journal_t *journal, int write)
                write ? "Clearing" : "Ignoring");
 
        err = jbd2_journal_skip_recovery(journal);
-       if (write)
-               jbd2_journal_update_superblock(journal, 1);
+       if (write) {
+               /* Lock to make assertions happy... */
+               mutex_lock(&journal->j_checkpoint_mutex);
+               jbd2_mark_journal_empty(journal);
+               mutex_unlock(&journal->j_checkpoint_mutex);
+       }
 
  no_recovery:
        return err;
@@ -1787,8 +1956,12 @@ static void __journal_abort_soft (journal_t *journal, int errno)
 
        __jbd2_journal_abort_hard(journal);
 
-       if (errno)
-               jbd2_journal_update_superblock(journal, 1);
+       if (errno) {
+               jbd2_journal_update_sb_errno(journal);
+               write_lock(&journal->j_state_lock);
+               journal->j_flags |= JBD2_REC_ERR;
+               write_unlock(&journal->j_state_lock);
+       }
 }
 
 /**
index da6d7ba..875df5f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/crc32.h>
+#include <linux/blkdev.h>
 #endif
 
 /*
@@ -265,7 +266,9 @@ int jbd2_journal_recover(journal_t *journal)
        err2 = sync_blockdev(journal->j_fs_dev);
        if (!err)
                err = err2;
-
+       /* Make sure all replayed data is on permanent storage */
+       if (journal->j_flags & JBD2_BARRIER)
+               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
        return err;
 }
 
@@ -711,11 +714,16 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 {
        jbd2_journal_revoke_header_t *header;
        int offset, max;
+       __u32 rcount;
        int record_len = 4;
 
        header = (jbd2_journal_revoke_header_t *) bh->b_data;
        offset = sizeof(jbd2_journal_revoke_header_t);
-       max = be32_to_cpu(header->r_count);
+       rcount = be32_to_cpu(header->r_count);
+
+       if (rcount > journal->j_blocksize)
+               return -EINVAL;
+       max = rcount;
 
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
                record_len = 8;
index 8aa28cd..9af0125 100644 (file)
@@ -398,6 +398,24 @@ void path_put(struct path *path)
 }
 EXPORT_SYMBOL(path_put);
 
+/**
+ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root
+ * @path: nameidate to verify
+ *
+ * Rename can sometimes move a file or directory outside of a bind
+ * mount, path_connected allows those cases to be detected.
+ */
+static bool path_connected(const struct path *path)
+{
+       struct vfsmount *mnt = path->mnt;
+
+       /* Only bind mounts can have disconnected paths */
+       if (mnt->mnt_root == mnt->mnt_sb->s_root)
+               return true;
+
+       return is_subdir(path->dentry, mnt->mnt_root);
+}
+
 /*
  * Path walking has 2 modes, rcu-walk and ref-walk (see
  * Documentation/filesystems/path-lookup.txt).  In situations when we can't
@@ -933,6 +951,8 @@ static int follow_dotdot_rcu(struct nameidata *nd)
                                goto failed;
                        nd->path.dentry = parent;
                        nd->seq = seq;
+                       if (unlikely(!path_connected(&nd->path)))
+                               goto failed;
                        break;
                }
                if (!follow_up_rcu(&nd->path))
@@ -1027,7 +1047,7 @@ static void follow_mount(struct path *path)
        }
 }
 
-static void follow_dotdot(struct nameidata *nd)
+static int follow_dotdot(struct nameidata *nd)
 {
        if (!nd->root.mnt)
                set_root(nd);
@@ -1043,6 +1063,10 @@ static void follow_dotdot(struct nameidata *nd)
                        /* rare case of legitimate dget_parent()... */
                        nd->path.dentry = dget_parent(nd->path.dentry);
                        dput(old);
+                       if (unlikely(!path_connected(&nd->path))) {
+                               path_put(&nd->path);
+                               return -ENOENT;
+                       }
                        break;
                }
                if (!follow_up(&nd->path))
@@ -1050,6 +1074,7 @@ static void follow_dotdot(struct nameidata *nd)
        }
        follow_mount(&nd->path);
        nd->inode = nd->path.dentry->d_inode;
+       return 0;
 }
 
 /*
@@ -1241,7 +1266,7 @@ static inline int handle_dots(struct nameidata *nd, int type)
                        if (follow_dotdot_rcu(nd))
                                return -ECHILD;
                } else
-                       follow_dotdot(nd);
+                       return follow_dotdot(nd);
        }
        return 0;
 }
index 183c6b1..bee14a3 100644 (file)
@@ -1333,7 +1333,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
        if (args->npages != 0)
                xdr_write_pages(xdr, args->pages, 0, args->len);
        else
-               xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE);
+               xdr_reserve_space(xdr, args->len);
 
        error = nfsacl_encode(xdr->buf, base, args->inode,
                            (args->mask & NFS_ACL) ?
index e83786f..609a951 100644 (file)
@@ -1793,7 +1793,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode
        if (server->caps & NFS_CAP_POSIX_LOCK)
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
-       if (opendata->o_arg.open_flags & O_EXCL) {
+       if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
                nfs4_exclusive_attrset(opendata, sattr);
 
                nfs_fattr_init(opendata->o_res.f_attr);
index ce4168a..c4c8243 100644 (file)
@@ -1192,6 +1192,8 @@ restart:
                                }
                                spin_unlock(&state->state_lock);
                                nfs4_put_open_state(state);
+                               clear_bit(NFS_STATE_RECLAIM_NOGRACE,
+                                       &state->flags);
                                goto restart;
                        }
                }
index 6e91f8b..d455ea0 100644 (file)
@@ -3272,10 +3272,17 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_sess
        return nfserr_old_stateid;
 }
 
+static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols)
+{
+       if (ols->st_stateowner->so_is_open_owner &&
+           !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+               return nfserr_bad_stateid;
+       return nfs_ok;
+}
+
 __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 {
        struct nfs4_stid *s;
-       struct nfs4_ol_stateid *ols;
        __be32 status;
 
        if (STALE_STATEID(stateid))
@@ -3289,11 +3296,7 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
                return status;
        if (!(s->sc_type & (NFS4_OPEN_STID | NFS4_LOCK_STID)))
                return nfs_ok;
-       ols = openlockstateid(s);
-       if (ols->st_stateowner->so_is_open_owner
-           && !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
-               return nfserr_bad_stateid;
-       return nfs_ok;
+       return nfsd4_check_openowner_confirmed(openlockstateid(s));
 }
 
 static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
@@ -3360,8 +3363,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                status = nfs4_check_fh(current_fh, stp);
                if (status)
                        goto out;
-               if (stp->st_stateowner->so_is_open_owner
-                   && !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+               status = nfsd4_check_openowner_confirmed(stp);
+               if (status)
                        goto out;
                status = nfs4_check_openmode(stp, flags);
                if (status)
index ecdbae1..090d8ce 100644 (file)
@@ -388,7 +388,7 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
        nchildren = nilfs_btree_node_get_nchildren(node);
 
        if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
-                    level > NILFS_BTREE_LEVEL_MAX ||
+                    level >= NILFS_BTREE_LEVEL_MAX ||
                     nchildren < 0 ||
                     nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
                pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
index dbc372e..8e48ba5 100644 (file)
@@ -729,6 +729,19 @@ lookup:
        if (tmpres) {
                spin_unlock(&dlm->spinlock);
                spin_lock(&tmpres->spinlock);
+
+               /*
+                * Right after dlm spinlock was released, dlm_thread could have
+                * purged the lockres. Check if lockres got unhashed. If so
+                * start over.
+                */
+               if (hlist_unhashed(&tmpres->hash_node)) {
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
+               }
+
                /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
@@ -1398,6 +1411,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
        int found, ret;
        int set_maybe;
        int dispatch_assert = 0;
+       int dispatched = 0;
 
        if (!dlm_grab(dlm))
                return DLM_MASTER_RESP_NO;
@@ -1604,13 +1618,16 @@ send_response:
                        mlog(ML_ERROR, "failed to dispatch assert master work\n");
                        response = DLM_MASTER_RESP_ERROR;
                        dlm_lockres_put(res);
+               } else {
+                       dispatched = 1;
                }
        } else {
                if (res)
                        dlm_lockres_put(res);
        }
 
-       dlm_put(dlm);
+       if (!dispatched)
+               dlm_put(dlm);
        return response;
 }
 
@@ -2028,7 +2045,6 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
 
 
        /* queue up work for dlm_assert_master_worker */
-       dlm_grab(dlm);  /* get an extra ref for the work item */
        dlm_init_work_item(dlm, item, dlm_assert_master_worker, NULL);
        item->u.am.lockres = res; /* already have a ref */
        /* can optionally ignore node numbers higher than this node */
index d15b071..0e5013e 100644 (file)
@@ -1689,6 +1689,7 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
        unsigned int hash;
        int master = DLM_LOCK_RES_OWNER_UNKNOWN;
        u32 flags = DLM_ASSERT_MASTER_REQUERY;
+       int dispatched = 0;
 
        if (!dlm_grab(dlm)) {
                /* since the domain has gone away on this
@@ -1710,6 +1711,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
                                mlog_errno(-ENOMEM);
                                /* retry!? */
                                BUG();
+                       } else {
+                               dispatched = 1;
                        }
                } else /* put.. incase we are not the master */
                        dlm_lockres_put(res);
@@ -1717,7 +1720,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
        }
        spin_unlock(&dlm->spinlock);
 
-       dlm_put(dlm);
+       if (!dispatched)
+               dlm_put(dlm);
        return master;
 }
 
index 231eab2..b5e457c 100644 (file)
@@ -3968,9 +3968,13 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
        osb->dc_work_sequence = osb->dc_wake_sequence;
 
        processed = osb->blocked_lock_count;
-       while (processed) {
-               BUG_ON(list_empty(&osb->blocked_lock_list));
-
+       /*
+        * blocked lock processing in this loop might call iput which can
+        * remove items off osb->blocked_lock_list. Downconvert up to
+        * 'processed' number of locks, but stop short if we had some
+        * removed in ocfs2_mark_lockres_freeing when downconverting.
+        */
+       while (processed && !list_empty(&osb->blocked_lock_list)) {
                lockres = list_entry(osb->blocked_lock_list.next,
                                     struct ocfs2_lock_res, l_blocked_list);
                list_del_init(&lockres->l_blocked_list);
index 4994f8b..5fe6b1e 100644 (file)
@@ -1583,8 +1583,8 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
                seq_printf(s, ",localflocks,");
 
        if (osb->osb_cluster_stack[0])
-               seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
-                          osb->osb_cluster_stack);
+               seq_show_option_n(s, "cluster_stack", osb->osb_cluster_stack,
+                                 OCFS2_STACK_LABEL_LEN);
        if (opts & OCFS2_MOUNT_USRQUOTA)
                seq_printf(s, ",usrquota");
        if (opts & OCFS2_MOUNT_GRPQUOTA)
index e043c4c..f58f1c4 100644 (file)
@@ -361,7 +361,7 @@ nomem:
 }
 
 enum {
-       Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask
+       Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, Opt_err
 };
 
 static const match_table_t tokens = {
@@ -370,6 +370,7 @@ static const match_table_t tokens = {
        {Opt_umask, "umask=%o"},
        {Opt_dmask, "dmask=%o"},
        {Opt_fmask, "fmask=%o"},
+       {Opt_err, NULL},
 };
 
 static int parse_options(char *options, struct omfs_sb_info *sbi)
index 8ca88fc..d2cbeff 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -103,25 +103,27 @@ void pipe_wait(struct pipe_inode_info *pipe)
 }
 
 static int
-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,
-                       int atomic)
+pipe_iov_copy_from_user(void *addr, int *offset, struct iovec *iov,
+                       size_t *remaining, int atomic)
 {
        unsigned long copy;
 
-       while (len > 0) {
+       while (*remaining > 0) {
                while (!iov->iov_len)
                        iov++;
-               copy = min_t(unsigned long, len, iov->iov_len);
+               copy = min_t(unsigned long, *remaining, iov->iov_len);
 
                if (atomic) {
-                       if (__copy_from_user_inatomic(to, iov->iov_base, copy))
+                       if (__copy_from_user_inatomic(addr + *offset,
+                                                     iov->iov_base, copy))
                                return -EFAULT;
                } else {
-                       if (copy_from_user(to, iov->iov_base, copy))
+                       if (copy_from_user(addr + *offset,
+                                          iov->iov_base, copy))
                                return -EFAULT;
                }
-               to += copy;
-               len -= copy;
+               *offset += copy;
+               *remaining -= copy;
                iov->iov_base += copy;
                iov->iov_len -= copy;
        }
@@ -129,25 +131,27 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,
 }
 
 static int
-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,
-                     int atomic)
+pipe_iov_copy_to_user(struct iovec *iov, void *addr, int *offset,
+                     size_t *remaining, int atomic)
 {
        unsigned long copy;
 
-       while (len > 0) {
+       while (*remaining > 0) {
                while (!iov->iov_len)
                        iov++;
-               copy = min_t(unsigned long, len, iov->iov_len);
+               copy = min_t(unsigned long, *remaining, iov->iov_len);
 
                if (atomic) {
-                       if (__copy_to_user_inatomic(iov->iov_base, from, copy))
+                       if (__copy_to_user_inatomic(iov->iov_base,
+                                                   addr + *offset, copy))
                                return -EFAULT;
                } else {
-                       if (copy_to_user(iov->iov_base, from, copy))
+                       if (copy_to_user(iov->iov_base,
+                                        addr + *offset, copy))
                                return -EFAULT;
                }
-               from += copy;
-               len -= copy;
+               *offset += copy;
+               *remaining -= copy;
                iov->iov_base += copy;
                iov->iov_len -= copy;
        }
@@ -383,7 +387,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
                        struct pipe_buffer *buf = pipe->bufs + curbuf;
                        const struct pipe_buf_operations *ops = buf->ops;
                        void *addr;
-                       size_t chars = buf->len;
+                       size_t chars = buf->len, remaining;
                        int error, atomic;
 
                        if (chars > total_len)
@@ -397,9 +401,11 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
                        }
 
                        atomic = !iov_fault_in_pages_write(iov, chars);
+                       remaining = chars;
 redo:
                        addr = ops->map(pipe, buf, atomic);
-                       error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic);
+                       error = pipe_iov_copy_to_user(iov, addr, &buf->offset,
+                                                     &remaining, atomic);
                        ops->unmap(pipe, buf, addr);
                        if (unlikely(error)) {
                                /*
@@ -414,7 +420,6 @@ redo:
                                break;
                        }
                        ret += chars;
-                       buf->offset += chars;
                        buf->len -= chars;
 
                        /* Was it a packet buffer? Clean up and exit */
@@ -521,6 +526,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
                if (ops->can_merge && offset + chars <= PAGE_SIZE) {
                        int error, atomic = 1;
                        void *addr;
+                       size_t remaining = chars;
 
                        error = ops->confirm(pipe, buf);
                        if (error)
@@ -529,8 +535,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
                        iov_fault_in_pages_read(iov, chars);
 redo1:
                        addr = ops->map(pipe, buf, atomic);
-                       error = pipe_iov_copy_from_user(offset + addr, iov,
-                                                       chars, atomic);
+                       error = pipe_iov_copy_from_user(addr, &offset, iov,
+                                                       &remaining, atomic);
                        ops->unmap(pipe, buf, addr);
                        ret = error;
                        do_wakeup = 1;
@@ -565,6 +571,8 @@ redo1:
                        struct page *page = pipe->tmp_page;
                        char *src;
                        int error, atomic = 1;
+                       int offset = 0;
+                       size_t remaining;
 
                        if (!page) {
                                page = alloc_page(GFP_HIGHUSER);
@@ -585,14 +593,15 @@ redo1:
                                chars = total_len;
 
                        iov_fault_in_pages_read(iov, chars);
+                       remaining = chars;
 redo2:
                        if (atomic)
                                src = kmap_atomic(page, KM_USER0);
                        else
                                src = kmap(page);
 
-                       error = pipe_iov_copy_from_user(src, iov, chars,
-                                                       atomic);
+                       error = pipe_iov_copy_from_user(src, &offset, iov,
+                                                       &remaining, atomic);
                        if (atomic)
                                kunmap_atomic(src, KM_USER0);
                        else
index bc02b6b..8e1b444 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/rmap.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
+#include <linux/security.h>
 
 #include <asm/elf.h>
 #include <asm/uaccess.h>
@@ -831,6 +832,7 @@ const struct file_operations proc_clear_refs_operations = {
 struct pagemapread {
        int pos, len;           /* units: PM_ENTRY_BYTES, not bytes */
        u64 *buffer;
+       bool show_pfn;
 };
 
 #define PM_ENTRY_BYTES      sizeof(u64)
@@ -879,14 +881,14 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte)
        return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
 }
 
-static u64 pte_to_pagemap_entry(pte_t pte)
+static u64 pte_to_pagemap_entry(struct pagemapread *pm, pte_t pte)
 {
        u64 pme = 0;
        if (is_swap_pte(pte))
                pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte))
                        | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
        else if (pte_present(pte))
-               pme = PM_PFRAME(pte_pfn(pte))
+               pme = (pm->show_pfn ? PM_PFRAME(pte_pfn(pte)) : 0)
                        | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
        return pme;
 }
@@ -918,7 +920,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                if (vma && (vma->vm_start <= addr) &&
                    !is_vm_hugetlb_page(vma)) {
                        pte = pte_offset_map(pmd, addr);
-                       pfn = pte_to_pagemap_entry(*pte);
+                       pfn = pte_to_pagemap_entry(pm, *pte);
                        /* unmap before userspace copy */
                        pte_unmap(pte);
                }
@@ -933,11 +935,11 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 }
 
 #ifdef CONFIG_HUGETLB_PAGE
-static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset)
+static u64 huge_pte_to_pagemap_entry(struct pagemapread *pm, pte_t pte, int offset)
 {
        u64 pme = 0;
        if (pte_present(pte))
-               pme = PM_PFRAME(pte_pfn(pte) + offset)
+               pme = (pm->show_pfn ? PM_PFRAME(pte_pfn(pte) + offset) : 0)
                        | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
        return pme;
 }
@@ -953,7 +955,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
 
        for (; addr != end; addr += PAGE_SIZE) {
                int offset = (addr & ~hmask) >> PAGE_SHIFT;
-               pfn = huge_pte_to_pagemap_entry(*pte, offset);
+               pfn = huge_pte_to_pagemap_entry(pm, *pte, offset);
                err = add_to_pagemap(addr, pfn, pm);
                if (err)
                        return err;
@@ -1017,6 +1019,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        if (!count)
                goto out_task;
 
+       /* do not disclose physical addresses: attack vector */
+       pm.show_pfn = !security_capable(&init_user_ns, file->f_cred, 
+                                       CAP_SYS_ADMIN);
+
        pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
        pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY);
        ret = -ENOMEM;
index cdaa7ad..3f2d8af 100644 (file)
@@ -1189,7 +1189,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
        long ret, bytes;
        umode_t i_mode;
        size_t len;
-       int i, flags;
+       int i, flags, more;
 
        /*
         * We require the input being a regular file, as we don't want to
@@ -1232,6 +1232,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
         * Don't block on output, we have to drain the direct pipe.
         */
        sd->flags &= ~SPLICE_F_NONBLOCK;
+       more = sd->flags & SPLICE_F_MORE;
 
        while (len) {
                size_t read_len;
@@ -1244,6 +1245,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
                read_len = ret;
                sd->total_len = read_len;
 
+               /*
+                * If more data is pending, set SPLICE_F_MORE
+                * If this is the last data and SPLICE_F_MORE was not set
+                * initially, clears it.
+                */
+               if (read_len < len)
+                       sd->flags |= SPLICE_F_MORE;
+               else if (!more)
+                       sd->flags &= ~SPLICE_F_MORE;
                /*
                 * NOTE: nonblocking mode only applies to the input. We
                 * must not do the output in nonblocking mode as then we
index b367581..c2b06d4 100644 (file)
@@ -365,7 +365,8 @@ xfs_end_bio(
        xfs_ioend_t             *ioend = bio->bi_private;
 
        ASSERT(atomic_read(&bio->bi_cnt) >= 1);
-       ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
+       if (!ioend->io_error && !test_bit(BIO_UPTODATE, &bio->bi_flags))
+               ioend->io_error = error;
 
        /* Toss bio and pass work off to an xfsdatad thread */
        bio->bi_private = NULL;
index 9c7d22f..c782906 100644 (file)
@@ -111,8 +111,15 @@ typedef struct xfs_attr_leaf_name_remote {
 typedef struct xfs_attr_leafblock {
        xfs_attr_leaf_hdr_t     hdr;    /* constant-structure header block */
        xfs_attr_leaf_entry_t   entries[1];     /* sorted on key, not name */
-       xfs_attr_leaf_name_local_t namelist;    /* grows from bottom of buf */
-       xfs_attr_leaf_name_remote_t valuelist;  /* grows from bottom of buf */
+       /*
+        * The rest of the block contains the following structures after the
+        * leaf entries, growing from the bottom up. The variables are never
+        * referenced and definining them can actually make gcc optimize away
+        * accesses to the 'entries' array above index 0 so don't do that.
+        *
+        * xfs_attr_leaf_name_local_t namelist;
+        * xfs_attr_leaf_name_remote_t valuelist;
+        */
 } xfs_attr_leafblock_t;
 
 /*
index 8a89949..90ccd1c 100644 (file)
@@ -533,9 +533,9 @@ xfs_showargs(
                seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
 
        if (mp->m_logname)
-               seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
+               seq_show_option(m, MNTOPT_LOGDEV, mp->m_logname);
        if (mp->m_rtname)
-               seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
+               seq_show_option(m, MNTOPT_RTDEV, mp->m_rtname);
 
        if (mp->m_dalign > 0)
                seq_printf(m, "," MNTOPT_SUNIT "=%d",
index f554a93..2ba218e 100644 (file)
@@ -125,7 +125,7 @@ void acpi_free(void *address);
  */
 acpi_status acpi_reallocate_root_table(void);
 
-acpi_status acpi_find_root_pointer(acpi_size *rsdp_address);
+acpi_status acpi_find_root_pointer(acpi_physical_address *rsdp_address);
 
 acpi_status acpi_load_tables(void);
 
index ed73f67..31a0f4b 100644 (file)
@@ -198,9 +198,29 @@ typedef int INT32;
 typedef s32 acpi_native_int;
 
 typedef u32 acpi_size;
+
+#ifdef ACPI_32BIT_PHYSICAL_ADDRESS
+
+/*
+ * OSPMs can define this to shrink the size of the structures for 32-bit
+ * none PAE environment. ASL compiler may always define this to generate
+ * 32-bit OSPM compliant tables.
+ */
 typedef u32 acpi_io_address;
 typedef u32 acpi_physical_address;
 
+#else                          /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+/*
+ * It is reported that, after some calculations, the physical addresses can
+ * wrap over the 32-bit boundary on 32-bit PAE environment.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=87971
+ */
+typedef u64 acpi_io_address;
+typedef u64 acpi_physical_address;
+
+#endif                         /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
 #define ACPI_MAX_PTR                    ACPI_UINT32_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
 
@@ -475,6 +495,7 @@ typedef u64 acpi_integer;
 #define ACPI_NO_ACPI_ENABLE             0x10
 #define ACPI_NO_DEVICE_INIT             0x20
 #define ACPI_NO_OBJECT_INIT             0x40
+#define ACPI_NO_FACS_INIT               0x80
 
 /*
  * Initialization state
index 5af3ed5..b9f9210 100644 (file)
@@ -75,6 +75,7 @@
 #define ACPI_CONSTANT_EVAL_ONLY
 #define ACPI_LARGE_NAMESPACE_NODE
 #define ACPI_DATA_TABLE_DISASSEMBLY
+#define ACPI_32BIT_PHYSICAL_ADDRESS
 #endif
 
 #ifdef ACPI_EXEC_APP
index 6001b4d..4e3ac03 100644 (file)
@@ -110,6 +110,12 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
 extern u32 acpi_irq_handled;
 extern u32 acpi_irq_not_handled;
+extern unsigned int acpi_sci_irq;
+#define INVALID_ACPI_IRQ       ((unsigned)-1)
+static inline bool acpi_sci_irq_valid(void)
+{
+       return acpi_sci_irq != INVALID_ACPI_IRQ;
+}
 
 extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
index 458f497..fed3f3a 100644 (file)
@@ -166,12 +166,13 @@ void __wait_on_buffer(struct buffer_head *);
 wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
 struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
                        unsigned size);
-struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
-                       unsigned size);
+struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
+                                 unsigned size, gfp_t gfp);
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
 void __breadahead(struct block_device *, sector_t block, unsigned int size);
-struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
+struct buffer_head *__bread_gfp(struct block_device *,
+                               sector_t block, unsigned size, gfp_t gfp);
 void invalidate_bh_lrus(void);
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
@@ -286,7 +287,13 @@ static inline void bforget(struct buffer_head *bh)
 static inline struct buffer_head *
 sb_bread(struct super_block *sb, sector_t block)
 {
-       return __bread(sb->s_bdev, block, sb->s_blocksize);
+       return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
+}
+
+static inline struct buffer_head *
+sb_bread_unmovable(struct super_block *sb, sector_t block)
+{
+       return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
 }
 
 static inline void
@@ -298,7 +305,14 @@ sb_breadahead(struct super_block *sb, sector_t block)
 static inline struct buffer_head *
 sb_getblk(struct super_block *sb, sector_t block)
 {
-       return __getblk(sb->s_bdev, block, sb->s_blocksize);
+       return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
+}
+
+
+static inline struct buffer_head *
+sb_getblk_gfp(struct super_block *sb, sector_t block, gfp_t gfp)
+{
+       return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, gfp);
 }
 
 static inline struct buffer_head *
@@ -335,6 +349,36 @@ static inline void lock_buffer(struct buffer_head *bh)
                __lock_buffer(bh);
 }
 
+static inline struct buffer_head *getblk_unmovable(struct block_device *bdev,
+                                                  sector_t block,
+                                                  unsigned size)
+{
+       return __getblk_gfp(bdev, block, size, 0);
+}
+
+static inline struct buffer_head *__getblk(struct block_device *bdev,
+                                          sector_t block,
+                                          unsigned size)
+{
+       return __getblk_gfp(bdev, block, size, __GFP_MOVABLE);
+}
+
+/**
+ *  __bread() - reads a specified block and returns the bh
+ *  @bdev: the block_device to read from
+ *  @block: number of block
+ *  @size: size (in bytes) to read
+ *
+ *  Reads a specified block, and returns buffer head that contains it.
+ *  The page cache is allocated from movable area so that it can be migrated.
+ *  It returns NULL if the block was unreadable.
+ */
+static inline struct buffer_head *
+__bread(struct block_device *bdev, sector_t block, unsigned size)
+{
+       return __bread_gfp(bdev, block, size, __GFP_MOVABLE);
+}
+
 extern int __set_page_dirty_buffers(struct page *page);
 
 #else /* CONFIG_BLOCK */
index fffdf00..2fe0d22 100644 (file)
@@ -83,6 +83,7 @@ struct fsl_usb2_platform_data {
 
        unsigned        suspended:1;
        unsigned        already_suspended:1;
+       unsigned        has_fsl_erratum_a005275:1;
 
        /* register save area for suspend/resume */
        u32             pm_command;
index a153ed5..f272051 100644 (file)
@@ -954,6 +954,7 @@ struct journal_s
 #define JBD2_ABORT_ON_SYNCDATA_ERR     0x040   /* Abort the journal on file
                                                 * data write error in ordered
                                                 * mode */
+#define JBD2_REC_ERR   0x080   /* The errno in the sb has been recorded */
 
 /*
  * Function declarations for the journaling transaction and buffer
@@ -972,13 +973,17 @@ extern void __journal_clean_data_list(transaction_t *transaction);
 /* Log buffer allocation */
 extern struct journal_head * jbd2_journal_get_descriptor_buffer(journal_t *);
 int jbd2_journal_next_log_block(journal_t *, unsigned long long *);
+int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid,
+                             unsigned long *block);
+int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
 
 /* Commit management */
 extern void jbd2_journal_commit_transaction(journal_t *);
 
 /* Checkpoint list management */
-int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
+int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
 int __jbd2_journal_remove_checkpoint(struct journal_head *);
+void jbd2_journal_destroy_checkpoint(journal_t *journal);
 void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
 
@@ -1083,7 +1088,8 @@ extern int           jbd2_journal_destroy    (journal_t *);
 extern int        jbd2_journal_recover    (journal_t *journal);
 extern int        jbd2_journal_wipe       (journal_t *, int);
 extern int        jbd2_journal_skip_recovery   (journal_t *);
-extern void       jbd2_journal_update_superblock       (journal_t *, int);
+extern int        jbd2_journal_update_sb_log_tail      (journal_t *, tid_t,
+                               unsigned long, int);
 extern void       __jbd2_journal_abort_hard    (journal_t *);
 extern void       jbd2_journal_abort      (journal_t *, int);
 extern int        jbd2_journal_errno      (journal_t *);
index 47cb09e..348c6f4 100644 (file)
@@ -145,11 +145,11 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
 }
 
 
-/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
-static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+/* __jhash_nwords - hash exactly 3, 2 or 1 word(s) */
+static inline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval)
 {
-       a += JHASH_INITVAL;
-       b += JHASH_INITVAL;
+       a += initval;
+       b += initval;
        c += initval;
 
        __jhash_final(a, b, c);
@@ -157,14 +157,19 @@ static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
        return c;
 }
 
+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+{
+       return __jhash_nwords(a, b, c, initval + JHASH_INITVAL + (3 << 2));
+}
+
 static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
 {
-       return jhash_3words(a, b, 0, initval);
+       return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2));
 }
 
 static inline u32 jhash_1word(u32 a, u32 initval)
 {
-       return jhash_3words(a, 0, 0, initval);
+       return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
 }
 
 #endif /* _LINUX_JHASH_H */
index 42ac6ad..000434e 100644 (file)
@@ -182,6 +182,7 @@ enum {
        ATA_LFLAG_DISABLED      = (1 << 6), /* link is disabled */
        ATA_LFLAG_SW_ACTIVITY   = (1 << 7), /* keep activity stats */
        ATA_LFLAG_NO_LPM        = (1 << 8), /* disable LPM on this link */
+       ATA_LFLAG_CHANGED       = (1 << 10), /* LPM state changed on this link */
 
        /* struct ata_port flags */
        ATA_FLAG_SLAVE_POSS     = (1 << 0), /* host supports slave dev */
@@ -284,6 +285,12 @@ enum {
         */
        ATA_TMOUT_PMP_SRST_WAIT = 5000,
 
+       /* When the LPM policy is set to ATA_LPM_MAX_POWER, there might
+        * be a spurious PHY event, so ignore the first PHY event that
+        * occurs within 10s after the policy change.
+        */
+       ATA_TMOUT_SPURIOUS_PHY  = 10000,
+
        /* ATA bus states */
        BUS_UNKNOWN             = 0,
        BUS_DMA                 = 1,
@@ -396,6 +403,8 @@ enum {
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
        ATA_HORKAGE_NOLPM       = (1 << 20),    /* don't use LPM */
        ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21),  /* some WDs have broken LPM */
+       ATA_HORKAGE_NOTRIM      = (1 << 24),    /* don't use TRIM */
+
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
@@ -728,6 +737,8 @@ struct ata_link {
        struct ata_eh_context   eh_context;
 
        struct ata_device       device[ATA_MAX_DEVICES];
+
+       unsigned long           last_lpm_change; /* when last LPM change happened */
 };
 #define ATA_LINK_CLEAR_BEGIN           offsetof(struct ata_link, active_tag)
 #define ATA_LINK_CLEAR_END             offsetof(struct ata_link, device[0])
@@ -1064,6 +1075,7 @@ extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
 extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
 extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q);
+extern bool sata_lpm_ignore_phy_events(struct ata_link *link);
 
 extern int ata_cable_40wire(struct ata_port *ap);
 extern int ata_cable_80wire(struct ata_port *ap);
index 41116ab..d2abc34 100644 (file)
@@ -1056,7 +1056,7 @@ struct nfs_impl_id4 {
        struct nfstime4 date;
 };
 
-#define NFS4_EXCHANGE_ID_LEN   (48)
+#define NFS4_EXCHANGE_ID_LEN   (127)
 struct nfs41_exchange_id_args {
        struct nfs_client               *client;
        nfs4_verifier                   *verifier;
index 7454ad7..d4d512f 100644 (file)
@@ -457,7 +457,7 @@ struct nilfs_btree_node {
 /* level */
 #define NILFS_BTREE_LEVEL_DATA          0
 #define NILFS_BTREE_LEVEL_NODE_MIN      (NILFS_BTREE_LEVEL_DATA + 1)
-#define NILFS_BTREE_LEVEL_MAX           14
+#define NILFS_BTREE_LEVEL_MAX           14     /* Max level (exclusive) */
 
 /**
  * struct nilfs_palloc_group_desc - block group descriptor
index 9bf9611..c81ef31 100644 (file)
@@ -211,6 +211,9 @@ extern int of_property_read_string(struct device_node *np,
 extern int of_property_read_string_index(struct device_node *np,
                                         const char *propname,
                                         int index, const char **output);
+extern int of_property_match_string(struct device_node *np,
+                                   const char *propname,
+                                   const char *string);
 extern int of_property_count_strings(struct device_node *np,
                                     const char *propname);
 extern int of_device_is_compatible(const struct device_node *device,
@@ -315,6 +318,13 @@ static inline int of_property_read_u64(const struct device_node *np,
        return -ENOSYS;
 }
 
+static inline int of_property_match_string(struct device_node *np,
+                                          const char *propname,
+                                          const char *string)
+{
+       return -ENOSYS;
+}
+
 static inline struct device_node *of_parse_phandle(struct device_node *np,
                                                   const char *phandle_name,
                                                   int index)
index fe76a74..f0c4495 100644 (file)
@@ -176,6 +176,8 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
        /* Provide indication device is assigned by a Virtual Machine Manager */
        PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
+       /* Get VPD from function 0 VPD */
+       PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
 };
 
 enum pci_irq_reroute_variant {
index 95d15ce..9b9ac29 100644 (file)
@@ -2347,15 +2347,15 @@ static inline bool thread_group_leader(struct task_struct *p)
  * all we care about is that we have a task with the appropriate
  * pid, we don't actually care if we have the right task.
  */
-static inline int has_group_leader_pid(struct task_struct *p)
+static inline bool has_group_leader_pid(struct task_struct *p)
 {
-       return p->pid == p->tgid;
+       return task_pid(p) == p->signal->leader_pid;
 }
 
 static inline
-int same_thread_group(struct task_struct *p1, struct task_struct *p2)
+bool same_thread_group(struct task_struct *p1, struct task_struct *p2)
 {
-       return p1->tgid == p2->tgid;
+       return p1->signal == p2->signal;
 }
 
 static inline struct task_struct *next_thread(const struct task_struct *p)
index 0b69a46..8803d6e 100644 (file)
@@ -122,6 +122,41 @@ void *__seq_open_private(struct file *, const struct seq_operations *, int);
 int seq_open_private(struct file *, const struct seq_operations *, int);
 int seq_release_private(struct inode *, struct file *);
 
+/**
+ * seq_show_options - display mount options with appropriate escapes.
+ * @m: the seq_file handle
+ * @name: the mount option name
+ * @value: the mount option name's value, can be NULL
+ */
+static inline void seq_show_option(struct seq_file *m, const char *name,
+                                  const char *value)
+{
+       seq_putc(m, ',');
+       seq_escape(m, name, ",= \t\n\\");
+       if (value) {
+               seq_putc(m, '=');
+               seq_escape(m, value, ", \t\n\\");
+       }
+}
+
+/**
+ * seq_show_option_n - display mount options with appropriate escapes
+ *                    where @value must be a specific length.
+ * @m: the seq_file handle
+ * @name: the mount option name
+ * @value: the mount option name's value, cannot be NULL
+ * @length: the length of @value to display
+ *
+ * This is a macro since this uses "length" to define the size of the
+ * stack buffer.
+ */
+#define seq_show_option_n(m, name, value, length) {    \
+       char val_buf[length + 1];                       \
+       strncpy(val_buf, value, length);                \
+       val_buf[length] = '\0';                         \
+       seq_show_option(m, name, val_buf);              \
+}
+
 #define SEQ_START_TOKEN ((void *)1)
 
 /*
index 1b4ea29..d0c9e6d 100644 (file)
@@ -2045,6 +2045,9 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 {
        if (skb->ip_summed == CHECKSUM_COMPLETE)
                skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
+       else if (skb->ip_summed == CHECKSUM_PARTIAL &&
+                skb_checksum_start_offset(skb) < 0)
+               skb->ip_summed = CHECKSUM_NONE;
 }
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
@@ -2131,7 +2134,8 @@ extern int               skb_copy_datagram_iovec(const struct sk_buff *from,
                                               int size);
 extern int            skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
                                                        int hlen,
-                                                       struct iovec *iov);
+                                                       struct iovec *iov,
+                                                       int len);
 extern int            skb_copy_datagram_from_iovec(struct sk_buff *skb,
                                                    int offset,
                                                    const struct iovec *from,
index 22fac98..df3be8f 100644 (file)
@@ -38,7 +38,8 @@ extern int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 
 static inline void inet_ctl_sock_destroy(struct sock *sk)
 {
-       sk_release_kernel(sk);
+       if (sk)
+               sk_release_kernel(sk);
 }
 
 #endif
index 1ee535b..2c7c5a9 100644 (file)
@@ -138,6 +138,7 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
 }
 
 /* datagram.c */
+int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
 extern int             ip4_datagram_connect(struct sock *sk, 
                                             struct sockaddr *uaddr, int addr_len);
 
index 5735a0f..3907358 100644 (file)
@@ -217,7 +217,7 @@ extern void                 inet6_rt_notify(int event, struct rt6_info *rt,
                                                struct nl_info *info);
 
 extern void                    fib6_run_gc(unsigned long expires,
-                                           struct net *net);
+                                           struct net *net, bool force);
 
 extern void                    fib6_gc_cleanup(void);
 
index 416dcb0..b8b2e50 100644 (file)
@@ -1202,6 +1202,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
 
 extern int ip_vs_use_count_inc(void);
 extern void ip_vs_use_count_dec(void);
+extern int ip_vs_register_nl_ioctl(void);
+extern void ip_vs_unregister_nl_ioctl(void);
 extern int ip_vs_control_init(void);
 extern void ip_vs_control_cleanup(void);
 extern struct ip_vs_dest *
index a15432d..2cccd82 100644 (file)
@@ -209,6 +209,7 @@ extern struct sctp_globals {
        struct list_head addr_waitq;
        struct timer_list addr_wq_timer;
        struct list_head auto_asconf_splist;
+       /* Lock that protects both addr_waitq and auto_asconf_splist */
        spinlock_t addr_wq_lock;
 
        /* Lock that protects the local_addr_list writers */
@@ -355,6 +356,10 @@ struct sctp_sock {
        atomic_t pd_mode;
        /* Receive to here while partial delivery is in effect. */
        struct sk_buff_head pd_lobby;
+
+       /* These must be the last fields, as they will skipped on copies,
+        * like on accept and peeloff operations
+        */
        struct list_head auto_asconf_list;
        int do_auto_asconf;
 };
index 4f865df..7ee55e3 100644 (file)
@@ -43,7 +43,8 @@
 
 #define EMUPAGESIZE     4096
 #define MAXREQVOICES    8
-#define MAXPAGES        8192
+#define MAXPAGES0       4096   /* 32 bit mode */
+#define MAXPAGES1       8192   /* 31 bit mode */
 #define RESERVED        0
 #define NUM_MIDI        16
 #define NUM_G           64              /* use all channels */
@@ -52,8 +53,7 @@
 
 /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
 #define EMU10K1_DMA_MASK       0x7fffffffUL    /* 31bit */
-#define AUDIGY_DMA_MASK                0x7fffffffUL    /* 31bit FIXME - 32 should work? */
-                                               /* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK                0xffffffffUL    /* 32bit mode */
 
 #define TMEMSIZE        256*1024
 #define TMEMSIZEREG     4
 
 #define MAPB                   0x0d            /* Cache map B                                          */
 
-#define MAP_PTE_MASK           0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
-#define MAP_PTI_MASK           0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
+#define MAP_PTE_MASK0          0xfffff000      /* The 20 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK0          0x00000fff      /* The 12 bit index to one of the 4096 PTE dwords       */
+
+#define MAP_PTE_MASK1          0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK1          0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
 
 /* 0x0e, 0x0f: Not used */
 
@@ -1708,6 +1711,7 @@ struct snd_emu10k1 {
        unsigned short model;                   /* subsystem id */
        unsigned int card_type;                 /* EMU10K1_CARD_* */
        unsigned int ecard_ctrl;                /* ecard control bits */
+       unsigned int address_mode;              /* address mode */
        unsigned long dma_mask;                 /* PCI DMA mask */
        unsigned int delay_pcm_irq;             /* in samples */
        int max_cache_pages;                    /* max memory size / PAGE_SIZE */
index 898be3a..6d8f8fb 100644 (file)
 #define WM8904_MIC_REGS  2
 #define WM8904_GPIO_REGS 4
 #define WM8904_DRC_REGS  4
-#define WM8904_EQ_REGS   25
+#define WM8904_EQ_REGS   24
 
 /**
  * DRC configurations are specified with a label and a set of register
index 7596441..5c74007 100644 (file)
@@ -200,7 +200,7 @@ TRACE_EVENT(jbd2_checkpoint_stats,
                  __entry->forced_to_close, __entry->written, __entry->dropped)
 );
 
-TRACE_EVENT(jbd2_cleanup_journal_tail,
+TRACE_EVENT(jbd2_update_log_tail,
 
        TP_PROTO(journal_t *journal, tid_t first_tid,
                 unsigned long block_nr, unsigned long freed),
index 8f3d622..89b672d 100644 (file)
@@ -12,7 +12,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
                              irq_handler_t handler,
                              unsigned long irqflags, const char *devname,
                              void *dev_id);
-int bind_virq_to_irq(unsigned int virq, unsigned int cpu);
+int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu);
 int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
                            irq_handler_t handler,
                            unsigned long irqflags, const char *devname,
index 25f1a61..391e3e0 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -198,6 +198,15 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
                return retval;
        }
 
+       msq->q_stime = msq->q_rtime = 0;
+       msq->q_ctime = get_seconds();
+       msq->q_cbytes = msq->q_qnum = 0;
+       msq->q_qbytes = ns->msg_ctlmnb;
+       msq->q_lspid = msq->q_lrpid = 0;
+       INIT_LIST_HEAD(&msq->q_messages);
+       INIT_LIST_HEAD(&msq->q_receivers);
+       INIT_LIST_HEAD(&msq->q_senders);
+
        /*
         * ipc_addid() locks msq
         */
@@ -208,15 +217,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
                return id;
        }
 
-       msq->q_stime = msq->q_rtime = 0;
-       msq->q_ctime = get_seconds();
-       msq->q_cbytes = msq->q_qnum = 0;
-       msq->q_qbytes = ns->msg_ctlmnb;
-       msq->q_lspid = msq->q_lrpid = 0;
-       INIT_LIST_HEAD(&msq->q_messages);
-       INIT_LIST_HEAD(&msq->q_receivers);
-       INIT_LIST_HEAD(&msq->q_senders);
-
        msg_unlock(msq);
 
        return msq->q_perm.id;
index 5215a81..b31c3ef 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -314,14 +314,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
                return retval;
        }
 
-       id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
-       if (id < 0) {
-               security_sem_free(sma);
-               ipc_rcu_putref(sma);
-               return id;
-       }
-       ns->used_sems += nsems;
-
        sma->sem_base = (struct sem *) &sma[1];
 
        for (i = 0; i < nsems; i++)
@@ -332,6 +324,15 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        INIT_LIST_HEAD(&sma->list_id);
        sma->sem_nsems = nsems;
        sma->sem_ctime = get_seconds();
+
+       id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
+       if (id < 0) {
+               security_sem_free(sma);
+               ipc_rcu_putref(sma);
+               return id;
+       }
+       ns->used_sems += nsems;
+
        sem_unlock(sma);
 
        return sma->sem_perm.id;
@@ -1606,16 +1607,27 @@ void exit_sem(struct task_struct *tsk)
                rcu_read_lock();
                un = list_entry_rcu(ulp->list_proc.next,
                                    struct sem_undo, list_proc);
-               if (&un->list_proc == &ulp->list_proc)
-                       semid = -1;
-                else
-                       semid = un->semid;
+               if (&un->list_proc == &ulp->list_proc) {
+                       /*
+                        * We must wait for freeary() before freeing this ulp,
+                        * in case we raced with last sem_undo. There is a small
+                        * possibility where we exit while freeary() didn't
+                        * finish unlocking sem_undo_list.
+                        */
+                       spin_unlock_wait(&ulp->lock);
+                       rcu_read_unlock();
+                       break;
+               }
+               spin_lock(&ulp->lock);
+               semid = un->semid;
+               spin_unlock(&ulp->lock);
                rcu_read_unlock();
 
+               /* exit_sem raced with IPC_RMID, nothing to do */
                if (semid == -1)
-                       break;
+                       continue;
 
-               sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid);
+               sma = sem_lock_check(tsk->nsproxy->ipc_ns, semid);
 
                /* exit_sem raced with IPC_RMID, nothing to do */
                if (IS_ERR(sma))
index 326a20b..16b1f9e 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -498,12 +498,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        if (IS_ERR(file))
                goto no_file;
 
-       id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
-       if (id < 0) {
-               error = id;
-               goto no_id;
-       }
-
        shp->shm_cprid = task_tgid_vnr(current);
        shp->shm_lprid = 0;
        shp->shm_atim = shp->shm_dtim = 0;
@@ -512,6 +506,13 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_nattch = 0;
        shp->shm_file = file;
        shp->shm_creator = current;
+
+       id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+       if (id < 0) {
+               error = id;
+               goto no_id;
+       }
+
        /*
         * shmid gets reported as "inode#" in /proc/pid/maps.
         * proc-ps tools use this. Changing this will break them.
index 75261a3..e4c9377 100644 (file)
@@ -264,6 +264,10 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        rcu_read_lock();
        spin_lock(&new->lock);
 
+       current_euid_egid(&euid, &egid);
+       new->cuid = new->uid = euid;
+       new->gid = new->cgid = egid;
+
        err = idr_get_new(&ids->ipcs_idr, new, &id);
        if (err) {
                spin_unlock(&new->lock);
@@ -273,10 +277,6 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 
        ids->in_use++;
 
-       current_euid_egid(&euid, &egid);
-       new->cuid = new->uid = euid;
-       new->gid = new->cgid = egid;
-
        new->seq = ids->seq++;
        if(ids->seq > ids->seq_max)
                ids->seq = 0;
index eafb6dd..ec64a18 100644 (file)
@@ -1053,15 +1053,16 @@ static int cgroup_show_options(struct seq_file *seq, struct vfsmount *vfs)
 
        mutex_lock(&cgroup_mutex);
        for_each_subsys(root, ss)
-               seq_printf(seq, ",%s", ss->name);
+               seq_show_option(seq, ss->name, NULL);
        if (test_bit(ROOT_NOPREFIX, &root->flags))
                seq_puts(seq, ",noprefix");
        if (strlen(root->release_agent_path))
-               seq_printf(seq, ",release_agent=%s", root->release_agent_path);
+               seq_show_option(seq, "release_agent",
+                               root->release_agent_path);
        if (clone_children(&root->top_cgroup))
                seq_puts(seq, ",clone_children");
        if (strlen(root->name))
-               seq_printf(seq, ",name=%s", root->name);
+               seq_show_option(seq, "name", root->name);
        mutex_unlock(&cgroup_mutex);
        return 0;
 }
index 4277095..7c0b4f0 100644 (file)
@@ -3942,12 +3942,20 @@ static const struct file_operations perf_fops = {
  * to user-space before waking everybody up.
  */
 
+static inline struct fasync_struct **perf_event_fasync(struct perf_event *event)
+{
+       /* only the parent has fasync state */
+       if (event->parent)
+               event = event->parent;
+       return &event->fasync;
+}
+
 void perf_event_wakeup(struct perf_event *event)
 {
        ring_buffer_wakeup(event);
 
        if (event->pending_kill) {
-               kill_fasync(&event->fasync, SIGIO, event->pending_kill);
+               kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
                event->pending_kill = 0;
        }
 }
@@ -4924,7 +4932,7 @@ static int __perf_event_overflow(struct perf_event *event,
        else
                perf_event_output(event, data, regs);
 
-       if (event->fasync && event->pending_kill) {
+       if (*perf_event_fasync(event) && event->pending_kill) {
                event->pending_wakeup = 1;
                irq_work_queue(&event->pending);
        }
@@ -5385,6 +5393,10 @@ static int perf_tp_filter_match(struct perf_event *event,
 {
        void *record = data->raw->data;
 
+       /* only top level events have filters set */
+       if (event->parent)
+               event = event->parent;
+
        if (likely(!event->filter) || filter_match_preds(event->filter, record))
                return 1;
        return 0;
index 20e88af..d9ce3d4 100644 (file)
@@ -848,6 +848,9 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
        if (delta.tv64 < 0)
                return 0;
 
+       if (WARN_ON(timer->state & HRTIMER_STATE_ENQUEUED))
+               return 0;
+
        if (interval.tv64 < timer->base->resolution.tv64)
                interval.tv64 = timer->base->resolution.tv64;
 
@@ -1260,11 +1263,14 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
         * Note: We clear the CALLBACK bit after enqueue_hrtimer and
         * we do not reprogramm the event hardware. Happens either in
         * hrtimer_start_range_ns() or in hrtimer_interrupt()
+        *
+        * Note: Because we dropped the cpu_base->lock above,
+        * hrtimer_start_range_ns() can have popped in and enqueued the timer
+        * for us already.
         */
-       if (restart != HRTIMER_NORESTART) {
-               BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+       if (restart != HRTIMER_NORESTART &&
+           !(timer->state & HRTIMER_STATE_ENQUEUED))
                enqueue_hrtimer(timer, base);
-       }
 
        WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));
 
index fb655f5..15374d0 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/mutex.h>
 
 #include "internals.h"
 
@@ -326,18 +327,29 @@ void register_handler_proc(unsigned int irq, struct irqaction *action)
 
 void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 {
+       static DEFINE_MUTEX(register_lock);
        char name [MAX_NAMELEN];
 
-       if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
+       if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
                return;
 
+       /*
+        * irq directories are registered only when a handler is
+        * added, not when the descriptor is created, so multiple
+        * tasks might try to register at the same time.
+        */
+       mutex_lock(&register_lock);
+
+       if (desc->dir)
+               goto out_unlock;
+
        memset(name, 0, MAX_NAMELEN);
        sprintf(name, "%d", irq);
 
        /* create /proc/irq/1234 */
        desc->dir = proc_mkdir(name, root_irq_dir);
        if (!desc->dir)
-               return;
+               goto out_unlock;
 
 #ifdef CONFIG_SMP
        /* create /proc/irq/<irq>/smp_affinity */
@@ -358,6 +370,9 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 
        proc_create_data("spurious", 0444, desc->dir,
                         &irq_spurious_proc_fops, (void *)(long)irq);
+
+out_unlock:
+       mutex_unlock(&register_lock);
 }
 
 void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
index 95ecd9f..8d2f37d 100644 (file)
@@ -893,11 +893,15 @@ void symbol_put_addr(void *addr)
        if (core_kernel_text(a))
                return;
 
-       /* module_text_address is safe here: we're supposed to have reference
-        * to module from symbol_get, so it can't go away. */
+       /*
+        * Even though we hold a reference on the module; we still need to
+        * disable preemption in order to safely traverse the data structure.
+        */
+       preempt_disable();
        modaddr = __module_text_address(a);
        BUG_ON(!modaddr);
        module_put(modaddr);
+       preempt_enable();
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
index f79803a..f07c144 100644 (file)
@@ -225,7 +225,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
         */
        int dumpable = 0;
        /* Don't let security modules deny introspection */
-       if (task == current)
+       if (same_thread_group(task, current))
                return 0;
        rcu_read_lock();
        tcred = __task_cred(task);
@@ -640,6 +640,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 static int ptrace_resume(struct task_struct *child, long request,
                         unsigned long data)
 {
+       bool need_siglock;
+
        if (!valid_signal(data))
                return -EIO;
 
@@ -667,8 +669,26 @@ static int ptrace_resume(struct task_struct *child, long request,
                user_disable_single_step(child);
        }
 
+       /*
+        * Change ->exit_code and ->state under siglock to avoid the race
+        * with wait_task_stopped() in between; a non-zero ->exit_code will
+        * wrongly look like another report from tracee.
+        *
+        * Note that we need siglock even if ->exit_code == data and/or this
+        * status was not reported yet, the new status must not be cleared by
+        * wait_task_stopped() after resume.
+        *
+        * If data == 0 we do not care if wait_task_stopped() reports the old
+        * status and clears the code too; this can't race with the tracee, it
+        * takes siglock after resume.
+        */
+       need_siglock = data && !thread_group_empty(current);
+       if (need_siglock)
+               spin_lock_irq(&child->sighand->siglock);
        child->exit_code = data;
        wake_up_state(child, __TASK_TRACED);
+       if (need_siglock)
+               spin_unlock_irq(&child->sighand->siglock);
 
        return 0;
 }
index 636af6d..bc84596 100644 (file)
@@ -160,6 +160,11 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
 
        /* Move the ready-to-invoke callbacks to a local list. */
        local_irq_save(flags);
+       if (rcp->donetail == &rcp->rcucblist) {
+               /* No callbacks ready, so just leave. */
+               local_irq_restore(flags);
+               return;
+       }
        RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, -1));
        list = rcp->rcucblist;
        rcp->rcucblist = *rcp->donetail;
index 596b3ca..2b9014b 100644 (file)
@@ -1016,8 +1016,10 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
         * After ->on_cpu is cleared, the task can be moved to a different CPU.
         * We must ensure this doesn't happen until the switch is completely
         * finished.
+        *
+        * Pairs with the control dependency and rmb in try_to_wake_up().
         */
-       smp_wmb();
+       smp_mb();
        prev->on_cpu = 0;
 #endif
 #ifdef CONFIG_DEBUG_SPINLOCK
@@ -3191,11 +3193,11 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
         * If a task dies, then it sets TASK_DEAD in tsk->state and calls
         * schedule one last time. The schedule call will never return, and
         * the scheduled task must drop that reference.
-        * The test for TASK_DEAD must occur while the runqueue locks are
-        * still held, otherwise prev could be scheduled on another cpu, die
-        * there before we look at prev->state, and then the reference would
-        * be dropped twice.
-        *              Manfred Spraul <manfred@colorfullife.com>
+        *
+        * We must observe prev->state before clearing prev->on_cpu (in
+        * finish_lock_switch), otherwise a concurrent wakeup can get prev
+        * running on another CPU and we could rave with its RUNNING -> DEAD
+        * transition, resulting in a double drop.
         */
        prev_state = prev->state;
        finish_arch_switch(prev);
index 2c71d91..44bc103 100644 (file)
@@ -194,22 +194,28 @@ void local_bh_enable_ip(unsigned long ip)
 EXPORT_SYMBOL(local_bh_enable_ip);
 
 /*
- * We restart softirq processing MAX_SOFTIRQ_RESTART times,
- * and we fall back to softirqd after that.
+ * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times,
+ * but break the loop if need_resched() is set or after 2 ms.
+ * The MAX_SOFTIRQ_TIME provides a nice upper bound in most cases, but in
+ * certain cases, such as stop_machine(), jiffies may cease to
+ * increment and so we need the MAX_SOFTIRQ_RESTART limit as
+ * well to make sure we eventually return from this method.
  *
- * This number has been established via experimentation.
+ * These limits have been established via experimentation.
  * The two things to balance is latency against fairness -
  * we want to handle softirqs as soon as possible, but they
  * should not be able to lock up the box.
  */
+#define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
 #define MAX_SOFTIRQ_RESTART 10
 
 asmlinkage void __do_softirq(void)
 {
        struct softirq_action *h;
        __u32 pending;
-       int max_restart = MAX_SOFTIRQ_RESTART;
+       unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        int cpu;
+       int max_restart = MAX_SOFTIRQ_RESTART;
 
        pending = local_softirq_pending();
        account_system_vtime(current);
@@ -255,11 +261,13 @@ restart:
        local_irq_disable();
 
        pending = local_softirq_pending();
-       if (pending && --max_restart)
-               goto restart;
+       if (pending) {
+               if (time_before(jiffies, end) && !need_resched() &&
+                   --max_restart)
+                       goto restart;
 
-       if (pending)
                wakeup_softirqd();
+       }
 
        lockdep_softirq_exit();
 
index d3ad022..fee10b5 100644 (file)
@@ -291,7 +291,7 @@ static void clocksource_watchdog(unsigned long data)
                        continue;
 
                /* Check the deviation from the watchdog clocksource. */
-               if ((abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD)) {
+               if (abs64(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
                        clocksource_unstable(cs, cs_nsec - wd_nsec);
                        continue;
                }
index a5457d5..6ad2e2d 100644 (file)
@@ -455,7 +455,7 @@ static int __init ring_buffer_benchmark_init(void)
 
        if (producer_fifo >= 0) {
                struct sched_param param = {
-                       .sched_priority = consumer_fifo
+                       .sched_priority = producer_fifo
                };
                sched_setscheduler(producer, SCHED_FIFO, &param);
        } else
index b0996c1..bfeb725 100644 (file)
@@ -1027,6 +1027,9 @@ static void parse_init(struct filter_parse_state *ps,
 
 static char infix_next(struct filter_parse_state *ps)
 {
+       if (!ps->infix.cnt)
+               return 0;
+
        ps->infix.cnt--;
 
        return ps->infix.string[ps->infix.tail++];
@@ -1042,6 +1045,9 @@ static char infix_peek(struct filter_parse_state *ps)
 
 static void infix_advance(struct filter_parse_state *ps)
 {
+       if (!ps->infix.cnt)
+               return;
+
        ps->infix.cnt--;
        ps->infix.tail++;
 }
@@ -1343,19 +1349,27 @@ static int check_preds(struct filter_parse_state *ps)
 {
        int n_normal_preds = 0, n_logical_preds = 0;
        struct postfix_elt *elt;
+       int cnt = 0;
 
        list_for_each_entry(elt, &ps->postfix, list) {
-               if (elt->op == OP_NONE)
+               if (elt->op == OP_NONE) {
+                       cnt++;
                        continue;
+               }
 
                if (elt->op == OP_AND || elt->op == OP_OR) {
                        n_logical_preds++;
+                       cnt--;
                        continue;
                }
+               cnt--;
                n_normal_preds++;
+               /* all ops should have operands */
+               if (cnt < 0)
+                       break;
        }
 
-       if (!n_normal_preds || n_logical_preds >= n_normal_preds) {
+       if (cnt != 1 || !n_normal_preds || n_logical_preds >= n_normal_preds) {
                parse_error(ps, FILT_ERR_INVALID_FILTER, 0);
                return -EINVAL;
        }
index dbc526f..389e75e 100644 (file)
@@ -601,12 +601,12 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
        unsigned a, b;
        int c, old_c, totaldigits;
        const char __user __force *ubuf = (const char __user __force *)buf;
-       int exp_digit, in_range;
+       int at_start, in_range;
 
        totaldigits = c = 0;
        bitmap_zero(maskp, nmaskbits);
        do {
-               exp_digit = 1;
+               at_start = 1;
                in_range = 0;
                a = b = 0;
 
@@ -635,11 +635,10 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
                                break;
 
                        if (c == '-') {
-                               if (exp_digit || in_range)
+                               if (at_start || in_range)
                                        return -EINVAL;
                                b = 0;
                                in_range = 1;
-                               exp_digit = 1;
                                continue;
                        }
 
@@ -649,16 +648,18 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
                        b = b * 10 + (c - '0');
                        if (!in_range)
                                a = b;
-                       exp_digit = 0;
+                       at_start = 0;
                        totaldigits++;
                }
                if (!(a <= b))
                        return -EINVAL;
                if (b >= nmaskbits)
                        return -ERANGE;
-               while (a <= b) {
-                       set_bit(a, maskp);
-                       a++;
+               if (!at_start) {
+                       while (a <= b) {
+                               set_bit(a, maskp);
+                               a++;
+                       }
                }
        } while (buflen && c == ',');
        return 0;
index 7c0e953..41bff68 100644 (file)
@@ -339,7 +339,7 @@ void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask)
        if (!iomap)
                return;
 
-       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+       for (i = 0; i < PCIM_IOMAP_MAX; i++) {
                if (!(mask & (1 << i)))
                        continue;
 
index 40136f6..dcbe695 100644 (file)
@@ -595,7 +595,7 @@ EXPORT_SYMBOL(memset);
 void memzero_explicit(void *s, size_t count)
 {
        memset(s, 0, count);
-       OPTIMIZER_HIDE_VAR(s);
+       barrier();
 }
 EXPORT_SYMBOL(memzero_explicit);
 
index 556858c..f2f5247 100644 (file)
@@ -2007,8 +2007,8 @@ int file_remove_suid(struct file *file)
                error = security_inode_killpriv(dentry);
        if (!error && killsuid)
                error = __remove_suid(dentry, killsuid);
-       if (!error && (inode->i_sb->s_flags & MS_NOSEC))
-               inode->i_flags |= S_NOSEC;
+       if (!error)
+               inode_has_no_xattr(inode);
 
        return error;
 }
@@ -2408,6 +2408,11 @@ again:
                        break;
                }
 
+               if (fatal_signal_pending(current)) {
+                       status = -EINTR;
+                       break;
+               }
+
                status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                                                &page, &fsdata);
                if (unlikely(status))
@@ -2448,10 +2453,6 @@ again:
                written += copied;
 
                balance_dirty_pages_ratelimited(mapping);
-               if (fatal_signal_pending(current)) {
-                       status = -EINTR;
-                       break;
-               }
        } while (iov_iter_count(i));
 
        return written ? written : status;
index a978529..68aff08 100644 (file)
@@ -2502,6 +2502,14 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
                if (iter_vma == vma)
                        continue;
 
+               /*
+                * Shared VMAs have their own reserves and do not affect
+                * MAP_PRIVATE accounting but it is possible that a shared
+                * VMA is using the same page so check and skip such VMAs.
+                */
+               if (iter_vma->vm_flags & VM_MAYSHARE)
+                       continue;
+
                /*
                 * Unmap the page from other VMAs without their own reserves.
                 * They get marked to be SIGKILLed if they fault in these
index cc8cf1d..cbae846 100644 (file)
@@ -192,6 +192,8 @@ static struct kmem_cache *scan_area_cache;
 
 /* set if tracing memory operations is enabled */
 static atomic_t kmemleak_enabled = ATOMIC_INIT(0);
+/* same as above but only for the kmemleak_free() callback */
+static int kmemleak_free_enabled;
 /* set in the late_initcall if there were no errors */
 static atomic_t kmemleak_initialized = ATOMIC_INIT(0);
 /* enables or disables early logging of the memory operations */
@@ -885,7 +887,7 @@ void __ref kmemleak_free(const void *ptr)
 {
        pr_debug("%s(0x%p)\n", __func__, ptr);
 
-       if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+       if (kmemleak_free_enabled && ptr && !IS_ERR(ptr))
                delete_object_full((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
                log_early(KMEMLEAK_FREE, ptr, 0, 0);
@@ -1614,6 +1616,13 @@ static void kmemleak_do_cleanup(struct work_struct *work)
        mutex_lock(&scan_mutex);
        stop_scan_thread();
 
+       /*
+        * Once the scan thread has stopped, it is safe to no longer track
+        * object freeing. Ordering of the scan thread stopping and the memory
+        * accesses below is guaranteed by the kthread_stop() function.
+        */
+       kmemleak_free_enabled = 0;
+
        rcu_read_lock();
        list_for_each_entry_rcu(object, &object_list, object_list)
                delete_object_full(object->pointer);
@@ -1640,6 +1649,8 @@ static void kmemleak_disable(void)
        /* check whether it is too early for a kernel thread */
        if (atomic_read(&kmemleak_initialized))
                schedule_work(&cleanup_work);
+       else
+               kmemleak_free_enabled = 0;
 
        pr_info("Kernel memory leak detector disabled\n");
 }
@@ -1688,6 +1699,7 @@ void __init kmemleak_init(void)
        if (!atomic_read(&kmemleak_error)) {
                atomic_set(&kmemleak_enabled, 1);
                atomic_set(&kmemleak_early_log, 0);
+               kmemleak_free_enabled = 1;
        }
        local_irq_restore(flags);
 
index 79c71de..8ca2d7c 100644 (file)
@@ -3154,6 +3154,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
        pte_unmap(page_table);
 
+       /* File mapping without ->vm_ops ? */
+       if (vma->vm_flags & VM_SHARED)
+               return VM_FAULT_SIGBUS;
+
        /* Check if we need to add a guard page to the stack */
        if (check_stack_guard_page(vma, address) < 0)
                return VM_FAULT_SIGSEGV;
@@ -3413,6 +3417,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
 
        pte_unmap(page_table);
+       /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
+       if (!vma->vm_ops->fault)
+               return VM_FAULT_SIGBUS;
        return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
@@ -3471,11 +3478,9 @@ int handle_pte_fault(struct mm_struct *mm,
        entry = *pte;
        if (!pte_present(entry)) {
                if (pte_none(entry)) {
-                       if (vma->vm_ops) {
-                               if (likely(vma->vm_ops->fault))
-                                       return do_linear_fault(mm, vma, address,
+                       if (vma->vm_ops)
+                               return do_linear_fault(mm, vma, address,
                                                pte, pmd, flags, entry);
-                       }
                        return do_anonymous_page(mm, vma, address,
                                                 pte, pmd, flags);
                }
index 2b499d2..40c9a46 100644 (file)
@@ -559,7 +559,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
         */
        setpoint = (freerun + limit) / 2;
        x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
-                   limit - setpoint + 1);
+                     (limit - setpoint) | 1);
        pos_ratio = x;
        pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
        pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
@@ -610,7 +610,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
         * scale global setpoint to bdi's:
         *      bdi_setpoint = setpoint * bdi_thresh / thresh
         */
-       x = div_u64((u64)bdi_thresh << 16, thresh + 1);
+       x = div_u64((u64)bdi_thresh << 16, thresh | 1);
        bdi_setpoint = setpoint * (u64)x >> 16;
        /*
         * Use span=(8*write_bw) in single bdi case as indicated by
@@ -625,7 +625,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
 
        if (bdi_dirty < x_intercept - span / 4) {
                pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty),
-                                   x_intercept - bdi_setpoint + 1);
+                                     (x_intercept - bdi_setpoint) | 1);
        } else
                pos_ratio /= 4;
 
index 2ed452b..dd62331 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1878,18 +1878,24 @@ redo:
 /* Unfreeze all the cpu partial slabs */
 static void unfreeze_partials(struct kmem_cache *s)
 {
-       struct kmem_cache_node *n = NULL;
+       struct kmem_cache_node *n = NULL, *n2 = NULL;
        struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab);
        struct page *page, *discard_page = NULL;
 
        while ((page = c->partial)) {
-               enum slab_modes { M_PARTIAL, M_FREE };
-               enum slab_modes l, m;
                struct page new;
                struct page old;
 
                c->partial = page->next;
-               l = M_FREE;
+
+               n2 = get_node(s, page_to_nid(page));
+               if (n != n2) {
+                       if (n)
+                               spin_unlock(&n->list_lock);
+
+                       n = n2;
+                       spin_lock(&n->list_lock);
+               }
 
                do {
 
@@ -1902,40 +1908,17 @@ static void unfreeze_partials(struct kmem_cache *s)
 
                        new.frozen = 0;
 
-                       if (!new.inuse && (!n || n->nr_partial > s->min_partial))
-                               m = M_FREE;
-                       else {
-                               struct kmem_cache_node *n2 = get_node(s,
-                                                       page_to_nid(page));
-
-                               m = M_PARTIAL;
-                               if (n != n2) {
-                                       if (n)
-                                               spin_unlock(&n->list_lock);
-
-                                       n = n2;
-                                       spin_lock(&n->list_lock);
-                               }
-                       }
-
-                       if (l != m) {
-                               if (l == M_PARTIAL)
-                                       remove_partial(n, page);
-                               else
-                                       add_partial(n, page,
-                                               DEACTIVATE_TO_TAIL);
-
-                               l = m;
-                       }
-
                } while (!cmpxchg_double_slab(s, page,
                                old.freelist, old.counters,
                                new.freelist, new.counters,
                                "unfreezing slab"));
 
-               if (m == M_FREE) {
+               if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) {
                        page->next = discard_page;
                        discard_page = page;
+               } else {
+                       add_partial(n, page, DEACTIVATE_TO_TAIL);
+                       stat(s, FREE_ADD_PARTIAL);
                }
        }
 
index 854ca7a..e958178 100644 (file)
@@ -824,7 +824,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
        if (err < 0) {
                if (err == -EIO)
                        c->status = Disconnected;
-               goto reterr;
+               if (err != -ERESTARTSYS)
+                       goto reterr;
        }
        if (req->status == REQ_STATUS_ERROR) {
                P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
index a073148..946e17a 100644 (file)
@@ -250,7 +250,7 @@ menu "Network testing"
 
 config NET_PKTGEN
        tristate "Packet Generator (USE WITH CAUTION)"
-       depends on PROC_FS
+       depends on INET && PROC_FS
        ---help---
          This module will inject preconfigured packets, at a configurable
          rate, out of a given interface.  It is used for network interface
index 7222fe1..ea0e15c 100644 (file)
@@ -246,9 +246,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_bh(&br->lock);
                br_stp_set_bridge_priority(br, args[1]);
-               spin_unlock_bh(&br->lock);
                return 0;
 
        case BRCTL_SET_PORT_PRIORITY:
index 398a297..5f21e53 100644 (file)
@@ -36,6 +36,9 @@
 #define mlock_dereference(X, br) \
        rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
 
+static void br_multicast_add_router(struct net_bridge *br,
+                                   struct net_bridge_port *port);
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
 {
@@ -842,6 +845,8 @@ void br_multicast_enable_port(struct net_bridge_port *port)
                goto out;
 
        __br_multicast_enable_port(port);
+       if (port->multicast_router == 2 && hlist_unhashed(&port->rlist))
+               br_multicast_add_router(br, port);
 
 out:
        spin_unlock(&br->multicast_lock);
@@ -972,7 +977,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
                }
 
                err = br_ip6_multicast_add_group(br, port, &grec->grec_mca);
-               if (!err)
+               if (err)
                        break;
        }
 
@@ -991,6 +996,9 @@ static void br_multicast_add_router(struct net_bridge *br,
        struct net_bridge_port *p;
        struct hlist_node *n, *slot = NULL;
 
+       if (!hlist_unhashed(&port->rlist))
+               return;
+
        hlist_for_each_entry(p, n, &br->router_list, rlist) {
                if ((unsigned long) port >= (unsigned long) p)
                        break;
@@ -1018,12 +1026,8 @@ static void br_multicast_mark_router(struct net_bridge *br,
        if (port->multicast_router != 1)
                return;
 
-       if (!hlist_unhashed(&port->rlist))
-               goto timer;
-
        br_multicast_add_router(br, port);
 
-timer:
        mod_timer(&port->multicast_router_timer,
                  now + br->multicast_querier_interval);
 }
index 7c1745d..6cdd3af 100644 (file)
@@ -822,12 +822,15 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
            !skb_is_gso(skb)) {
                if (br_parse_ip_options(skb))
                        /* Drop invalid packet */
-                       return NF_DROP;
+                       goto drop;
                ret = ip_fragment(skb, br_dev_queue_push_xmit);
        } else
                ret = br_dev_queue_push_xmit(skb);
 
        return ret;
+ drop:
+       kfree_skb(skb);
+       return 0;
 }
 #else
 static int br_nf_dev_queue_xmit(struct sk_buff *skb)
index 19308e3..0f7dc60 100644 (file)
@@ -235,12 +235,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
        return true;
 }
 
-/* called under bridge lock */
+/* Acquires and releases bridge lock */
 void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
 {
        struct net_bridge_port *p;
        int wasroot;
 
+       spin_lock_bh(&br->lock);
        wasroot = br_is_root_bridge(br);
 
        list_for_each_entry(p, &br->port_list, list) {
@@ -258,6 +259,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
        br_port_state_selection(br);
        if (br_is_root_bridge(br) && !wasroot)
                br_become_root_bridge(br);
+       spin_unlock_bh(&br->lock);
 }
 
 /* called under bridge lock */
index 7eed9eb..7e4b4b4 100644 (file)
@@ -366,6 +366,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo)
                release_sock(sk);
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
+
+               if (sock_flag(sk, SOCK_DEAD))
+                       break;
+
                clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
        }
 
@@ -410,6 +414,10 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                struct sk_buff *skb;
 
                lock_sock(sk);
+               if (sock_flag(sk, SOCK_DEAD)) {
+                       err = -ECONNRESET;
+                       goto unlock;
+               }
                skb = skb_dequeue(&sk->sk_receive_queue);
                caif_check_flow_release(sk);
 
index fd863fe..bb38a3c 100644 (file)
@@ -102,7 +102,7 @@ static int crush_decode_tree_bucket(void **p, void *end,
 {
        int j;
        dout("crush_decode_tree_bucket %p to %p\n", *p, end);
-       ceph_decode_32_safe(p, end, b->num_nodes, bad);
+       ceph_decode_8_safe(p, end, b->num_nodes, bad);
        b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS);
        if (b->node_weights == NULL)
                return -ENOMEM;
index 68bbf9f..6616bfb 100644 (file)
@@ -128,6 +128,35 @@ out_noerr:
        goto out;
 }
 
+static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
+{
+       struct sk_buff *nskb;
+
+       if (skb->peeked)
+               return skb;
+
+       /* We have to unshare an skb before modifying it. */
+       if (!skb_shared(skb))
+               goto done;
+
+       nskb = skb_clone(skb, GFP_ATOMIC);
+       if (!nskb)
+               return ERR_PTR(-ENOMEM);
+
+       skb->prev->next = nskb;
+       skb->next->prev = nskb;
+       nskb->prev = skb->prev;
+       nskb->next = skb->next;
+
+       consume_skb(skb);
+       skb = nskb;
+
+done:
+       skb->peeked = 1;
+
+       return skb;
+}
+
 /**
  *     __skb_recv_datagram - Receive a datagram skbuff
  *     @sk: socket
@@ -160,7 +189,9 @@ out_noerr:
 struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
                                    int *peeked, int *err)
 {
+       struct sk_buff_head *queue = &sk->sk_receive_queue;
        struct sk_buff *skb;
+       unsigned long cpu_flags;
        long timeo;
        /*
         * Caller is allowed not to check sk->sk_err before skb_recv_datagram()
@@ -179,19 +210,22 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
                 * Look at current nfs client by the way...
                 * However, this function was correct in any case. 8)
                 */
-               unsigned long cpu_flags;
-
-               spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
-               skb = skb_peek(&sk->sk_receive_queue);
+               spin_lock_irqsave(&queue->lock, cpu_flags);
+               skb = skb_peek(queue);
                if (skb) {
                        *peeked = skb->peeked;
                        if (flags & MSG_PEEK) {
-                               skb->peeked = 1;
+
+                               skb = skb_set_peeked(skb);
+                               error = PTR_ERR(skb);
+                               if (IS_ERR(skb))
+                                       goto unlock_err;
+
                                atomic_inc(&skb->users);
                        } else
-                               __skb_unlink(skb, &sk->sk_receive_queue);
+                               __skb_unlink(skb, queue);
                }
-               spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
+               spin_unlock_irqrestore(&queue->lock, cpu_flags);
 
                if (skb)
                        return skb;
@@ -205,6 +239,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
 
        return NULL;
 
+unlock_err:
+       spin_unlock_irqrestore(&queue->lock, cpu_flags);
 no_packet:
        *err = error;
        return NULL;
@@ -655,7 +691,8 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
        if (likely(!sum)) {
                if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
                        netdev_rx_csum_fault(skb->dev);
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               if (!skb_shared(skb))
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
        return sum;
 }
@@ -672,6 +709,7 @@ EXPORT_SYMBOL(__skb_checksum_complete);
  *     @skb: skbuff
  *     @hlen: hardware length
  *     @iov: io vector
+ *     @len: amount of data to copy from skb to iov
  *
  *     Caller _must_ check that skb will fit to this iovec.
  *
@@ -681,11 +719,14 @@ EXPORT_SYMBOL(__skb_checksum_complete);
  *                        can be modified!
  */
 int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
-                                    int hlen, struct iovec *iov)
+                                    int hlen, struct iovec *iov, int len)
 {
        __wsum csum;
        int chunk = skb->len - hlen;
 
+       if (chunk > len)
+               chunk = len;
+
        if (!chunk)
                return 0;
 
index 1c0d862..7f43202 100644 (file)
@@ -2947,6 +2947,8 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
        local_irq_save(flags);
 
        rps_lock(sd);
+       if (!netif_running(skb->dev))
+               goto drop;
        if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) {
                if (skb_queue_len(&sd->input_pkt_queue)) {
 enqueue:
@@ -2967,6 +2969,7 @@ enqueue:
                goto enqueue;
        }
 
+drop:
        sd->dropped++;
        rps_unlock(sd);
 
@@ -3258,8 +3261,6 @@ static int __netif_receive_skb(struct sk_buff *skb)
 
        pt_prev = NULL;
 
-       rcu_read_lock();
-
 another_round:
 
        __this_cpu_inc(softnet_data.processed);
@@ -3354,7 +3355,6 @@ ncls:
        }
 
 out:
-       rcu_read_unlock();
        return ret;
 }
 
@@ -3375,34 +3375,31 @@ out:
  */
 int netif_receive_skb(struct sk_buff *skb)
 {
+       int ret;
+
        if (netdev_tstamp_prequeue)
                net_timestamp_check(skb);
 
        if (skb_defer_rx_timestamp(skb))
                return NET_RX_SUCCESS;
 
+       rcu_read_lock();
+
 #ifdef CONFIG_RPS
        {
                struct rps_dev_flow voidflow, *rflow = &voidflow;
-               int cpu, ret;
-
-               rcu_read_lock();
-
-               cpu = get_rps_cpu(skb->dev, skb, &rflow);
+               int cpu = get_rps_cpu(skb->dev, skb, &rflow);
 
                if (cpu >= 0) {
                        ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
                        rcu_read_unlock();
-               } else {
-                       rcu_read_unlock();
-                       ret = __netif_receive_skb(skb);
+                       return ret;
                }
-
-               return ret;
        }
-#else
-       return __netif_receive_skb(skb);
 #endif
+       ret = __netif_receive_skb(skb);
+       rcu_read_unlock();
+       return ret;
 }
 EXPORT_SYMBOL(netif_receive_skb);
 
@@ -3793,8 +3790,10 @@ static int process_backlog(struct napi_struct *napi, int quota)
                unsigned int qlen;
 
                while ((skb = __skb_dequeue(&sd->process_queue))) {
+                       rcu_read_lock();
                        local_irq_enable();
                        __netif_receive_skb(skb);
+                       rcu_read_unlock();
                        local_irq_disable();
                        input_queue_head_incr(sd);
                        if (++work >= quota) {
@@ -5305,6 +5304,7 @@ static void rollback_registered_many(struct list_head *head)
                unlist_netdevice(dev);
 
                dev->reg_state = NETREG_UNREGISTERING;
+               on_each_cpu(flush_backlog, dev, 1);
        }
 
        synchronize_net();
@@ -5877,8 +5877,6 @@ void netdev_run_todo(void)
 
                dev->reg_state = NETREG_UNREGISTERED;
 
-               on_each_cpu(flush_backlog, dev, 1);
-
                netdev_wait_allrefs(dev);
 
                /* paranoia */
index d5e2c4c..946e214 100644 (file)
@@ -272,7 +272,7 @@ void dst_release(struct dst_entry *dst)
 
                newrefcnt = atomic_dec_return(&dst->__refcnt);
                WARN_ON(newrefcnt < 0);
-               if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) {
+               if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) {
                        dst = dst_destroy(dst);
                        if (dst)
                                __dst_free(dst);
index 2367246..f31698a 100644 (file)
@@ -1359,7 +1359,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 
        gstrings.len = ret;
 
-       data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+       data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
        if (!data)
                return -ENOMEM;
 
index 6af54f2..c7caf3e 100644 (file)
@@ -594,15 +594,17 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
 {
        int idx = 0;
        struct fib_rule *rule;
+       int err = 0;
 
        rcu_read_lock();
        list_for_each_entry_rcu(rule, &ops->rules_list, list) {
                if (idx < cb->args[1])
                        goto skip;
 
-               if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
-                                    cb->nlh->nlmsg_seq, RTM_NEWRULE,
-                                    NLM_F_MULTI, ops) < 0)
+               err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
+                                      cb->nlh->nlmsg_seq, RTM_NEWRULE,
+                                      NLM_F_MULTI, ops);
+               if (err < 0)
                        break;
 skip:
                idx++;
@@ -611,7 +613,7 @@ skip:
        cb->args[1] = idx;
        rules_ops_put(ops);
 
-       return skb->len;
+       return err;
 }
 
 static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
@@ -627,7 +629,9 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
                if (ops == NULL)
                        return -EAFNOSUPPORT;
 
-               return dump_rules(skb, cb, ops);
+               dump_rules(skb, cb, ops);
+
+               return skb->len;
        }
 
        rcu_read_lock();
index 0ea3fd3..c8c2645 100644 (file)
@@ -955,6 +955,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
        rc = 0;
        if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
                goto out_unlock_bh;
+       if (neigh->dead)
+               goto out_dead;
 
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
                if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
@@ -1003,6 +1005,13 @@ out_unlock_bh:
                write_unlock(&neigh->lock);
        local_bh_enable();
        return rc;
+
+out_dead:
+       if (neigh->nud_state & NUD_STALE)
+               goto out_unlock_bh;
+       write_unlock_bh(&neigh->lock);
+       kfree_skb(skb);
+       return 1;
 }
 EXPORT_SYMBOL(__neigh_event_send);
 
@@ -1066,6 +1075,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
        if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
            (old & (NUD_NOARP | NUD_PERMANENT)))
                goto out;
+       if (neigh->dead)
+               goto out;
 
        if (!(new & NUD_VALID)) {
                neigh_del_timer(neigh);
index 80aeac9..7879b2f 100644 (file)
@@ -568,7 +568,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
                           "     dst_min: %s  dst_max: %s\n",
                           pkt_dev->dst_min, pkt_dev->dst_max);
                seq_printf(seq,
-                          "        src_min: %s  src_max: %s\n",
+                          "     src_min: %s  src_max: %s\n",
                           pkt_dev->src_min, pkt_dev->src_max);
        }
 
@@ -3481,8 +3481,10 @@ static int pktgen_thread_worker(void *arg)
        pktgen_rem_thread(t);
 
        /* Wait for kthread_stop */
-       while (!kthread_should_stop()) {
+       for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
+               if (kthread_should_stop())
+                       break;
                schedule();
        }
        __set_current_state(TASK_RUNNING);
index 5b412f0..e77373a 100644 (file)
@@ -1147,10 +1147,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
        [IFLA_INFO_DATA]        = { .type = NLA_NESTED },
 };
 
-static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
-       [IFLA_VF_INFO]          = { .type = NLA_NESTED },
-};
-
 static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
        [IFLA_VF_MAC]           = { .len = sizeof(struct ifla_vf_mac) },
        [IFLA_VF_VLAN]          = { .len = sizeof(struct ifla_vf_vlan) },
@@ -1224,58 +1220,53 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
        return 0;
 }
 
-static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
+static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
 {
-       int rem, err = -EINVAL;
-       struct nlattr *vf;
        const struct net_device_ops *ops = dev->netdev_ops;
+       int err = -EINVAL;
 
-       nla_for_each_nested(vf, attr, rem) {
-               switch (nla_type(vf)) {
-               case IFLA_VF_MAC: {
-                       struct ifla_vf_mac *ivm;
-                       ivm = nla_data(vf);
-                       err = -EOPNOTSUPP;
-                       if (ops->ndo_set_vf_mac)
-                               err = ops->ndo_set_vf_mac(dev, ivm->vf,
-                                                         ivm->mac);
-                       break;
-               }
-               case IFLA_VF_VLAN: {
-                       struct ifla_vf_vlan *ivv;
-                       ivv = nla_data(vf);
-                       err = -EOPNOTSUPP;
-                       if (ops->ndo_set_vf_vlan)
-                               err = ops->ndo_set_vf_vlan(dev, ivv->vf,
-                                                          ivv->vlan,
-                                                          ivv->qos);
-                       break;
-               }
-               case IFLA_VF_TX_RATE: {
-                       struct ifla_vf_tx_rate *ivt;
-                       ivt = nla_data(vf);
-                       err = -EOPNOTSUPP;
-                       if (ops->ndo_set_vf_tx_rate)
-                               err = ops->ndo_set_vf_tx_rate(dev, ivt->vf,
-                                                             ivt->rate);
-                       break;
-               }
-               case IFLA_VF_SPOOFCHK: {
-                       struct ifla_vf_spoofchk *ivs;
-                       ivs = nla_data(vf);
-                       err = -EOPNOTSUPP;
-                       if (ops->ndo_set_vf_spoofchk)
-                               err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
-                                                              ivs->setting);
-                       break;
-               }
-               default:
-                       err = -EINVAL;
-                       break;
-               }
-               if (err)
-                       break;
+       if (tb[IFLA_VF_MAC]) {
+               struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]);
+               err = -EOPNOTSUPP;
+               if (ops->ndo_set_vf_mac)
+                       err = ops->ndo_set_vf_mac(dev, ivm->vf,
+                                                 ivm->mac);
+               if (err < 0)
+                       return err;
        }
+
+       if (tb[IFLA_VF_VLAN]) {
+               struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]);
+
+               err = -EOPNOTSUPP;
+               if (ops->ndo_set_vf_vlan)
+                       err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan,
+                                                  ivv->qos);
+               if (err < 0)
+                       return err;
+       }
+
+       if (tb[IFLA_VF_TX_RATE]) {
+               struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]);
+
+               if (ops->ndo_set_vf_tx_rate)
+                       err = ops->ndo_set_vf_tx_rate(dev, ivt->vf,
+                                                     ivt->rate);
+               if (err < 0)
+                       return err;
+       }
+
+       if (tb[IFLA_VF_SPOOFCHK]) {
+               struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]);
+
+               err = -EOPNOTSUPP;
+               if (ops->ndo_set_vf_spoofchk)
+                       err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
+                                                      ivs->setting);
+               if (err < 0)
+                       return err;
+       }
+
        return err;
 }
 
@@ -1458,14 +1449,21 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
        }
 
        if (tb[IFLA_VFINFO_LIST]) {
+               struct nlattr *vfinfo[IFLA_VF_MAX + 1];
                struct nlattr *attr;
                int rem;
+
                nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
-                       if (nla_type(attr) != IFLA_VF_INFO) {
+                       if (nla_type(attr) != IFLA_VF_INFO ||
+                           nla_len(attr) < NLA_HDRLEN) {
                                err = -EINVAL;
                                goto errout;
                        }
-                       err = do_setvfinfo(dev, attr);
+                       err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr,
+                                              ifla_vf_policy);
+                       if (err < 0)
+                               goto errout;
+                       err = do_setvfinfo(dev, vfinfo);
                        if (err < 0)
                                goto errout;
                        modified = 1;
index 7121d9b..b30d9c2 100644 (file)
@@ -2579,11 +2579,12 @@ EXPORT_SYMBOL(skb_append_datato_frags);
  */
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
 {
+       unsigned char *data = skb->data;
+
        BUG_ON(len > skb->len);
-       skb->len -= len;
-       BUG_ON(skb->len < skb->data_len);
-       skb_postpull_rcsum(skb, skb->data, len);
-       return skb->data += len;
+       __skb_pull(skb, len);
+       skb_postpull_rcsum(skb, data, len);
+       return skb->data;
 }
 EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
index ec07510..ffb8b6e 100644 (file)
@@ -20,7 +20,7 @@
 #include <net/route.h>
 #include <net/tcp_states.h>
 
-int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
@@ -39,8 +39,6 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        sk_dst_reset(sk);
 
-       lock_sock(sk);
-
        oif = sk->sk_bound_dev_if;
        saddr = inet->inet_saddr;
        if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
@@ -81,7 +79,17 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        sk_dst_set(sk, &rt->dst);
        err = 0;
 out:
-       release_sock(sk);
        return err;
 }
+EXPORT_SYMBOL(__ip4_datagram_connect);
+
+int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+       int res;
+
+       lock_sock(sk);
+       res = __ip4_datagram_connect(sk, uaddr, addr_len);
+       release_sock(sk);
+       return res;
+}
 EXPORT_SYMBOL(ip4_datagram_connect);
index 16e25a4..c20c356 100644 (file)
@@ -385,7 +385,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
        ihl = ip_hdrlen(skb);
 
        /* Determine the position of this fragment. */
-       end = offset + skb->len - ihl;
+       end = offset + skb->len - skb_network_offset(skb) - ihl;
        err = -EINVAL;
 
        /* Is this the final fragment? */
@@ -415,7 +415,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
                goto err;
 
        err = -ENOMEM;
-       if (pskb_pull(skb, ihl) == NULL)
+       if (!pskb_pull(skb, skb_network_offset(skb) + ihl))
                goto err;
 
        err = pskb_trim_rcsum(skb, end - offset);
@@ -638,6 +638,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
        iph->frag_off = 0;
        iph->tot_len = htons(len);
        iph->tos |= ecn;
+       ip_send_check(iph);
+
        IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
        qp->q.fragments = NULL;
        qp->q.fragments_tail = NULL;
index 7993d16..581dcb3 100644 (file)
@@ -1590,7 +1590,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
 {
        struct ip_options *opt = &(IPCB(skb)->opt);
 
-       IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
+       IP_INC_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
 
        if (unlikely(opt->optlen))
                ip_forward_options(skb);
@@ -1652,7 +1652,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
                 * to blackhole.
                 */
 
-               IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+               IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
                ip_rt_put(rt);
                goto out_free;
        }
index afe6886..f8b5899 100644 (file)
@@ -5198,7 +5198,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
                err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
        else
                err = skb_copy_and_csum_datagram_iovec(skb, hlen,
-                                                      tp->ucopy.iov);
+                                                      tp->ucopy.iov, chunk);
 
        if (!err) {
                tp->ucopy.len -= chunk;
index 8c2e259..b111221 100644 (file)
@@ -1207,7 +1207,7 @@ try_again:
        else {
                err = skb_copy_and_csum_datagram_iovec(skb,
                                                       sizeof(struct udphdr),
-                                                      msg->msg_iov);
+                                                      msg->msg_iov, copied);
 
                if (err == -EINVAL)
                        goto csum_copy_err;
@@ -1248,10 +1248,8 @@ csum_copy_err:
                UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
        unlock_sock_fast(sk, slow);
 
-       if (noblock)
-               return -EAGAIN;
-
-       /* starting over for a new packet */
+       /* starting over for a new packet, but check if we need to yield */
+       cond_resched();
        msg->msg_flags &= ~MSG_TRUNC;
        goto try_again;
 }
index 4b20d56..8b25fbb 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_NETFILTER)       += netfilter/
 obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 
-obj-y += addrconf_core.o exthdrs_core.o output_core.o
+obj-y += addrconf_core.o exthdrs_core.o
+obj-$(CONFIG_INET) += output_core.o
 
 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
index 3afdd78..006867d 100644 (file)
@@ -4321,6 +4321,21 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
        return ret;
 }
 
+static
+int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct inet6_dev *idev = ctl->extra1;
+       int min_mtu = IPV6_MIN_MTU;
+       struct ctl_table lctl;
+
+       lctl = *ctl;
+       lctl.extra1 = &min_mtu;
+       lctl.extra2 = idev ? &idev->dev->mtu : NULL;
+
+       return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos);
+}
+
 static void dev_disable_change(struct inet6_dev *idev)
 {
        if (!idev || !idev->dev)
@@ -4421,7 +4436,7 @@ static struct addrconf_sysctl_table
                        .data           = &ipv6_devconf.mtu6,
                        .maxlen         = sizeof(int),
                        .mode           = 0644,
-                       .proc_handler   = proc_dointvec,
+                       .proc_handler   = addrconf_sysctl_mtu,
                },
                {
                        .procname       = "accept_ra",
index 33719b7..67f3632 100644 (file)
@@ -38,7 +38,7 @@ static inline int ipv6_mapped_addr_any(const struct in6_addr *a)
        return (ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0));
 }
 
-int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        struct sockaddr_in6     *usin = (struct sockaddr_in6 *) uaddr;
        struct inet_sock        *inet = inet_sk(sk);
@@ -54,7 +54,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (usin->sin6_family == AF_INET) {
                if (__ipv6_only_sock(sk))
                        return -EAFNOSUPPORT;
-               err = ip4_datagram_connect(sk, uaddr, addr_len);
+               err = __ip4_datagram_connect(sk, uaddr, addr_len);
                goto ipv4_connected;
        }
 
@@ -97,9 +97,9 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                sin.sin_addr.s_addr = daddr->s6_addr32[3];
                sin.sin_port = usin->sin6_port;
 
-               err = ip4_datagram_connect(sk,
-                                          (struct sockaddr*) &sin,
-                                          sizeof(sin));
+               err = __ip4_datagram_connect(sk,
+                                            (struct sockaddr *) &sin,
+                                            sizeof(sin));
 
 ipv4_connected:
                if (err)
@@ -203,6 +203,16 @@ out:
        return err;
 }
 
+int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+       int res;
+
+       lock_sock(sk);
+       res = __ip6_datagram_connect(sk, uaddr, addr_len);
+       release_sock(sk);
+       return res;
+}
+
 void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
                     __be16 port, u32 info, u8 *payload)
 {
index ad62afc..785e62d 100644 (file)
@@ -1473,27 +1473,28 @@ static int fib6_age(struct rt6_info *rt, void *arg)
 
 static DEFINE_SPINLOCK(fib6_gc_lock);
 
-void fib6_run_gc(unsigned long expires, struct net *net)
+void fib6_run_gc(unsigned long expires, struct net *net, bool force)
 {
-       if (expires != ~0UL) {
+       unsigned long now;
+
+       if (force) {
                spin_lock_bh(&fib6_gc_lock);
-               gc_args.timeout = expires ? (int)expires :
-                       net->ipv6.sysctl.ip6_rt_gc_interval;
-       } else {
-               if (!spin_trylock_bh(&fib6_gc_lock)) {
-                       mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
-                       return;
-               }
-               gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
+       } else if (!spin_trylock_bh(&fib6_gc_lock)) {
+               mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
+               return;
        }
+       gc_args.timeout = expires ? (int)expires :
+                         net->ipv6.sysctl.ip6_rt_gc_interval;
 
        gc_args.more = icmp6_dst_gc();
 
        fib6_clean_all(net, fib6_age, 0, NULL);
+       now = jiffies;
+       net->ipv6.ip6_rt_last_gc = now;
 
        if (gc_args.more)
                mod_timer(&net->ipv6.ip6_fib_timer,
-                         round_jiffies(jiffies
+                         round_jiffies(now
                                        + net->ipv6.sysctl.ip6_rt_gc_interval));
        else
                del_timer(&net->ipv6.ip6_fib_timer);
@@ -1502,7 +1503,7 @@ void fib6_run_gc(unsigned long expires, struct net *net)
 
 static void fib6_gc_timer_cb(unsigned long arg)
 {
-       fib6_run_gc(0, (struct net *)arg);
+       fib6_run_gc(0, (struct net *)arg, true);
 }
 
 static int __net_init fib6_net_init(struct net *net)
index f96c96f..99ee86d 100644 (file)
@@ -550,7 +550,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
 
        if (it->cache == &mrt->mfc6_unres_queue)
                spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == mrt->mfc6_cache_array)
+       else if (it->cache == &mrt->mfc6_cache_array[it->ct])
                read_unlock(&mrt_lock);
 }
 
index 884d45f..39836da 100644 (file)
@@ -1743,11 +1743,11 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&nd_tbl, dev);
-               fib6_run_gc(~0UL, net);
+               fib6_run_gc(0, net, false);
                break;
        case NETDEV_DOWN:
                neigh_ifdown(&nd_tbl, dev);
-               fib6_run_gc(~0UL, net);
+               fib6_run_gc(0, net, false);
                break;
        case NETDEV_NOTIFY_PEERS:
                ndisc_send_unsol_na(dev);
index 9287f3e..240c102 100644 (file)
@@ -479,7 +479,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                        goto csum_copy_err;
                err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        } else {
-               err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov);
+               err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov, copied);
                if (err == -EINVAL)
                        goto csum_copy_err;
        }
index d89d1a6..3a8776d 100644 (file)
@@ -1159,7 +1159,6 @@ static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
 
 static int ip6_dst_gc(struct dst_ops *ops)
 {
-       unsigned long now = jiffies;
        struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
        int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
        int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
@@ -1169,13 +1168,12 @@ static int ip6_dst_gc(struct dst_ops *ops)
        int entries;
 
        entries = dst_entries_get_fast(ops);
-       if (time_after(rt_last_gc + rt_min_interval, now) &&
+       if (time_after(rt_last_gc + rt_min_interval, jiffies) &&
            entries <= rt_max_size)
                goto out;
 
        net->ipv6.ip6_rt_gc_expire++;
-       fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
-       net->ipv6.ip6_rt_last_gc = now;
+       fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, entries > rt_max_size);
        entries = dst_entries_get_slow(ops);
        if (entries < ops->gc_thresh)
                net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
@@ -2726,7 +2724,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
        net = (struct net *)ctl->extra1;
        delay = net->ipv6.sysctl.flush_delay;
        proc_dointvec(ctl, write, buffer, lenp, ppos);
-       fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
+       fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
        return 0;
 }
 
index 4f3cec1..aa109da 100644 (file)
@@ -145,6 +145,16 @@ static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        break;
 }
 
+static void tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                        u8 type, u8 code, int offset, __be32 info)
+{
+       struct xfrm6_tunnel *handler;
+
+       for_each_tunnel_rcu(tunnel46_handlers, handler)
+               if (!handler->err_handler(skb, opt, type, code, offset, info))
+                       break;
+}
+
 static const struct inet6_protocol tunnel6_protocol = {
        .handler        = tunnel6_rcv,
        .err_handler    = tunnel6_err,
@@ -153,7 +163,7 @@ static const struct inet6_protocol tunnel6_protocol = {
 
 static const struct inet6_protocol tunnel46_protocol = {
        .handler        = tunnel46_rcv,
-       .err_handler    = tunnel6_err,
+       .err_handler    = tunnel46_err,
        .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
index d131a95..888892e 100644 (file)
@@ -383,7 +383,8 @@ try_again:
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
                                              msg->msg_iov, copied       );
        else {
-               err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
+               err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr),
+                                                      msg->msg_iov, copied);
                if (err == -EINVAL)
                        goto csum_copy_err;
        }
@@ -451,10 +452,8 @@ csum_copy_err:
        }
        unlock_sock_fast(sk, slow);
 
-       if (noblock)
-               return -EAGAIN;
-
-       /* starting over for a new packet */
+       /* starting over for a new packet, but check if we need to yield */
+       cond_resched();
        msg->msg_flags &= ~MSG_TRUNC;
        goto try_again;
 }
index 6115a44..0721f82 100644 (file)
@@ -1868,7 +1868,7 @@ static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off)
        for (element = hashbin_get_first(iter->hashbin);
             element != NULL;
             element = hashbin_get_next(iter->hashbin)) {
-               if (!off || *off-- == 0) {
+               if (!off || (*off)-- == 0) {
                        /* NB: hashbin left locked */
                        return element;
                }
index dc8d7ef..8636f10 100644 (file)
@@ -220,7 +220,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
 #define BROADCAST_ONE          1
 #define BROADCAST_REGISTERED   2
 #define BROADCAST_PROMISC_ONLY 4
-static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
+static int pfkey_broadcast(struct sk_buff *skb,
                           int broadcast_flags, struct sock *one_sk,
                           struct net *net)
 {
@@ -246,7 +246,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                 * socket.
                 */
                if (pfk->promisc)
-                       pfkey_broadcast_one(skb, &skb2, allocation, sk);
+                       pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
                /* the exact target will be processed later */
                if (sk == one_sk)
@@ -261,7 +261,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                                continue;
                }
 
-               err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk);
+               err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
                /* Error is cleare after succecful sending to at least one
                 * registered KM */
@@ -271,7 +271,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
        rcu_read_unlock();
 
        if (one_sk != NULL)
-               err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
+               err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk);
 
        kfree_skb(skb2);
        kfree_skb(skb);
@@ -294,7 +294,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
                hdr = (struct sadb_msg *) pfk->dump.skb->data;
                hdr->sadb_msg_seq = 0;
                hdr->sadb_msg_errno = rc;
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
                pfk->dump.skb = NULL;
        }
@@ -335,7 +335,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
                             sizeof(uint64_t));
 
-       pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
+       pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
 
        return 0;
 }
@@ -1361,7 +1361,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
        xfrm_state_put(x);
 
-       pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
+       pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net);
 
        return 0;
 }
@@ -1449,7 +1449,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
        hdr->sadb_msg_seq = c->seq;
        hdr->sadb_msg_pid = c->pid;
 
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x));
 
        return 0;
 }
@@ -1566,7 +1566,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg
        out_hdr->sadb_msg_reserved = 0;
        out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
        out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+       pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk));
 
        return 0;
 }
@@ -1667,7 +1667,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
                return -ENOBUFS;
        }
 
-       pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, sock_net(sk));
+       pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk));
 
        return 0;
 }
@@ -1686,7 +1686,7 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
        hdr->sadb_msg_errno = (uint8_t) 0;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+       return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
 }
 
 static int key_notify_sa_flush(const struct km_event *c)
@@ -1707,7 +1707,7 @@ static int key_notify_sa_flush(const struct km_event *c)
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        hdr->sadb_msg_reserved = 0;
 
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net);
 
        return 0;
 }
@@ -1768,7 +1768,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
        out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
 
        if (pfk->dump.skb)
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
        pfk->dump.skb = out_skb;
 
@@ -1829,7 +1829,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb
                new_hdr->sadb_msg_errno = 0;
        }
 
-       pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk));
        return 0;
 }
 
@@ -2160,7 +2160,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
        out_hdr->sadb_msg_errno = 0;
        out_hdr->sadb_msg_seq = c->seq;
        out_hdr->sadb_msg_pid = c->pid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
+       pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp));
        return 0;
 
 }
@@ -2386,7 +2386,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
        out_hdr->sadb_msg_errno = 0;
        out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
        out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
+       pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp));
        err = 0;
 
 out:
@@ -2639,7 +2639,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
        out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
 
        if (pfk->dump.skb)
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
        pfk->dump.skb = out_skb;
 
@@ -2690,7 +2690,7 @@ static int key_notify_policy_flush(const struct km_event *c)
        hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        hdr->sadb_msg_reserved = 0;
-       pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+       pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net);
        return 0;
 
 }
@@ -2756,7 +2756,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
        void *ext_hdrs[SADB_EXT_MAX];
        int err;
 
-       pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
+       pfkey_broadcast(skb_clone(skb, GFP_KERNEL),
                        BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
 
        memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -2962,7 +2962,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
        out_hdr->sadb_msg_seq = 0;
        out_hdr->sadb_msg_pid = 0;
 
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x));
        return 0;
 }
 
@@ -3134,7 +3134,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
                       xfrm_ctx->ctx_len);
        }
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
 }
 
 static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3332,7 +3332,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
        n_port->sadb_x_nat_t_port_port = sport;
        n_port->sadb_x_nat_t_port_reserved = 0;
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
 }
 
 #ifdef CONFIG_NET_KEY_MIGRATE
@@ -3524,7 +3524,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
        }
 
        /* broadcast migrate message to sockets */
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net);
 
        return 0;
 
index 880a55d..0228ecb 100644 (file)
@@ -598,6 +598,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 
        debugfs_remove_recursive(sdata->debugfs.dir);
        sdata->debugfs.dir = NULL;
+       sdata->debugfs.subdir_stations = NULL;
 }
 
 void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
index 9da8626..ef00f24 100644 (file)
@@ -1840,7 +1840,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
        if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
            ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
-               int sig = ifmgd->ave_beacon_signal;
+               int sig = ifmgd->ave_beacon_signal / 16;
                int last_sig = ifmgd->last_ave_beacon_signal;
 
                /*
index 65df296..91826b6 100644 (file)
@@ -278,9 +278,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
        if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
                return TX_CONTINUE;
 
-       if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-               return TX_CONTINUE;
-
        if (tx->flags & IEEE80211_TX_PS_BUFFERED)
                return TX_CONTINUE;
 
index a1c6bfd..34583c5 100644 (file)
@@ -97,8 +97,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
 
        hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
-       if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN ||
-                   skb_headroom(skb) < WEP_IV_LEN))
+       if (WARN_ON(skb_headroom(skb) < WEP_IV_LEN))
                return NULL;
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -160,6 +159,9 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
        size_t len;
        u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
 
+       if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN))
+               return -1;
+
        iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
        if (!iv)
                return -1;
index d864aaf..197ed93 100644 (file)
@@ -2003,10 +2003,18 @@ static int __init ip_vs_init(void)
                goto cleanup_dev;
        }
 
+       ret = ip_vs_register_nl_ioctl();
+       if (ret < 0) {
+               pr_err("can't register netlink/ioctl.\n");
+               goto cleanup_hooks;
+       }
+
        pr_info("ipvs loaded.\n");
 
        return ret;
 
+cleanup_hooks:
+       nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
 cleanup_dev:
        unregister_pernet_device(&ipvs_core_dev_ops);
 cleanup_sub:
@@ -2022,6 +2030,7 @@ exit:
 
 static void __exit ip_vs_cleanup(void)
 {
+       ip_vs_unregister_nl_ioctl();
        nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
        unregister_pernet_device(&ipvs_core_dev_ops);
        unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
index 93acfa1..1e27a1f 100644 (file)
@@ -3689,6 +3689,9 @@ void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
        cancel_work_sync(&ipvs->defense_work.work);
        unregister_net_sysctl_table(ipvs->sysctl_hdr);
        ip_vs_stop_estimator(net, &ipvs->tot_stats);
+
+       if (!net_eq(net, &init_net))
+               kfree(ipvs->sysctl_tbl);
 }
 
 #else
@@ -3751,21 +3754,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
        free_percpu(ipvs->tot_stats.cpustats);
 }
 
-int __init ip_vs_control_init(void)
+int __init ip_vs_register_nl_ioctl(void)
 {
-       int idx;
        int ret;
 
-       EnterFunction(2);
-
-       /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
-       for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
-               INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
-               INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
-       }
-
-       smp_wmb();      /* Do we really need it now ? */
-
        ret = nf_register_sockopt(&ip_vs_sockopts);
        if (ret) {
                pr_err("cannot register sockopt.\n");
@@ -3777,28 +3769,47 @@ int __init ip_vs_control_init(void)
                pr_err("cannot register Generic Netlink interface.\n");
                goto err_genl;
        }
-
-       ret = register_netdevice_notifier(&ip_vs_dst_notifier);
-       if (ret < 0)
-               goto err_notf;
-
-       LeaveFunction(2);
        return 0;
 
-err_notf:
-       ip_vs_genl_unregister();
 err_genl:
        nf_unregister_sockopt(&ip_vs_sockopts);
 err_sock:
        return ret;
 }
 
+void ip_vs_unregister_nl_ioctl(void)
+{
+       ip_vs_genl_unregister();
+       nf_unregister_sockopt(&ip_vs_sockopts);
+}
+
+int __init ip_vs_control_init(void)
+{
+       int idx;
+       int ret;
+
+       EnterFunction(2);
+
+       /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
+       for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+               INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
+               INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
+       }
+
+       smp_wmb();      /* Do we really need it now ? */
+
+       ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+       if (ret < 0)
+               return ret;
+
+       LeaveFunction(2);
+       return 0;
+}
+
 
 void ip_vs_control_cleanup(void)
 {
        EnterFunction(2);
        unregister_netdevice_notifier(&ip_vs_dst_notifier);
-       ip_vs_genl_unregister();
-       nf_unregister_sockopt(&ip_vs_sockopts);
        LeaveFunction(2);
 }
index 7918eb7..cec0ed5 100644 (file)
@@ -205,7 +205,8 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
                        a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
        }
 
-       return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
+       return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) &&
+              nf_ct_zone(a->master) == nf_ct_zone(b->master);
 }
 
 static inline int expect_matches(const struct nf_conntrack_expect *a,
index 4f19bf2..4a912f7 100644 (file)
@@ -1170,16 +1170,6 @@ static void packet_sock_destruct(struct sock *sk)
        sk_refcnt_debug_dec(sk);
 }
 
-static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
-{
-       int x = atomic_read(&f->rr_cur) + 1;
-
-       if (x >= num)
-               x = 0;
-
-       return x;
-}
-
 static struct sock *fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
 {
        u32 idx, hash = skb->rxhash;
@@ -1191,13 +1181,9 @@ static struct sock *fanout_demux_hash(struct packet_fanout *f, struct sk_buff *s
 
 static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
 {
-       int cur, old;
+       unsigned int val = atomic_inc_return(&f->rr_cur);
 
-       cur = atomic_read(&f->rr_cur);
-       while ((old = atomic_cmpxchg(&f->rr_cur, cur,
-                                    fanout_rr_next(f, num))) != cur)
-               cur = old;
-       return f->arr[cur];
+       return f->arr[val % num];
 }
 
 static struct sock *fanout_demux_cpu(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
@@ -1211,7 +1197,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
                             struct packet_type *pt, struct net_device *orig_dev)
 {
        struct packet_fanout *f = pt->af_packet_priv;
-       unsigned int num = f->num_members;
+       unsigned int num = ACCESS_ONCE(f->num_members);
        struct packet_sock *po;
        struct sock *sk;
 
@@ -1277,10 +1263,10 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
 
 bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
 {
-       if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
-               return true;
+       if (sk->sk_family != PF_PACKET)
+               return false;
 
-       return false;
+       return ptype->af_packet_priv == pkt_sk(sk)->fanout;
 }
 
 static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
index 9e07c75..be3eecd 100644 (file)
@@ -178,6 +178,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
                }
        }
 
+       if (trans == NULL) {
+               kmem_cache_free(rds_conn_slab, conn);
+               conn = ERR_PTR(-ENODEV);
+               goto out;
+       }
+
        conn->c_trans = trans;
 
        ret = trans->conn_alloc(conn, gfp);
index e8fdb17..a985158 100644 (file)
@@ -759,8 +759,10 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
        }
 
        ibmr = rds_ib_alloc_fmr(rds_ibdev);
-       if (IS_ERR(ibmr))
+       if (IS_ERR(ibmr)) {
+               rds_ib_dev_put(rds_ibdev);
                return ibmr;
+       }
 
        ret = rds_ib_map_fmr(rds_ibdev, ibmr, sg, nents);
        if (ret == 0)
index f1c016c..a4adb39 100644 (file)
@@ -176,7 +176,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
 
        /* check for all kinds of wrapping and the like */
        start = (unsigned long)optval;
-       if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) {
+       if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) {
                ret = -EINVAL;
                goto out;
        }
index 78205e2..4204e3b 100644 (file)
@@ -235,8 +235,15 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
                        }
 
                        to_copy = min(tc->t_tinc_data_rem, left);
-                       pskb_pull(clone, offset);
-                       pskb_trim(clone, to_copy);
+                       if (!pskb_pull(clone, offset) ||
+                           pskb_trim(clone, to_copy)) {
+                               pr_warn("rds_tcp_data_recv: pull/trim failed "
+                                       "left %zu data_rem %zu skb_len %d\n",
+                                       left, tc->t_tinc_data_rem, skb->len);
+                               kfree_skb(clone);
+                               desc->error = -ENOMEM;
+                               goto out;
+                       }
                        skb_queue_tail(&tinc->ti_skb_list, clone);
 
                        rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
index 686fb1a..233dbe6 100644 (file)
@@ -195,7 +195,8 @@ static void rose_kill_by_device(struct net_device *dev)
 
                if (rose->device == dev) {
                        rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
-                       rose->neighbour->use--;
+                       if (rose->neighbour)
+                               rose->neighbour->use--;
                        rose->device = NULL;
                }
        }
index 5cc2da5..c67f5d3 100644 (file)
@@ -185,7 +185,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
                                                      msg->msg_iov, copy);
                } else {
                        ret = skb_copy_and_csum_datagram_iovec(skb, offset,
-                                                              msg->msg_iov);
+                                                              msg->msg_iov,
+                                                              copy);
                        if (ret == -EINVAL)
                                goto csum_copy_error;
                }
index 76388b0..581c06a 100644 (file)
@@ -681,7 +681,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
         * outstanding data and rely on the retransmission limit be reached
         * to shutdown the association.
         */
-       if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING)
+       if (t->asoc->state < SCTP_STATE_SHUTDOWN_PENDING)
                t->asoc->overall_error_count = 0;
 
        /* Clear the hb_sent flag to signal that we had a good
index fc63664..24e88af 100644 (file)
@@ -1539,8 +1539,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
 
        /* Supposedly, no process has access to the socket, but
         * the net layers still may.
+        * Also, sctp_destroy_sock() needs to be called with addr_wq_lock
+        * held and that should be grabbed before socket lock.
         */
-       sctp_local_bh_disable();
+       spin_lock_bh(&sctp_globals.addr_wq_lock);
        sctp_bh_lock_sock(sk);
 
        /* Hold the sock, since sk_common_release() will put sock_put()
@@ -1550,7 +1552,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
        sk_common_release(sk);
 
        sctp_bh_unlock_sock(sk);
-       sctp_local_bh_enable();
+       spin_unlock_bh(&sctp_globals.addr_wq_lock);
 
        sock_put(sk);
 
@@ -3499,6 +3501,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
        if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
                return 0;
 
+       spin_lock_bh(&sctp_globals.addr_wq_lock);
        if (val == 0 && sp->do_auto_asconf) {
                list_del(&sp->auto_asconf_list);
                sp->do_auto_asconf = 0;
@@ -3507,6 +3510,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
                    &sctp_auto_asconf_splist);
                sp->do_auto_asconf = 1;
        }
+       spin_unlock_bh(&sctp_globals.addr_wq_lock);
        return 0;
 }
 
@@ -3942,18 +3946,28 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        local_bh_disable();
        percpu_counter_inc(&sctp_sockets_allocated);
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+
+       /* Nothing can fail after this block, otherwise
+        * sctp_destroy_sock() will be called without addr_wq_lock held
+        */
        if (sctp_default_auto_asconf) {
+               spin_lock(&sctp_globals.addr_wq_lock);
                list_add_tail(&sp->auto_asconf_list,
                    &sctp_auto_asconf_splist);
                sp->do_auto_asconf = 1;
-       } else
+               spin_unlock(&sctp_globals.addr_wq_lock);
+       } else {
                sp->do_auto_asconf = 0;
+       }
+
        local_bh_enable();
 
        return 0;
 }
 
-/* Cleanup any SCTP per socket resources.  */
+/* Cleanup any SCTP per socket resources. Must be called with
+ * sctp_globals.addr_wq_lock held if sp->do_auto_asconf is true
+ */
 SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
 {
        struct sctp_sock *sp;
@@ -6719,6 +6733,19 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->mc_list = NULL;
 }
 
+static inline void sctp_copy_descendant(struct sock *sk_to,
+                                       const struct sock *sk_from)
+{
+       int ancestor_size = sizeof(struct inet_sock) +
+                           sizeof(struct sctp_sock) -
+                           offsetof(struct sctp_sock, auto_asconf_list);
+
+       if (sk_from->sk_family == PF_INET6)
+               ancestor_size += sizeof(struct ipv6_pinfo);
+
+       __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size);
+}
+
 /* Populate the fields of the newsk from the oldsk and migrate the assoc
  * and its messages to the newsk.
  */
@@ -6733,7 +6760,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        struct sk_buff *skb, *tmp;
        struct sctp_ulpevent *event;
        struct sctp_bind_hashbucket *head;
-       struct list_head tmplist;
 
        /* Migrate socket buffer sizes and all the socket level options to the
         * new socket.
@@ -6741,12 +6767,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        newsk->sk_sndbuf = oldsk->sk_sndbuf;
        newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
        /* Brute force copy old sctp opt. */
-       if (oldsp->do_auto_asconf) {
-               memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist));
-               inet_sk_copy_descendant(newsk, oldsk);
-               memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist));
-       } else
-               inet_sk_copy_descendant(newsk, oldsk);
+       sctp_copy_descendant(newsk, oldsk);
 
        /* Restore the ep value that was overwritten with the above structure
         * copy.
index 116cf9d..10ea25a 100644 (file)
@@ -1911,14 +1911,12 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
        int err, ctl_len, iov_size, total_len;
 
        err = -EFAULT;
-       if (MSG_CMSG_COMPAT & flags) {
-               if (get_compat_msghdr(msg_sys, msg_compat))
-                       return -EFAULT;
-       } else {
+       if (MSG_CMSG_COMPAT & flags)
+               err = get_compat_msghdr(msg_sys, msg_compat);
+       else
                err = copy_msghdr_from_user(msg_sys, msg);
-               if (err)
-                       return err;
-       }
+       if (err)
+               return err;
 
        /* do not move before msg_sys is valid */
        err = -EMSGSIZE;
@@ -2130,14 +2128,12 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
        struct sockaddr __user *uaddr;
        int __user *uaddr_len;
 
-       if (MSG_CMSG_COMPAT & flags) {
-               if (get_compat_msghdr(msg_sys, msg_compat))
-                       return -EFAULT;
-       } else {
+       if (MSG_CMSG_COMPAT & flags)
+               err = get_compat_msghdr(msg_sys, msg_compat);
+       else
                err = copy_msghdr_from_user(msg_sys, msg);
-               if (err)
-                       return err;
-       }
+       if (err)
+               return err;
 
        err = -EMSGSIZE;
        if (msg_sys->msg_iovlen > UIO_MAXIOV)
index 3ad435a..b56f23e 100644 (file)
@@ -59,7 +59,7 @@ static void xprt_free_allocation(struct rpc_rqst *req)
 
        dprintk("RPC:        free allocations for req= %p\n", req);
        BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
-       xbufp = &req->rq_private_buf;
+       xbufp = &req->rq_rcv_buf;
        free_page((unsigned long)xbufp->head[0].iov_base);
        xbufp = &req->rq_snd_buf;
        free_page((unsigned long)xbufp->head[0].iov_base);
index d77a4f0..3a82fec 100644 (file)
@@ -811,6 +811,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
 {
        struct socket *sock = transport->sock;
        struct sock *sk = transport->inet;
+       struct rpc_xprt *xprt = &transport->xprt;
 
        if (sk == NULL)
                return;
@@ -824,6 +825,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
        sk->sk_user_data = NULL;
 
        xs_restore_old_callbacks(transport, sk);
+       xprt_clear_connected(xprt);
        write_unlock_bh(&sk->sk_callback_lock);
 
        sk->sk_no_check = 0;
index 058941e..580ecf2 100644 (file)
@@ -1541,6 +1541,8 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
                u32 new_ref = new_tport->ref;
                struct tipc_msg *msg = buf_msg(buf);
 
+               security_sk_clone(sock->sk, new_sock->sk);
+
                lock_sock(new_sk);
 
                /*
index 8705ee3..9b1f371 100644 (file)
@@ -1870,6 +1870,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo)
                unix_state_unlock(sk);
                timeo = schedule_timeout(timeo);
                unix_state_lock(sk);
+
+               if (sock_flag(sk, SOCK_DEAD))
+                       break;
+
                clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
        }
 
@@ -1930,6 +1934,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                struct sk_buff *skb;
 
                unix_state_lock(sk);
+               if (sock_flag(sk, SOCK_DEAD)) {
+                       err = -ECONNRESET;
+                       goto unlock;
+               }
                skb = skb_peek(&sk->sk_receive_queue);
                if (skb == NULL) {
                        unix_sk(sk)->recursion_level = 0;
index 3346f42..4a19a7f 100644 (file)
@@ -125,7 +125,7 @@ my $ksource = $ARGV[0];
 my $kconfig = $ARGV[1];
 my $lsmod_file = $ENV{'LSMOD'};
 
-my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`;
 chomp @makefiles;
 
 my %depends;
index 5e29610..799d734 100644 (file)
@@ -375,7 +375,7 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
 
                if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
                        if (make_nop)
-                               ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
+                               ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
                        if (warn_on_notrace_sect && !once) {
                                printf("Section %s has mcount callers being ignored\n",
                                       txtname);
index 2e2395d..7817bb0 100644 (file)
@@ -172,6 +172,12 @@ static noinline void key_gc_unused_key(struct key *key)
 {
        key_check(key);
 
+       /* Throw away the key data if the key is instantiated */
+       if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+           !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+           key->type->destroy)
+               key->type->destroy(key);
+
        security_key_free(key);
 
        /* deal with the user's key tracking and quota */
@@ -186,10 +192,6 @@ static noinline void key_gc_unused_key(struct key *key)
        if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
                atomic_dec(&key->user->nikeys);
 
-       /* now throw away the key memory */
-       if (key->type->destroy)
-               key->type->destroy(key);
-
        key_user_put(key->user);
 
        kfree(key->description);
index 0cd7097..c279f2f 100644 (file)
@@ -1011,7 +1011,7 @@ static void selinux_write_opts(struct seq_file *m,
                seq_puts(m, prefix);
                if (has_comma)
                        seq_putc(m, '\"');
-               seq_puts(m, opts->mnt_opts[i]);
+               seq_escape(m, opts->mnt_opts[i], "\"\n\\");
                if (has_comma)
                        seq_putc(m, '\"');
        }
index 0920ea3..5776921 100644 (file)
@@ -100,6 +100,12 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] =
        { XFRM_MSG_FLUSHPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
        { XFRM_MSG_NEWAE,       NETLINK_XFRM_SOCKET__NLMSG_WRITE },
        { XFRM_MSG_GETAE,       NETLINK_XFRM_SOCKET__NLMSG_READ  },
+       { XFRM_MSG_REPORT,      NETLINK_XFRM_SOCKET__NLMSG_READ  },
+       { XFRM_MSG_MIGRATE,     NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+       { XFRM_MSG_NEWSADINFO,  NETLINK_XFRM_SOCKET__NLMSG_READ  },
+       { XFRM_MSG_GETSADINFO,  NETLINK_XFRM_SOCKET__NLMSG_READ  },
+       { XFRM_MSG_GETSPDINFO,  NETLINK_XFRM_SOCKET__NLMSG_READ  },
+       { XFRM_MSG_MAPPING,     NETLINK_XFRM_SOCKET__NLMSG_READ  },
 };
 
 static struct nlmsg_perm nlmsg_audit_perms[] =
index 885683a..e040621 100644 (file)
@@ -9,6 +9,14 @@ menuconfig SND_ARM
          Drivers that are implemented on ASoC can be found in
          "ALSA for SoC audio support" section.
 
+config SND_PXA2XX_LIB
+       tristate
+       select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
+       select SND_DMAENGINE_PCM
+
+config SND_PXA2XX_LIB_AC97
+       bool
+
 if SND_ARM
 
 config SND_ARMAACI
@@ -21,13 +29,6 @@ config SND_PXA2XX_PCM
        tristate
        select SND_PCM
 
-config SND_PXA2XX_LIB
-       tristate
-       select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
-
-config SND_PXA2XX_LIB_AC97
-       bool
-
 config SND_PXA2XX_AC97
        tristate "AC97 driver for the Intel PXA2xx chip"
        depends on ARCH_PXA
index eaa198e..f33e3cc 100644 (file)
@@ -181,8 +181,10 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
        }
 #endif
  
-       strcpy(card->driver, emu->card_capabilities->driver);
-       strcpy(card->shortname, emu->card_capabilities->name);
+       strlcpy(card->driver, emu->card_capabilities->driver,
+               sizeof(card->driver));
+       strlcpy(card->shortname, emu->card_capabilities->name,
+               sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
                 card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
index f35284b..8295950 100644 (file)
@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp)
        snd_emu10k1_ptr_write(hw, Z2, ch, 0);
 
        /* invalidate maps */
-       temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
+       temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
        snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
 #if 0
@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp)
                snd_emu10k1_ptr_write(hw, CDF, ch, sample);
 
                /* invalidate maps */
-               temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
+               temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
                snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
                snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
                
index d37b946..705e73e 100644 (file)
@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        snd_emu10k1_ptr_write(emu, TCB, 0, 0);  /* taken from original driver */
        snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
 
-       silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        for (ch = 0; ch < NUM_G; ch++) {
                snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page);
                snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
        }
 
+       if (emu->address_mode == 0) {
+               /* use 16M in 4G */
+               outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
+       }
+
        return 0;
 }
 
@@ -1390,7 +1395,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         *
         */
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
-        .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
+        .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
@@ -1528,7 +1533,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
-        .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
+        .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
@@ -1832,8 +1837,10 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
 
        is_audigy = emu->audigy = c->emu10k2_chip;
 
+       /* set addressing mode */
+       emu->address_mode = is_audigy ? 0 : 1;
        /* set the DMA transfer mask */
-       emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+       emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK;
        if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
            pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
                snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
@@ -1856,7 +1863,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                               32 * 1024, &emu->ptb_pages) < 0) {
+                               (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
                err = -ENOMEM;
                goto error;
        }
@@ -1955,8 +1962,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
 
        /* Clear silent pages and set up pointers */
        memset(emu->silent_page.area, 0, PAGE_SIZE);
-       silent_page = emu->silent_page.addr << 1;
-       for (idx = 0; idx < MAXPAGES; idx++)
+       silent_page = emu->silent_page.addr << emu->address_mode;
+       for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
                ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
 
        /* set up voice indices */
index e22b8e2..c673d2b 100644 (file)
@@ -379,7 +379,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        snd_emu10k1_ptr_write(emu, Z1, voice, 0);
        snd_emu10k1_ptr_write(emu, Z2, voice, 0);
        /* invalidate maps */
-       silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
        snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
        /* modulation envelope */
index bc38dd4..9c499e6 100644 (file)
@@ -241,31 +241,22 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
        u32 value2;
-       unsigned long flags;
        u32 rate;
 
        if (emu->card_capabilities->emu_model) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x38, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x1) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x2a, &value);
                        snd_emu1010_fpga_read(emu, 0x2b, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
                } else {
                        snd_iprintf(buffer, "ADAT Unlocked\n");
                }
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x20, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x4) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x28, &value);
                        snd_emu1010_fpga_read(emu, 0x29, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
                } else {
@@ -410,14 +401,11 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
 {
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
-       unsigned long flags;
        int i;
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
 
        for(i = 0; i < 0x40; i+=1) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, i, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f);
        }
 }
index 4f502a2..87b7c65 100644 (file)
  * aligned pages in others
  */
 #define __set_ptb_entry(emu,page,addr) \
-       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
+       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
 
 #define UNIT_PAGES             (PAGE_SIZE / EMUPAGESIZE)
-#define MAX_ALIGN_PAGES                (MAXPAGES / UNIT_PAGES)
+#define MAX_ALIGN_PAGES0               (MAXPAGES0 / UNIT_PAGES)
+#define MAX_ALIGN_PAGES1               (MAXPAGES1 / UNIT_PAGES)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> PAGE_SHIFT)
 /* get offset address from aligned page */
@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis
                }
                page = blk->mapped_page + blk->pages;
        }
-       size = MAX_ALIGN_PAGES - page;
+       size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page;
        if (size >= max_size) {
                *nextp = pos;
                return page;
@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
                q = get_emu10k1_memblk(p, mapped_link);
                end_page = q->mapped_page;
        } else
-               end_page = MAX_ALIGN_PAGES;
+               end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
 
        /* remove links */
        list_del(&blk->mapped_link);
@@ -305,7 +306,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
        if (snd_BUG_ON(!emu))
                return NULL;
        if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
-                      runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
+                      runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
                return NULL;
        hdr = emu->memhdr;
        if (snd_BUG_ON(!hdr))
index dcc95c5..1da4738 100644 (file)
@@ -3099,11 +3099,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
          .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+         AZX_DCAPS_NO_64BIT |
          AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
 #else
        /* this entry seems still valid -- i.e. without emu20kx chip */
        { PCI_DEVICE(0x1102, 0x0009),
          .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+         AZX_DCAPS_NO_64BIT |
          AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
 #endif
        /* Vortex86MX */
index 843d9f3..de51abc 100644 (file)
@@ -4495,6 +4495,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
+       SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
@@ -4598,6 +4599,14 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = {
          .patch = patch_conexant_auto },
        { .id = 0x14f150b9, .name = "CX20665",
          .patch = patch_conexant_auto },
+       { .id = 0x14f150f1, .name = "CX20721",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150f2, .name = "CX20722",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150f3, .name = "CX20723",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150f4, .name = "CX20724",
+         .patch = patch_conexant_auto },
        { .id = 0x14f1510f, .name = "CX20751/2",
          .patch = patch_conexant_auto },
        { .id = 0x14f15110, .name = "CX20751/2",
@@ -4632,6 +4641,10 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab");
 MODULE_ALIAS("snd-hda-codec-id:14f150ac");
 MODULE_ALIAS("snd-hda-codec-id:14f150b8");
 MODULE_ALIAS("snd-hda-codec-id:14f150b9");
+MODULE_ALIAS("snd-hda-codec-id:14f150f1");
+MODULE_ALIAS("snd-hda-codec-id:14f150f2");
+MODULE_ALIAS("snd-hda-codec-id:14f150f3");
+MODULE_ALIAS("snd-hda-codec-id:14f150f4");
 MODULE_ALIAS("snd-hda-codec-id:14f1510f");
 MODULE_ALIAS("snd-hda-codec-id:14f15110");
 MODULE_ALIAS("snd-hda-codec-id:14f15111");
index 240658b..9b89822 100644 (file)
@@ -4980,6 +4980,7 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
 static int hp_blike_system(u32 subsystem_id)
 {
        switch (subsystem_id) {
+       case 0x103c1473: /* HP ProBook 6550b */
        case 0x103c1520:
        case 0x103c1521:
        case 0x103c1523:
index 561d5e0..e99c10b 100644 (file)
@@ -475,10 +475,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        if (gpio_nreset >= 0) {
                /* Reset codec */
                gpio_direction_output(gpio_nreset, 0);
-               udelay(1);
+               mdelay(1);
                gpio_set_value(gpio_nreset, 1);
                /* Give the codec time to wake up */
-               udelay(1);
+               mdelay(1);
        }
 
        cs4271->gpio_nreset = gpio_nreset;
index f6aef58..2a012d3 100644 (file)
@@ -485,7 +485,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec,
 
                        /* Fast VMID ramp at 2*2.5k */
                        snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
-                                           WM8737_VMIDSEL_MASK, 0x4);
+                                           WM8737_VMIDSEL_MASK,
+                                           2 << WM8737_VMIDSEL_SHIFT);
 
                        /* Bring VMID up */
                        snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT,
@@ -499,7 +500,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec,
 
                /* VMID at 2*300k */
                snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
-                                   WM8737_VMIDSEL_MASK, 2);
+                                   WM8737_VMIDSEL_MASK,
+                                   1 << WM8737_VMIDSEL_SHIFT);
 
                break;
 
index 57ad22a..6ab4f27 100644 (file)
@@ -117,7 +117,7 @@ static struct {
 };
 
 static unsigned int rates_11289[] = {
-       44100, 88235,
+       44100, 88200,
 };
 
 static struct snd_pcm_hw_constraint_list constraints_11289 = {
@@ -144,7 +144,7 @@ static struct snd_pcm_hw_constraint_list constraints_16384 = {
 };
 
 static unsigned int rates_16934[] = {
-       44100, 88235,
+       44100, 88200,
 };
 
 static struct snd_pcm_hw_constraint_list constraints_16934 = {
@@ -162,7 +162,7 @@ static struct snd_pcm_hw_constraint_list constraints_18432 = {
 };
 
 static unsigned int rates_22579[] = {
-       44100, 88235, 1764000
+       44100, 88200, 176400
 };
 
 static struct snd_pcm_hw_constraint_list constraints_22579 = {
@@ -180,7 +180,7 @@ static struct snd_pcm_hw_constraint_list constraints_24576 = {
 };
 
 static unsigned int rates_36864[] = {
-       48000, 96000, 19200
+       48000, 96000, 192000
 };
 
 static struct snd_pcm_hw_constraint_list constraints_36864 = {
index db94931..0bb4a64 100644 (file)
@@ -172,7 +172,7 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec,
 #define WM8903_VMID_BUF_ENA_WIDTH                    1  /* VMID_BUF_ENA */
 
 #define WM8903_VMID_RES_50K                          2
-#define WM8903_VMID_RES_250K                         3
+#define WM8903_VMID_RES_250K                         4
 #define WM8903_VMID_RES_5K                           6
 
 /*
index 77ff1d7..f8b9930 100644 (file)
@@ -282,7 +282,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec)
                snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2,
                                    WM8955_K_17_9_MASK,
                                    (pll.k >> 9) & WM8955_K_17_9_MASK);
-               snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2,
+               snd_soc_update_bits(codec, WM8955_PLL_CONTROL_3,
                                    WM8955_K_8_0_MASK,
                                    pll.k & WM8955_K_8_0_MASK);
                if (pll.k)
index b2abe93..c7911fd 100644 (file)
@@ -186,7 +186,7 @@ SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
 SOC_ENUM("ADC Polarity", wm8960_enum[0]),
 SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
 
-SOC_ENUM("DAC Polarity", wm8960_enum[2]),
+SOC_ENUM("DAC Polarity", wm8960_enum[1]),
 SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,
                    wm8960_get_deemph, wm8960_put_deemph),
 
@@ -336,7 +336,7 @@ static const struct snd_soc_dapm_route audio_paths[] = {
        { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
        { "Right Input Mixer", NULL, "RINPUT1", },  /* Really Boost Switch */
        { "Right Input Mixer", NULL, "RINPUT2" },
-       { "Right Input Mixer", NULL, "LINPUT3" },
+       { "Right Input Mixer", NULL, "RINPUT3" },
 
        { "Left ADC", NULL, "Left Input Mixer" },
        { "Right ADC", NULL, "Right Input Mixer" },
index b73f226..9a56798 100644 (file)
@@ -2449,7 +2449,7 @@ static struct {
 };
 
 static int fs_ratios[] = {
-       64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536
+       64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536
 };
 
 static int bclk_divs[] = {
index a0f7d3c..23deb67 100644 (file)
@@ -1,7 +1,6 @@
 config SND_PXA2XX_SOC
        tristate "SoC Audio for the Intel PXA2xx chip"
        depends on ARCH_PXA
-       select SND_ARM
        select SND_PXA2XX_LIB
        help
          Say Y or M if you want to add support for codecs attached to
@@ -15,7 +14,6 @@ config SND_PXA2XX_AC97
 config SND_PXA2XX_SOC_AC97
        tristate
        select AC97_BUS
-       select SND_ARM
        select SND_PXA2XX_LIB_AC97
        select SND_SOC_AC97_BUS
 
index 1d83a40..3dc1b8a 100644 (file)
@@ -2675,12 +2675,18 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                kfree(w);
                return -ENOMEM;
        }
-       if (dapm->codec && dapm->codec->name_prefix)
+       if (dapm->codec && dapm->codec->name_prefix) {
                snprintf(w->name, name_len, "%s %s",
                        dapm->codec->name_prefix, widget->name);
-       else
+               if (widget->sname)
+                       w->sname = kasprintf(GFP_KERNEL, "%s %s",
+                                            dapm->codec->name_prefix,
+                                            widget->sname);
+       } else {
                snprintf(w->name, name_len, "%s", widget->name);
-
+               if (widget->sname)
+                       w->sname = kasprintf(GFP_KERNEL, "%s", widget->sname);
+       }
        switch (w->id) {
        case snd_soc_dapm_switch:
        case snd_soc_dapm_mixer:
index 319754c..646b667 100644 (file)
@@ -69,7 +69,8 @@ snd_emux_init_seq_oss(struct snd_emux *emu)
        struct snd_seq_oss_reg *arg;
        struct snd_seq_device *dev;
 
-       if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS,
+       /* using device#1 here for avoiding conflicts with OPL3 */
+       if (snd_seq_device_new(emu->card, 1, SNDRV_SEQ_DEV_ID_OSS,
                               sizeof(struct snd_seq_oss_reg), &dev) < 0)
                return;
 
@@ -118,12 +119,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (snd_BUG_ON(!arg || !emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
-
-       if (!snd_emux_inc_count(emu)) {
-               mutex_unlock(&emu->register_mutex);
+       if (!snd_emux_inc_count(emu))
                return -EFAULT;
-       }
 
        memset(&callback, 0, sizeof(callback));
        callback.owner = THIS_MODULE;
@@ -135,7 +132,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (p == NULL) {
                snd_printk(KERN_ERR "can't create port\n");
                snd_emux_dec_count(emu);
-               mutex_unlock(&emu->register_mutex);
                return -ENOMEM;
        }
 
@@ -148,8 +144,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        reset_port_mode(p, arg->seq_mode);
 
        snd_emux_reset_port(p);
-
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
@@ -195,13 +189,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
        if (snd_BUG_ON(!emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
        snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
        snd_seq_event_port_detach(p->chset.client, p->chset.port);
        snd_emux_dec_count(emu);
 
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
index 7778b8e..a020920 100644 (file)
@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu)
        if (emu->voices)
                snd_emux_terminate_all(emu);
                
-       mutex_lock(&emu->register_mutex);
        if (emu->client >= 0) {
                snd_seq_delete_kernel_client(emu->client);
                emu->client = -1;
        }
-       mutex_unlock(&emu->register_mutex);
 }
 
 
@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data,
 /*
  * increment usage count
  */
-int
-snd_emux_inc_count(struct snd_emux *emu)
+static int
+__snd_emux_inc_count(struct snd_emux *emu)
 {
        emu->used++;
        if (!try_module_get(emu->ops.owner))
@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu)
        return 1;
 }
 
+int snd_emux_inc_count(struct snd_emux *emu)
+{
+       int ret;
+
+       mutex_lock(&emu->register_mutex);
+       ret = __snd_emux_inc_count(emu);
+       mutex_unlock(&emu->register_mutex);
+       return ret;
+}
 
 /*
  * decrease usage count
  */
-void
-snd_emux_dec_count(struct snd_emux *emu)
+static void
+__snd_emux_dec_count(struct snd_emux *emu)
 {
        module_put(emu->card->module);
        emu->used--;
@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu)
        module_put(emu->ops.owner);
 }
 
+void snd_emux_dec_count(struct snd_emux *emu)
+{
+       mutex_lock(&emu->register_mutex);
+       __snd_emux_dec_count(emu);
+       mutex_unlock(&emu->register_mutex);
+}
 
 /*
  * Routine that is called upon a first use of a particular port
@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_init_port(p);
-       snd_emux_inc_count(emu);
+       __snd_emux_inc_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
-       snd_emux_dec_count(emu);
+       __snd_emux_dec_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
index 88160b7..488e531 100644 (file)
@@ -838,6 +838,8 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
        case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
        case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
        case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
+       case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
+       case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
        case USB_ID(0x046d, 0x0991):
        /* Most audio usb devices lie about volume resolution.
         * Most Logitech webcams have res = 384.
@@ -1423,11 +1425,6 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
                snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid);
                return -EINVAL;
        }
-       /* no bmControls field (e.g. Maya44) -> ignore */
-       if (desc->bLength <= 10 + input_pins) {
-               snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid);
-               return 0;
-       }
 
        num_ins = 0;
        ich = 0;
@@ -1435,6 +1432,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
                err = parse_audio_unit(state, desc->baSourceID[pin]);
                if (err < 0)
                        return err;
+               /* no bmControls field (e.g. Maya44) -> ignore */
+               if (desc->bLength <= 10 + input_pins)
+                       continue;
                err = check_input_term(state, desc->baSourceID[pin], &iterm);
                if (err < 0)
                        return err;
index 1e0798f..893b750 100644 (file)
@@ -312,6 +312,20 @@ static const struct usbmix_name_map scms_usb3318_map[] = {
        { 0 }
 };
 
+/* Bose companion 5, the dB conversion factor is 16 instead of 256 */
+static struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
+static struct usbmix_name_map bose_companion5_map[] = {
+       { 3, NULL, .dB = &bose_companion5_dB },
+       { 0 }   /* terminator */
+};
+
+/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */
+static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000};
+static struct usbmix_name_map dragonfly_1_2_map[] = {
+       { 7, NULL, .dB = &dragonfly_1_2_dB },
+       { 0 }   /* terminator */
+};
+
 /*
  * Control map entries
  */
@@ -379,6 +393,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .map = scratch_live_map,
                .ignore_ctl_error = 1,
        },
+       {
+               /* MAYA44 USB+ */
+               .id = USB_ID(0x2573, 0x0008),
+               .map = maya44_map,
+       },
        {
                /* KEF X300A */
                .id = USB_ID(0x27ac, 0x1000),
@@ -389,6 +408,16 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x25c4, 0x0003),
                .map = scms_usb3318_map,
        },
+       {
+               /* Bose Companion 5 */
+               .id = USB_ID(0x05a7, 0x1020),
+               .map = bose_companion5_map,
+       },
+       {
+               /* Dragonfly DAC 1.2 */
+               .id = USB_ID(0x21b4, 0x0081),
+               .map = dragonfly_1_2_map,
+       },
        { 0 } /* terminator */
 };
 
index b38dde0..c014f00 100644 (file)
@@ -2383,6 +2383,74 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+/* Steinberg devices */
+{
+       /* Steinberg MI2 */
+       USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = & (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = &(const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+{
+       /* Steinberg MI4 */
+       USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = & (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = &(const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 /* TerraTec devices */
 {
        USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012),
index e45d2b1..6c871c0 100644 (file)
@@ -739,10 +739,10 @@ $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
 $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
 
 $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
 
 $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
index 2cd88c1..7a75ecb 100644 (file)
@@ -796,25 +796,19 @@ static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp)
 static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp)
 {
        ssize_t ret;
-       u32 nr;
+       u32 nr[2];
 
        ret = read(fd, &nr, sizeof(nr));
        if (ret != (ssize_t)sizeof(nr))
-               nr = -1; /* interpreted as error */
+               nr[0] = nr[1] = -1; /* interpreted as error */
 
-       if (ph->needs_swap)
-               nr = bswap_32(nr);
-
-       fprintf(fp, "# nrcpus online : %u\n", nr);
-
-       ret = read(fd, &nr, sizeof(nr));
-       if (ret != (ssize_t)sizeof(nr))
-               nr = -1; /* interpreted as error */
-
-       if (ph->needs_swap)
-               nr = bswap_32(nr);
+       if (ph->needs_swap) {
+               nr[0] = bswap_32(nr[0]);
+               nr[1] = bswap_32(nr[1]);
+       }
 
-       fprintf(fp, "# nrcpus avail : %u\n", nr);
+       fprintf(fp, "# nrcpus online : %u\n", nr[1]);
+       fprintf(fp, "# nrcpus avail : %u\n", nr[0]);
 }
 
 static void print_version(struct perf_header *ph, int fd, FILE *fp)