]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'powerpc-4.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 25 Mar 2015 00:23:03 +0000 (17:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 25 Mar 2015 00:23:03 +0000 (17:23 -0700)
Pull powerpc fixes from Michael Ellerman:

 - Fix the MCE code to use CONFIG_KVM_BOOK3S_64_HANDLER

 - Little endian fixes for post mobility device tree update

 - Add PVR for POWER8NVL processor

 - Fixes for hypervisor doorbell handling

* tag 'powerpc-4.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux:
  powerpc/book3s: Fix the MCE code to use CONFIG_KVM_BOOK3S_64_HANDLER
  powerpc/pseries: Little endian fixes for post mobility device tree update
  powerpc: Add PVR for POWER8NVL processor
  powerpc/powernv: Fixes for hypervisor doorbell handling

325 files changed:
MAINTAINERS
Makefile
arch/arm/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/kvm_mmu.h
arch/arm/kernel/setup.c
arch/arm/kvm/mmu.c
arch/arm/mm/cache-l2x0.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault.c
arch/arm/mm/pageattr.c
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/proc-fns.h
arch/arm64/kernel/efi.c
arch/arm64/mm/dma-mapping.c
arch/nios2/include/uapi/asm/Kbuild
arch/nios2/mm/fault.c
arch/s390/kvm/kvm-s390.c
arch/sparc/Kconfig
arch/sparc/include/asm/hypervisor.h
arch/sparc/include/asm/io_64.h
arch/sparc/include/asm/starfire.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/hvapi.c
arch/sparc/kernel/hvcalls.S
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/starfire.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/traps_64.c
arch/sparc/lib/memmove.S
arch/sparc/mm/init_64.c
arch/x86/boot/compressed/aslr.c
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/crypto/aesni-intel_glue.c
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/page_types.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/module.c
arch/x86/kernel/setup.c
arch/x86/kernel/traps.c
arch/x86/kernel/xsave.c
arch/x86/kvm/i8259.c
arch/x86/kvm/ioapic.c
arch/x86/kvm/lapic.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/pci/common.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/x86/vdso/vdso32/sigreturn.S
drivers/acpi/pci_irq.c
drivers/ata/libata-core.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
drivers/char/virtio_console.c
drivers/clocksource/time-efm32.c
drivers/clocksource/timer-sun5i.c
drivers/cpuidle/cpuidle-mvebu-v7.c
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dw/platform.c
drivers/dma/imx-sdma.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_connector.c [deleted file]
drivers/gpu/drm/exynos/exynos_drm_connector.h [deleted file]
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c
drivers/gpu/drm/radeon/radeon_kfd.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-tivo.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_wac.c
drivers/ide/ide-tape.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/isdn/icn/icn.c
drivers/md/dm-io.c
drivers/md/dm-snap.c
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid0.c
drivers/mfd/kempld-core.c
drivers/mfd/rtsx_usb.c
drivers/mmc/core/pwrseq_simple.c
drivers/mtd/ubi/eba.c
drivers/net/can/Kconfig
drivers/net/can/usb/kvaser_usb.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/usb/cx82310_eth.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/vendor.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/xen-netback/netback.c
drivers/of/base.c
drivers/of/irq.c
drivers/of/unittest.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/rsrc_pci.c [deleted file]
drivers/phy/phy-armada375-usb2.c
drivers/phy/phy-core.c
drivers/phy/phy-exynos-dp-video.c
drivers/phy/phy-exynos-mipi-video.c
drivers/phy/phy-exynos4210-usb2.c
drivers/phy/phy-exynos4x12-usb2.c
drivers/phy/phy-exynos5-usbdrd.c
drivers/phy/phy-exynos5250-usb2.c
drivers/phy/phy-hix5hd2-sata.c
drivers/phy/phy-miphy28lp.c
drivers/phy/phy-miphy365x.c
drivers/phy/phy-omap-control.c
drivers/phy/phy-omap-usb2.c
drivers/phy/phy-rockchip-usb.c
drivers/phy/phy-ti-pipe3.c
drivers/phy/phy-twl4030-usb.c
drivers/phy/phy-xgene.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/sunxi/pinctrl-sunxi.h
drivers/powercap/intel_rapl.c
drivers/regulator/core.c
drivers/regulator/palmas-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/rtc-at91rm9200.c
drivers/scsi/ipr.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/spi/spi-dw-mid.c
drivers/spi/spi-qup.c
drivers/spi/spi.c
drivers/staging/vt6655/device_main.c
drivers/staging/vt6655/rf.c
drivers/staging/vt6656/rf.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/loopback/tcm_loop.c
drivers/target/target_core_device.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_io.c
drivers/tty/serial/8250/8250_dw.c
drivers/usb/chipidea/udc.c
drivers/usb/common/usb-otg-fsm.c
drivers/usb/dwc2/core_intr.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/function/g_zero.h
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/gadget/legacy/zero.c
drivers/usb/host/ehci-atmel.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/isp1760/isp1760-core.c
drivers/usb/isp1760/isp1760-udc.c
drivers/usb/musb/Kconfig
drivers/usb/phy/phy-am335x-control.c
drivers/usb/storage/unusual_uas.h
drivers/vhost/scsi.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/xen/xen-scsiback.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/qgroup.c
fs/btrfs/tests/inode-tests.c
fs/btrfs/transaction.c
fs/fuse/dev.c
fs/kernfs/file.c
fs/nfsd/nfs4layouts.c
fs/overlayfs/super.c
fs/proc/task_mmu.c
include/kvm/arm_vgic.h
include/linux/device-mapper.h
include/linux/libata.h
include/linux/mfd/palmas.h
include/linux/module.h
include/linux/netdevice.h
include/linux/pinctrl/consumer.h
include/linux/regulator/driver.h
include/linux/skbuff.h
include/net/dst.h
include/net/netfilter/nf_log.h
include/net/vxlan.h
include/target/target_core_backend.h
include/trace/events/regmap.h
include/uapi/linux/virtio_blk.h
include/uapi/linux/virtio_scsi.h
kernel/events/core.c
kernel/livepatch/core.c
lib/lz4/lz4_decompress.c
net/9p/trans_virtio.c
net/bridge/br_if.c
net/caif/caif_socket.c
net/compat.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/ip_forward.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_output.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/udp_offload.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/util.c
net/netfilter/nf_log.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_core.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nft_compat.c
net/netfilter/nft_hash.c
net/netfilter/xt_TPROXY.c
net/rds/iw_rdma.c
net/rxrpc/ar-recvmsg.c
net/sched/act_bpf.c
net/sched/cls_u32.c
net/socket.c
net/wireless/nl80211.c
net/xfrm/xfrm_policy.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_proc.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/da732x.c
sound/soc/codecs/es8328.c
sound/soc/codecs/pcm1681.c
sound/soc/codecs/rt286.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sn95031.c
sound/soc/codecs/tas5086.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/fsl/fsl_ssi.c
sound/soc/intel/sst-haswell-dsp.c
sound/soc/intel/sst-haswell-ipc.c
sound/soc/soc-core.c
tools/perf/util/annotate.c
virt/kvm/arm/vgic-v2.c
virt/kvm/arm/vgic-v3.c
virt/kvm/arm/vgic.c
virt/kvm/kvm_main.c

index 0e1abe8cc6840369966a5dc3a754f23a8eca94ab..358eb0105e008d4b89b0f485141f8b676884fdb3 100644 (file)
@@ -1741,7 +1741,7 @@ S:        Maintained
 F:     drivers/net/ethernet/atheros/
 
 ATM
-M:     Chas Williams <chas@cmf.nrl.navy.mil>
+M:     Chas Williams <3chas3@gmail.com>
 L:     linux-atm-general@lists.sourceforge.net (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
 W:     http://linux-atm.sourceforge.net
@@ -10207,6 +10207,13 @@ S:     Maintained
 F:     Documentation/usb/ohci.txt
 F:     drivers/usb/host/ohci*
 
+USB OTG FSM (Finite State Machine)
+M:     Peter Chen <Peter.Chen@freescale.com>
+T:     git git://github.com/hzpeterchen/linux-usb.git
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/common/usb-otg-fsm.c
+
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah.kh@samsung.com>
index e734965b160403185cf1f1342055ce0a4a956a77..14c722f9687766d5f672c74814c7c4298ea85110 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Hurr durr I'ma sheep
 
 # *DOCUMENTATION*
index 71e5fc7cfb18f489f3adadb20c6f8049421fb079..1d1800f71c5b3d372d33ec1e43acdaa35e17d3be 100644 (file)
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__  7
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
 #endif
 
 #ifdef __thumb__
 # define adrl adr
 #endif
 
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch  armv7-a
+.fpu   neon
+
 .text
 .syntax        unified         @ ARMv7-capable assembler is expected to handle this
 #ifdef __thumb2__
@@ -74,8 +78,6 @@
 .code   32
 #endif
 
-.fpu   neon
-
 .type  _bsaes_decrypt8,%function
 .align 4
 _bsaes_decrypt8:
@@ -2095,9 +2097,11 @@ bsaes_xts_decrypt:
        vld1.8  {q8}, [r0]                      @ initial tweak
        adr     r2, .Lxts_magic
 
+#ifndef        XTS_CHAIN_TWEAK
        tst     r9, #0xf                        @ if not multiple of 16
        it      ne                              @ Thumb2 thing, sanity check in ARM
        subne   r9, #0x10                       @ subtract another 16 bytes
+#endif
        subs    r9, #0x80
 
        blo     .Lxts_dec_short
index be068db960ee0006ac1aa25a4e69b95265404844..a4d3856e7d2477ec6379f1f10a9121e32f36a974 100644 (file)
@@ -701,14 +701,18 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__  7
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
 #endif
 
 #ifdef __thumb__
 # define adrl adr
 #endif
 
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch  armv7-a
+.fpu   neon
+
 .text
 .syntax        unified         @ ARMv7-capable assembler is expected to handle this
 #ifdef __thumb2__
@@ -717,8 +721,6 @@ $code.=<<___;
 .code   32
 #endif
 
-.fpu   neon
-
 .type  _bsaes_decrypt8,%function
 .align 4
 _bsaes_decrypt8:
@@ -2076,9 +2078,11 @@ bsaes_xts_decrypt:
        vld1.8  {@XMM[8]}, [r0]                 @ initial tweak
        adr     $magic, .Lxts_magic
 
+#ifndef        XTS_CHAIN_TWEAK
        tst     $len, #0xf                      @ if not multiple of 16
        it      ne                              @ Thumb2 thing, sanity check in ARM
        subne   $len, #0x10                     @ subtract another 16 bytes
+#endif
        subs    $len, #0x80
 
        blo     .Lxts_dec_short
index bf0fe99e8ca927e8b3894dabaf1e1fca9f079c3d..4cf48c3aca13e9afe7b852660afa4d5945994a93 100644 (file)
@@ -149,29 +149,28 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
        (__boundary - 1 < (end) - 1)? __boundary: (end);                \
 })
 
+#define kvm_pgd_index(addr)                    pgd_index(addr)
+
 static inline bool kvm_page_empty(void *ptr)
 {
        struct page *ptr_page = virt_to_page(ptr);
        return page_count(ptr_page) == 1;
 }
 
-
 #define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
 #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
 #define kvm_pud_table_empty(kvm, pudp) (0)
 
 #define KVM_PREALLOC_LEVEL     0
 
-static inline int kvm_prealloc_hwpgd(struct kvm *kvm, pgd_t *pgd)
+static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
-       return 0;
+       return kvm->arch.pgd;
 }
 
-static inline void kvm_free_hwpgd(struct kvm *kvm) { }
-
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
+static inline unsigned int kvm_get_hwpgd_size(void)
 {
-       return kvm->arch.pgd;
+       return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
 struct kvm;
index e55408e965596964ff8c8708dcfec529a559b1bc..1d60bebea4b8b7923748cd6eb2d25fc4299bfc32 100644 (file)
@@ -246,12 +246,9 @@ static int __get_cpu_architecture(void)
                if (cpu_arch)
                        cpu_arch += CPU_ARCH_ARMv3;
        } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
-               unsigned int mmfr0;
-
                /* Revised CPUID format. Read the Memory Model Feature
                 * Register 0 and check for VMSAv7 or PMSAv7 */
-               asm("mrc        p15, 0, %0, c0, c1, 4"
-                   : "=r" (mmfr0));
+               unsigned int mmfr0 = read_cpuid_ext(CPUID_EXT_MMFR0);
                if ((mmfr0 & 0x0000000f) >= 0x00000003 ||
                    (mmfr0 & 0x000000f0) >= 0x00000030)
                        cpu_arch = CPU_ARCH_ARMv7;
index 3e6859bc3e1170fc83489be9ba51a15c97b148a5..5656d79c5a44f4d2ca816e15b647abf29a114e0b 100644 (file)
@@ -290,7 +290,7 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        phys_addr_t addr = start, end = start + size;
        phys_addr_t next;
 
-       pgd = pgdp + pgd_index(addr);
+       pgd = pgdp + kvm_pgd_index(addr);
        do {
                next = kvm_pgd_addr_end(addr, end);
                if (!pgd_none(*pgd))
@@ -355,7 +355,7 @@ static void stage2_flush_memslot(struct kvm *kvm,
        phys_addr_t next;
        pgd_t *pgd;
 
-       pgd = kvm->arch.pgd + pgd_index(addr);
+       pgd = kvm->arch.pgd + kvm_pgd_index(addr);
        do {
                next = kvm_pgd_addr_end(addr, end);
                stage2_flush_puds(kvm, pgd, addr, next);
@@ -632,6 +632,20 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
                                     __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
 }
 
+/* Free the HW pgd, one page at a time */
+static void kvm_free_hwpgd(void *hwpgd)
+{
+       free_pages_exact(hwpgd, kvm_get_hwpgd_size());
+}
+
+/* Allocate the HW PGD, making sure that each page gets its own refcount */
+static void *kvm_alloc_hwpgd(void)
+{
+       unsigned int size = kvm_get_hwpgd_size();
+
+       return alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+}
+
 /**
  * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
  * @kvm:       The KVM struct pointer for the VM.
@@ -645,15 +659,31 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
  */
 int kvm_alloc_stage2_pgd(struct kvm *kvm)
 {
-       int ret;
        pgd_t *pgd;
+       void *hwpgd;
 
        if (kvm->arch.pgd != NULL) {
                kvm_err("kvm_arch already initialized?\n");
                return -EINVAL;
        }
 
+       hwpgd = kvm_alloc_hwpgd();
+       if (!hwpgd)
+               return -ENOMEM;
+
+       /* When the kernel uses more levels of page tables than the
+        * guest, we allocate a fake PGD and pre-populate it to point
+        * to the next-level page table, which will be the real
+        * initial page table pointed to by the VTTBR.
+        *
+        * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
+        * the PMD and the kernel will use folded pud.
+        * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
+        * pages.
+        */
        if (KVM_PREALLOC_LEVEL > 0) {
+               int i;
+
                /*
                 * Allocate fake pgd for the page table manipulation macros to
                 * work.  This is not used by the hardware and we have no
@@ -661,30 +691,32 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
                 */
                pgd = (pgd_t *)kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
                                       GFP_KERNEL | __GFP_ZERO);
+
+               if (!pgd) {
+                       kvm_free_hwpgd(hwpgd);
+                       return -ENOMEM;
+               }
+
+               /* Plug the HW PGD into the fake one. */
+               for (i = 0; i < PTRS_PER_S2_PGD; i++) {
+                       if (KVM_PREALLOC_LEVEL == 1)
+                               pgd_populate(NULL, pgd + i,
+                                            (pud_t *)hwpgd + i * PTRS_PER_PUD);
+                       else if (KVM_PREALLOC_LEVEL == 2)
+                               pud_populate(NULL, pud_offset(pgd, 0) + i,
+                                            (pmd_t *)hwpgd + i * PTRS_PER_PMD);
+               }
        } else {
                /*
                 * Allocate actual first-level Stage-2 page table used by the
                 * hardware for Stage-2 page table walks.
                 */
-               pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, S2_PGD_ORDER);
+               pgd = (pgd_t *)hwpgd;
        }
 
-       if (!pgd)
-               return -ENOMEM;
-
-       ret = kvm_prealloc_hwpgd(kvm, pgd);
-       if (ret)
-               goto out_err;
-
        kvm_clean_pgd(pgd);
        kvm->arch.pgd = pgd;
        return 0;
-out_err:
-       if (KVM_PREALLOC_LEVEL > 0)
-               kfree(pgd);
-       else
-               free_pages((unsigned long)pgd, S2_PGD_ORDER);
-       return ret;
 }
 
 /**
@@ -785,11 +817,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
                return;
 
        unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
-       kvm_free_hwpgd(kvm);
+       kvm_free_hwpgd(kvm_get_hwpgd(kvm));
        if (KVM_PREALLOC_LEVEL > 0)
                kfree(kvm->arch.pgd);
-       else
-               free_pages((unsigned long)kvm->arch.pgd, S2_PGD_ORDER);
+
        kvm->arch.pgd = NULL;
 }
 
@@ -799,7 +830,7 @@ static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
        pgd_t *pgd;
        pud_t *pud;
 
-       pgd = kvm->arch.pgd + pgd_index(addr);
+       pgd = kvm->arch.pgd + kvm_pgd_index(addr);
        if (WARN_ON(pgd_none(*pgd))) {
                if (!cache)
                        return NULL;
@@ -1089,7 +1120,7 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
        pgd_t *pgd;
        phys_addr_t next;
 
-       pgd = kvm->arch.pgd + pgd_index(addr);
+       pgd = kvm->arch.pgd + kvm_pgd_index(addr);
        do {
                /*
                 * Release kvm_mmu_lock periodically if the memory region is
index c6c7696b8db97e33344fdec64767d9409800cb06..8f15f70622a6aa30a9ff7f20fb6cea3a963fc53b 100644 (file)
@@ -1131,23 +1131,22 @@ static void __init l2c310_of_parse(const struct device_node *np,
        }
 
        ret = l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K);
-       if (ret)
-               return;
-
-       switch (assoc) {
-       case 16:
-               *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
-               *aux_val |= L310_AUX_CTRL_ASSOCIATIVITY_16;
-               *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
-               break;
-       case 8:
-               *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
-               *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
-               break;
-       default:
-               pr_err("L2C-310 OF cache associativity %d invalid, only 8 or 16 permitted\n",
-                      assoc);
-               break;
+       if (!ret) {
+               switch (assoc) {
+               case 16:
+                       *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
+                       *aux_val |= L310_AUX_CTRL_ASSOCIATIVITY_16;
+                       *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
+                       break;
+               case 8:
+                       *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
+                       *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
+                       break;
+               default:
+                       pr_err("L2C-310 OF cache associativity %d invalid, only 8 or 16 permitted\n",
+                              assoc);
+                       break;
+               }
        }
 
        prefetch = l2x0_saved_regs.prefetch_ctrl;
index 170a116d1b298c1befb81efdeaee49735362fd26..c27447653903f1134594fe309dc885285ea43bb3 100644 (file)
@@ -171,7 +171,7 @@ static int __dma_supported(struct device *dev, u64 mask, bool warn)
         */
        if (sizeof(mask) != sizeof(dma_addr_t) &&
            mask > (dma_addr_t)~0 &&
-           dma_to_pfn(dev, ~0) < max_pfn) {
+           dma_to_pfn(dev, ~0) < max_pfn - 1) {
                if (warn) {
                        dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
                                 mask);
index a982dc3190dfb3a841bbe196f76f58cdbb554f84..6333d9c178757fe4f365b8e765b2a9ea75e2b80b 100644 (file)
@@ -552,6 +552,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
        pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n",
                inf->name, fsr, addr);
+       show_pte(current->mm, addr);
 
        info.si_signo = inf->sig;
        info.si_errno = 0;
index 004e35cdcfffea6fa4add161e7e4da0a17bf6a44..cf30daff8932504f95422c2aa3b5882b154713b5 100644 (file)
@@ -49,7 +49,10 @@ static int change_memory_common(unsigned long addr, int numpages,
                WARN_ON_ONCE(1);
        }
 
-       if (!is_module_address(start) || !is_module_address(end - 1))
+       if (start < MODULES_VADDR || start >= MODULES_END)
+               return -EINVAL;
+
+       if (end < MODULES_VADDR || start >= MODULES_END)
                return -EINVAL;
 
        data.set_mask = set_mask;
index 94674eb7e7bb3cebaf671ef28ec7de05145bb0c9..54bb4ba974417e269656d50adb524654851fbbd2 100644 (file)
  * 40 bits wide (T0SZ = 24).  Systems with a PARange smaller than 40 bits are
  * not known to exist and will break with this configuration.
  *
+ * VTCR_EL2.PS is extracted from ID_AA64MMFR0_EL1.PARange at boot time
+ * (see hyp-init.S).
+ *
  * Note that when using 4K pages, we concatenate two first level page tables
  * together.
  *
 #ifdef CONFIG_ARM64_64K_PAGES
 /*
  * Stage2 translation configuration:
- * 40bits output (PS = 2)
  * 40bits input  (T0SZ = 24)
  * 64kB pages (TG0 = 1)
  * 2 level page tables (SL = 1)
 #else
 /*
  * Stage2 translation configuration:
- * 40bits output (PS = 2)
  * 40bits input  (T0SZ = 24)
  * 4kB pages (TG0 = 0)
  * 3 level page tables (SL = 1)
index 6458b53731421343e7640a922a202a2b4c9682be..bbfb600fa82295a8a81c85603254946422b70992 100644 (file)
@@ -158,6 +158,8 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 #define PTRS_PER_S2_PGD                (1 << PTRS_PER_S2_PGD_SHIFT)
 #define S2_PGD_ORDER           get_order(PTRS_PER_S2_PGD * sizeof(pgd_t))
 
+#define kvm_pgd_index(addr)    (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
 /*
  * If we are concatenating first level stage-2 page tables, we would have less
  * than or equal to 16 pointers in the fake PGD, because that's what the
@@ -171,43 +173,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 #define KVM_PREALLOC_LEVEL     (0)
 #endif
 
-/**
- * kvm_prealloc_hwpgd - allocate inital table for VTTBR
- * @kvm:       The KVM struct pointer for the VM.
- * @pgd:       The kernel pseudo pgd
- *
- * When the kernel uses more levels of page tables than the guest, we allocate
- * a fake PGD and pre-populate it to point to the next-level page table, which
- * will be the real initial page table pointed to by the VTTBR.
- *
- * When KVM_PREALLOC_LEVEL==2, we allocate a single page for the PMD and
- * the kernel will use folded pud.  When KVM_PREALLOC_LEVEL==1, we
- * allocate 2 consecutive PUD pages.
- */
-static inline int kvm_prealloc_hwpgd(struct kvm *kvm, pgd_t *pgd)
-{
-       unsigned int i;
-       unsigned long hwpgd;
-
-       if (KVM_PREALLOC_LEVEL == 0)
-               return 0;
-
-       hwpgd = __get_free_pages(GFP_KERNEL | __GFP_ZERO, PTRS_PER_S2_PGD_SHIFT);
-       if (!hwpgd)
-               return -ENOMEM;
-
-       for (i = 0; i < PTRS_PER_S2_PGD; i++) {
-               if (KVM_PREALLOC_LEVEL == 1)
-                       pgd_populate(NULL, pgd + i,
-                                    (pud_t *)hwpgd + i * PTRS_PER_PUD);
-               else if (KVM_PREALLOC_LEVEL == 2)
-                       pud_populate(NULL, pud_offset(pgd, 0) + i,
-                                    (pmd_t *)hwpgd + i * PTRS_PER_PMD);
-       }
-
-       return 0;
-}
-
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
        pgd_t *pgd = kvm->arch.pgd;
@@ -224,12 +189,11 @@ static inline void *kvm_get_hwpgd(struct kvm *kvm)
        return pmd_offset(pud, 0);
 }
 
-static inline void kvm_free_hwpgd(struct kvm *kvm)
+static inline unsigned int kvm_get_hwpgd_size(void)
 {
-       if (KVM_PREALLOC_LEVEL > 0) {
-               unsigned long hwpgd = (unsigned long)kvm_get_hwpgd(kvm);
-               free_pages(hwpgd, PTRS_PER_S2_PGD_SHIFT);
-       }
+       if (KVM_PREALLOC_LEVEL > 0)
+               return PTRS_PER_S2_PGD * PAGE_SIZE;
+       return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
 static inline bool kvm_page_empty(void *ptr)
index 9a8fd84f8fb2b67fe4bc2d845e7f6b584cbf0799..941c375616e2072d3b9fbf6442426c3491f00c01 100644 (file)
@@ -39,7 +39,11 @@ extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr);
 
 #include <asm/memory.h>
 
-#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
+#define cpu_switch_mm(pgd,mm)                          \
+do {                                                   \
+       BUG_ON(pgd == swapper_pg_dir);                  \
+       cpu_do_switch_mm(virt_to_phys(pgd),mm);         \
+} while (0)
 
 #define cpu_get_pgd()                                  \
 ({                                                     \
index 2b8d70164428010911cff2b66791c5d6c4b1dad4..ab21e0d58278825e5dfc0199cd18b853f07232c1 100644 (file)
@@ -337,7 +337,11 @@ core_initcall(arm64_dmi_init);
 
 static void efi_set_pgd(struct mm_struct *mm)
 {
-       cpu_switch_mm(mm->pgd, mm);
+       if (mm == &init_mm)
+               cpu_set_reserved_ttbr0();
+       else
+               cpu_switch_mm(mm->pgd, mm);
+
        flush_tlb_all();
        if (icache_is_aivivt())
                __flush_icache_all();
index 58e0c2bdde04221cfd66e6c0ba5f6cb47051f544..ef7d112f5ce0df9ca1c1a793301c2c1b3874e23f 100644 (file)
@@ -51,7 +51,7 @@ static int __init early_coherent_pool(char *p)
 }
 early_param("coherent_pool", early_coherent_pool);
 
-static void *__alloc_from_pool(size_t size, struct page **ret_page)
+static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
 {
        unsigned long val;
        void *ptr = NULL;
@@ -67,6 +67,8 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
 
                *ret_page = phys_to_page(phys);
                ptr = (void *)val;
+               if (flags & __GFP_ZERO)
+                       memset(ptr, 0, size);
        }
 
        return ptr;
@@ -101,6 +103,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
                flags |= GFP_DMA;
        if (IS_ENABLED(CONFIG_DMA_CMA) && (flags & __GFP_WAIT)) {
                struct page *page;
+               void *addr;
 
                size = PAGE_ALIGN(size);
                page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
@@ -109,7 +112,10 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
                        return NULL;
 
                *dma_handle = phys_to_dma(dev, page_to_phys(page));
-               return page_address(page);
+               addr = page_address(page);
+               if (flags & __GFP_ZERO)
+                       memset(addr, 0, size);
+               return addr;
        } else {
                return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
        }
@@ -146,7 +152,7 @@ static void *__dma_alloc(struct device *dev, size_t size,
 
        if (!coherent && !(flags & __GFP_WAIT)) {
                struct page *page = NULL;
-               void *addr = __alloc_from_pool(size, &page);
+               void *addr = __alloc_from_pool(size, &page, flags);
 
                if (addr)
                        *dma_handle = phys_to_dma(dev, page_to_phys(page));
index 376131194cc35d75933dd929c7beb6bc1ad87b8a..e0bb972a50d7425b3f422605ab64bbc82c428cc0 100644 (file)
@@ -1,6 +1,5 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 header-y += elf.h
-header-y += ucontext.h
 
 generic-y += ucontext.h
index 0d231adfe576b897073c924e02211dea7b110285..0c9b6afe69e9094815cc1e73084422368b3a2e52 100644 (file)
@@ -126,7 +126,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
                break;
        }
 
-survive:
        /*
         * If for any reason at all we couldn't handle the fault,
         * make sure we exit gracefully rather than endlessly redo
@@ -220,11 +219,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (is_global_init(tsk)) {
-               yield();
-               down_read(&mm->mmap_sem);
-               goto survive;
-       }
        if (!user_mode(regs))
                goto no_context;
        pagefault_out_of_memory();
index f6579cfde2dfb3ae17b0b9968d209c6d6b0cabd8..19e17bd7aec09b2662874a3925e3d55f4e4207f4 100644 (file)
@@ -165,7 +165,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_ONE_REG:
        case KVM_CAP_ENABLE_CAP:
        case KVM_CAP_S390_CSS_SUPPORT:
-       case KVM_CAP_IRQFD:
        case KVM_CAP_IOEVENTFD:
        case KVM_CAP_DEVICE_CTRL:
        case KVM_CAP_ENABLE_CAP_VM:
index 96ac69c5eba016a7b5c1ef93fd35baccf8e2f52b..efb00ec758058afebb97f912e2bc6f142bbd43ff 100644 (file)
@@ -86,6 +86,9 @@ config ARCH_DEFCONFIG
        default "arch/sparc/configs/sparc32_defconfig" if SPARC32
        default "arch/sparc/configs/sparc64_defconfig" if SPARC64
 
+config ARCH_PROC_KCORE_TEXT
+       def_bool y
+
 config IOMMU_HELPER
        bool
        default y if SPARC64
index 4f6725ff4c336878fd3600f840f81897fdc65099..f5b6537306f0b3259e2313f3ec03b3ed32215c49 100644 (file)
@@ -2957,6 +2957,17 @@ unsigned long sun4v_t5_set_perfreg(unsigned long reg_num,
                                   unsigned long reg_val);
 #endif
 
+
+#define HV_FAST_M7_GET_PERFREG 0x43
+#define HV_FAST_M7_SET_PERFREG 0x44
+
+#ifndef        __ASSEMBLY__
+unsigned long sun4v_m7_get_perfreg(unsigned long reg_num,
+                                     unsigned long *reg_val);
+unsigned long sun4v_m7_set_perfreg(unsigned long reg_num,
+                                     unsigned long reg_val);
+#endif
+
 /* Function numbers for HV_CORE_TRAP.  */
 #define HV_CORE_SET_VER                        0x00
 #define HV_CORE_PUTCHAR                        0x01
@@ -2981,6 +2992,7 @@ unsigned long sun4v_t5_set_perfreg(unsigned long reg_num,
 #define HV_GRP_SDIO                    0x0108
 #define HV_GRP_SDIO_ERR                        0x0109
 #define HV_GRP_REBOOT_DATA             0x0110
+#define HV_GRP_M7_PERF                 0x0114
 #define HV_GRP_NIAG_PERF               0x0200
 #define HV_GRP_FIRE_PERF               0x0201
 #define HV_GRP_N2_CPU                  0x0202
index 9b672be70dda6e84802853b0cd6acf7d5aa13e08..50d4840d9aebbfa036c7a110e9f866fa77007647 100644 (file)
@@ -407,16 +407,16 @@ static inline void iounmap(volatile void __iomem *addr)
 {
 }
 
-#define ioread8(X)                     readb(X)
-#define ioread16(X)                    readw(X)
-#define ioread16be(X)                  __raw_readw(X)
-#define ioread32(X)                    readl(X)
-#define ioread32be(X)                  __raw_readl(X)
-#define iowrite8(val,X)                        writeb(val,X)
-#define iowrite16(val,X)               writew(val,X)
-#define iowrite16be(val,X)             __raw_writew(val,X)
-#define iowrite32(val,X)               writel(val,X)
-#define iowrite32be(val,X)             __raw_writel(val,X)
+#define ioread8                        readb
+#define ioread16               readw
+#define ioread16be             __raw_readw
+#define ioread32               readl
+#define ioread32be             __raw_readl
+#define iowrite8               writeb
+#define iowrite16              writew
+#define iowrite16be            __raw_writew
+#define iowrite32              writel
+#define iowrite32be            __raw_writel
 
 /* Create a virtual mapping cookie for an IO port range */
 void __iomem *ioport_map(unsigned long port, unsigned int nr);
index c100dc27a0a9461e677e805224c586eb37082793..176fa0ad19f15d2d41a7234378cc36db144abd57 100644 (file)
@@ -12,7 +12,6 @@
 extern int this_is_starfire;
 
 void check_if_starfire(void);
-int starfire_hard_smp_processor_id(void);
 void starfire_hookup(int);
 unsigned int starfire_translate(unsigned long imap, unsigned int upaid);
 
index 88d322b67fac4d4be308280dd59bd52f2ecf92c0..07cc49e541f40ea2cacc1f952aa7e07dd4a4e69b 100644 (file)
@@ -98,11 +98,7 @@ void sun4v_do_mna(struct pt_regs *regs,
 void do_privop(struct pt_regs *regs);
 void do_privact(struct pt_regs *regs);
 void do_cee(struct pt_regs *regs);
-void do_cee_tl1(struct pt_regs *regs);
-void do_dae_tl1(struct pt_regs *regs);
-void do_iae_tl1(struct pt_regs *regs);
 void do_div0_tl1(struct pt_regs *regs);
-void do_fpdis_tl1(struct pt_regs *regs);
 void do_fpieee_tl1(struct pt_regs *regs);
 void do_fpother_tl1(struct pt_regs *regs);
 void do_ill_tl1(struct pt_regs *regs);
index 5c55145bfbf02d616ec606feb94539e26cbe1831..662500fa555f74160f6449143e6d0785af2643e9 100644 (file)
@@ -48,6 +48,7 @@ static struct api_info api_table[] = {
        { .group = HV_GRP_VT_CPU,                               },
        { .group = HV_GRP_T5_CPU,                               },
        { .group = HV_GRP_DIAG,         .flags = FLAG_PRE_API   },
+       { .group = HV_GRP_M7_PERF,                              },
 };
 
 static DEFINE_SPINLOCK(hvapi_lock);
index caedf8320416e1fe8bfc4cb76369ce1efd8ce729..afbaba52d2f16cb30daf092f5cd3986e7ca9c299 100644 (file)
@@ -837,3 +837,19 @@ ENTRY(sun4v_t5_set_perfreg)
        retl
         nop
 ENDPROC(sun4v_t5_set_perfreg)
+
+ENTRY(sun4v_m7_get_perfreg)
+       mov     %o1, %o4
+       mov     HV_FAST_M7_GET_PERFREG, %o5
+       ta      HV_FAST_TRAP
+       stx     %o1, [%o4]
+       retl
+       nop
+ENDPROC(sun4v_m7_get_perfreg)
+
+ENTRY(sun4v_m7_set_perfreg)
+       mov     HV_FAST_M7_SET_PERFREG, %o5
+       ta      HV_FAST_TRAP
+       retl
+       nop
+ENDPROC(sun4v_m7_set_perfreg)
index 7e967c8018c8cf19ba1886b39b087d9eb0638b0c..eb978c77c76a78d401e5dce22b4f5bafa8ef948d 100644 (file)
@@ -217,6 +217,31 @@ static const struct pcr_ops n5_pcr_ops = {
        .pcr_nmi_disable        = PCR_N4_PICNPT,
 };
 
+static u64 m7_pcr_read(unsigned long reg_num)
+{
+       unsigned long val;
+
+       (void) sun4v_m7_get_perfreg(reg_num, &val);
+
+       return val;
+}
+
+static void m7_pcr_write(unsigned long reg_num, u64 val)
+{
+       (void) sun4v_m7_set_perfreg(reg_num, val);
+}
+
+static const struct pcr_ops m7_pcr_ops = {
+       .read_pcr               = m7_pcr_read,
+       .write_pcr              = m7_pcr_write,
+       .read_pic               = n4_pic_read,
+       .write_pic              = n4_pic_write,
+       .nmi_picl_value         = n4_picl_value,
+       .pcr_nmi_enable         = (PCR_N4_PICNPT | PCR_N4_STRACE |
+                                  PCR_N4_UTRACE | PCR_N4_TOE |
+                                  (26 << PCR_N4_SL_SHIFT)),
+       .pcr_nmi_disable        = PCR_N4_PICNPT,
+};
 
 static unsigned long perf_hsvc_group;
 static unsigned long perf_hsvc_major;
@@ -248,6 +273,10 @@ static int __init register_perf_hsvc(void)
                        perf_hsvc_group = HV_GRP_T5_CPU;
                        break;
 
+               case SUN4V_CHIP_SPARC_M7:
+                       perf_hsvc_group = HV_GRP_M7_PERF;
+                       break;
+
                default:
                        return -ENODEV;
                }
@@ -293,6 +322,10 @@ static int __init setup_sun4v_pcr_ops(void)
                pcr_ops = &n5_pcr_ops;
                break;
 
+       case SUN4V_CHIP_SPARC_M7:
+               pcr_ops = &m7_pcr_ops;
+               break;
+
        default:
                ret = -ENODEV;
                break;
index 46a5e4508752814cb0ec21b820673cd445b19ada..86eebfa3b15873dfd60117389e9c80f0018a13e0 100644 (file)
@@ -792,6 +792,42 @@ static const struct sparc_pmu niagara4_pmu = {
        .num_pic_regs   = 4,
 };
 
+static void sparc_m7_write_pmc(int idx, u64 val)
+{
+       u64 pcr;
+
+       pcr = pcr_ops->read_pcr(idx);
+       /* ensure ov and ntc are reset */
+       pcr &= ~(PCR_N4_OV | PCR_N4_NTC);
+
+       pcr_ops->write_pic(idx, val & 0xffffffff);
+
+       pcr_ops->write_pcr(idx, pcr);
+}
+
+static const struct sparc_pmu sparc_m7_pmu = {
+       .event_map      = niagara4_event_map,
+       .cache_map      = &niagara4_cache_map,
+       .max_events     = ARRAY_SIZE(niagara4_perfmon_event_map),
+       .read_pmc       = sparc_vt_read_pmc,
+       .write_pmc      = sparc_m7_write_pmc,
+       .upper_shift    = 5,
+       .lower_shift    = 5,
+       .event_mask     = 0x7ff,
+       .user_bit       = PCR_N4_UTRACE,
+       .priv_bit       = PCR_N4_STRACE,
+
+       /* We explicitly don't support hypervisor tracing. */
+       .hv_bit         = 0,
+
+       .irq_bit        = PCR_N4_TOE,
+       .upper_nop      = 0,
+       .lower_nop      = 0,
+       .flags          = 0,
+       .max_hw_events  = 4,
+       .num_pcrs       = 4,
+       .num_pic_regs   = 4,
+};
 static const struct sparc_pmu *sparc_pmu __read_mostly;
 
 static u64 event_encoding(u64 event_id, int idx)
@@ -960,6 +996,8 @@ static void calculate_single_pcr(struct cpu_hw_events *cpuc)
        cpuc->pcr[0] |= cpuc->event[0]->hw.config_base;
 }
 
+static void sparc_pmu_start(struct perf_event *event, int flags);
+
 /* On this PMU each PIC has it's own PCR control register.  */
 static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
 {
@@ -972,20 +1010,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
                struct perf_event *cp = cpuc->event[i];
                struct hw_perf_event *hwc = &cp->hw;
                int idx = hwc->idx;
-               u64 enc;
 
                if (cpuc->current_idx[i] != PIC_NO_INDEX)
                        continue;
 
-               sparc_perf_event_set_period(cp, hwc, idx);
                cpuc->current_idx[i] = idx;
 
-               enc = perf_event_get_enc(cpuc->events[i]);
-               cpuc->pcr[idx] &= ~mask_for_index(idx);
-               if (hwc->state & PERF_HES_STOPPED)
-                       cpuc->pcr[idx] |= nop_for_index(idx);
-               else
-                       cpuc->pcr[idx] |= event_encoding(enc, idx);
+               sparc_pmu_start(cp, PERF_EF_RELOAD);
        }
 out:
        for (i = 0; i < cpuc->n_events; i++) {
@@ -1101,7 +1132,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
        int i;
 
        local_irq_save(flags);
-       perf_pmu_disable(event->pmu);
 
        for (i = 0; i < cpuc->n_events; i++) {
                if (event == cpuc->event[i]) {
@@ -1127,7 +1157,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
                }
        }
 
-       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
@@ -1361,7 +1390,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
        unsigned long flags;
 
        local_irq_save(flags);
-       perf_pmu_disable(event->pmu);
 
        n0 = cpuc->n_events;
        if (n0 >= sparc_pmu->max_hw_events)
@@ -1394,7 +1422,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
 
        ret = 0;
 out:
-       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
        return ret;
 }
@@ -1667,6 +1694,10 @@ static bool __init supported_pmu(void)
                sparc_pmu = &niagara4_pmu;
                return true;
        }
+       if (!strcmp(sparc_pmu_type, "sparc-m7")) {
+               sparc_pmu = &sparc_m7_pmu;
+               return true;
+       }
        return false;
 }
 
index 0be7bf978cb1da03b8d657958ec6d0ec3c4e7d8b..46a59643bb1cee71edbd3d91d3f8f2eb09b3a26a 100644 (file)
@@ -287,6 +287,8 @@ void arch_trigger_all_cpu_backtrace(bool include_self)
                        printk("             TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
                               gp->tpc, gp->o7, gp->i7, gp->rpc);
                }
+
+               touch_nmi_watchdog();
        }
 
        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
@@ -362,6 +364,8 @@ static void pmu_snapshot_all_cpus(void)
                       (cpu == this_cpu ? '*' : ' '), cpu,
                       pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
                       pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
+
+               touch_nmi_watchdog();
        }
 
        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
index da6f1a7fc4db4713425d1927af185cb797b4c1fc..61139d9924cae4a8fdf5d4d5366a31052ea29616 100644 (file)
@@ -1406,11 +1406,32 @@ void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
        scheduler_ipi();
 }
 
-/* This is a nop because we capture all other cpus
- * anyways when making the PROM active.
- */
+static void stop_this_cpu(void *dummy)
+{
+       prom_stopself();
+}
+
 void smp_send_stop(void)
 {
+       int cpu;
+
+       if (tlb_type == hypervisor) {
+               for_each_online_cpu(cpu) {
+                       if (cpu == smp_processor_id())
+                               continue;
+#ifdef CONFIG_SUN_LDOMS
+                       if (ldom_domaining_enabled) {
+                               unsigned long hv_err;
+                               hv_err = sun4v_cpu_stop(cpu);
+                               if (hv_err)
+                                       printk(KERN_ERR "sun4v_cpu_stop() "
+                                              "failed err=%lu\n", hv_err);
+                       } else
+#endif
+                               prom_stopcpu_cpuid(cpu);
+               }
+       } else
+               smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 /**
index 82281a566bb86b866525a18b8fc4ca453d2e1e60..167fdfd9c83702bd2ccdc737625fcc8f57c9619c 100644 (file)
@@ -28,11 +28,6 @@ void check_if_starfire(void)
                this_is_starfire = 1;
 }
 
-int starfire_hard_smp_processor_id(void)
-{
-       return upa_readl(0x1fff40000d0UL);
-}
-
 /*
  * Each Starfire board has 32 registers which perform translation
  * and delivery of traditional interrupt packets into the extended
index c85403d0496c24f7639a32fa06b7dc53c1559381..30e7ddb27a3a966e74e5ab79ad686bab26eab459 100644 (file)
@@ -333,7 +333,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
        long err;
 
        /* No need for backward compatibility. We can start fresh... */
-       if (call <= SEMCTL) {
+       if (call <= SEMTIMEDOP) {
                switch (call) {
                case SEMOP:
                        err = sys_semtimedop(first, ptr,
index a27651e866e7a108dca92cf88c14ec8f21ae5b5b..0e699745d64311d44439327d3e971ce78114b7da 100644 (file)
@@ -2427,6 +2427,8 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
                }
                user_instruction_dump ((unsigned int __user *) regs->tpc);
        }
+       if (panic_on_oops)
+               panic("Fatal exception");
        if (regs->tstate & TSTATE_PRIV)
                do_exit(SIGKILL);
        do_exit(SIGSEGV);
@@ -2564,27 +2566,6 @@ void do_cee(struct pt_regs *regs)
        die_if_kernel("TL0: Cache Error Exception", regs);
 }
 
-void do_cee_tl1(struct pt_regs *regs)
-{
-       exception_enter();
-       dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
-       die_if_kernel("TL1: Cache Error Exception", regs);
-}
-
-void do_dae_tl1(struct pt_regs *regs)
-{
-       exception_enter();
-       dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
-       die_if_kernel("TL1: Data Access Exception", regs);
-}
-
-void do_iae_tl1(struct pt_regs *regs)
-{
-       exception_enter();
-       dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
-       die_if_kernel("TL1: Instruction Access Exception", regs);
-}
-
 void do_div0_tl1(struct pt_regs *regs)
 {
        exception_enter();
@@ -2592,13 +2573,6 @@ void do_div0_tl1(struct pt_regs *regs)
        die_if_kernel("TL1: DIV0 Exception", regs);
 }
 
-void do_fpdis_tl1(struct pt_regs *regs)
-{
-       exception_enter();
-       dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
-       die_if_kernel("TL1: FPU Disabled", regs);
-}
-
 void do_fpieee_tl1(struct pt_regs *regs)
 {
        exception_enter();
index b7f6334e159f9d22fc34ccc2f003511009ca9b61..857ad4f8905f942f44ac40770c9277323e4e3c09 100644 (file)
@@ -8,9 +8,11 @@
 
        .text
 ENTRY(memmove) /* o0=dst o1=src o2=len */
-       mov             %o0, %g1
+       brz,pn          %o2, 99f
+        mov            %o0, %g1
+
        cmp             %o0, %o1
-       bleu,pt         %xcc, memcpy
+       bleu,pt         %xcc, 2f
         add            %o1, %o2, %g7
        cmp             %g7, %o0
        bleu,pt         %xcc, memcpy
@@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */
        stb             %g7, [%o0]
        bne,pt          %icc, 1b
         sub            %o0, 1, %o0
-
+99:
        retl
         mov            %g1, %o0
+
+       /* We can't just call memcpy for these memmove cases.  On some
+        * chips the memcpy uses cache initializing stores and when dst
+        * and src are close enough, those can clobber the source data
+        * before we've loaded it in.
+        */
+2:     or              %o0, %o1, %g7
+       or              %o2, %g7, %g7
+       andcc           %g7, 0x7, %g0
+       bne,pn          %xcc, 4f
+        nop
+
+3:     ldx             [%o1], %g7
+       add             %o1, 8, %o1
+       subcc           %o2, 8, %o2
+       add             %o0, 8, %o0
+       bne,pt          %icc, 3b
+        stx            %g7, [%o0 - 0x8]
+       ba,a,pt         %xcc, 99b
+
+4:     ldub            [%o1], %g7
+       add             %o1, 1, %o1
+       subcc           %o2, 1, %o2
+       add             %o0, 1, %o0
+       bne,pt          %icc, 4b
+        stb            %g7, [%o0 - 0x1]
+       ba,a,pt         %xcc, 99b
 ENDPROC(memmove)
index 3ea267c53320d49683ab39c9e0d95189e4adb56e..4ca0d6ba5ec8331c67f43f8515eb3737526208bb 100644 (file)
@@ -2820,7 +2820,7 @@ static int __init report_memory(void)
 
        return 0;
 }
-device_initcall(report_memory);
+arch_initcall(report_memory);
 
 #ifdef CONFIG_SMP
 #define do_flush_tlb_kernel_range      smp_flush_tlb_kernel_range
index 7083c16cccba0b2b144ea5e03e160ebafe81e855..bb1376381985edb9f96e49c0a1b0269e56bd0f9e 100644 (file)
 static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
                LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
 
-struct kaslr_setup_data {
-       __u64 next;
-       __u32 type;
-       __u32 len;
-       __u8 data[1];
-} kaslr_setup_data;
-
 #define I8254_PORT_CONTROL     0x43
 #define I8254_PORT_COUNTER0    0x40
 #define I8254_CMD_READBACK     0xC0
@@ -302,29 +295,7 @@ static unsigned long find_random_addr(unsigned long minimum,
        return slots_fetch_random();
 }
 
-static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled)
-{
-       struct setup_data *data;
-
-       kaslr_setup_data.type = SETUP_KASLR;
-       kaslr_setup_data.len = 1;
-       kaslr_setup_data.next = 0;
-       kaslr_setup_data.data[0] = enabled;
-
-       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
-
-       while (data && data->next)
-               data = (struct setup_data *)(unsigned long)data->next;
-
-       if (data)
-               data->next = (unsigned long)&kaslr_setup_data;
-       else
-               params->hdr.setup_data = (unsigned long)&kaslr_setup_data;
-
-}
-
-unsigned char *choose_kernel_location(struct boot_params *params,
-                                     unsigned char *input,
+unsigned char *choose_kernel_location(unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size)
@@ -335,17 +306,14 @@ unsigned char *choose_kernel_location(struct boot_params *params,
 #ifdef CONFIG_HIBERNATION
        if (!cmdline_find_option_bool("kaslr")) {
                debug_putstr("KASLR disabled by default...\n");
-               add_kaslr_setup_data(params, 0);
                goto out;
        }
 #else
        if (cmdline_find_option_bool("nokaslr")) {
                debug_putstr("KASLR disabled by cmdline...\n");
-               add_kaslr_setup_data(params, 0);
                goto out;
        }
 #endif
-       add_kaslr_setup_data(params, 1);
 
        /* Record the various known unsafe memory ranges. */
        mem_avoid_init((unsigned long)input, input_size,
index 5903089c818f6843b9d1cc7c83507cf0d28a3e26..a950864a64dab3d558197c77bef3c56a07961494 100644 (file)
@@ -401,8 +401,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
         * the entire decompressed kernel plus relocation table, or the
         * entire decompressed kernel plus .bss and .brk sections.
         */
-       output = choose_kernel_location(real_mode, input_data, input_len,
-                                       output,
+       output = choose_kernel_location(input_data, input_len, output,
                                        output_len > run_size ? output_len
                                                              : run_size);
 
index ee3576b2666b8139eedf25077ce769da10712c11..04477d68403f1fe6197d82276033ce27338c1bac 100644 (file)
@@ -57,8 +57,7 @@ int cmdline_find_option_bool(const char *option);
 
 #if CONFIG_RANDOMIZE_BASE
 /* aslr.c */
-unsigned char *choose_kernel_location(struct boot_params *params,
-                                     unsigned char *input,
+unsigned char *choose_kernel_location(unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size);
@@ -66,8 +65,7 @@ unsigned char *choose_kernel_location(struct boot_params *params,
 bool has_cpuflag(int flag);
 #else
 static inline
-unsigned char *choose_kernel_location(struct boot_params *params,
-                                     unsigned char *input,
+unsigned char *choose_kernel_location(unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size)
index 947c6bf52c330452cfb7ac4a19d368f68f4e4509..54f60ab41c63025fd2cb42e5579df7f69c3d9b60 100644 (file)
@@ -1155,7 +1155,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
                src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC);
                if (!src)
                        return -ENOMEM;
-               assoc = (src + req->cryptlen + auth_tag_len);
+               assoc = (src + req->cryptlen);
                scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0);
                scatterwalk_map_and_copy(assoc, req->assoc, 0,
                        req->assoclen, 0);
@@ -1180,7 +1180,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
                scatterwalk_done(&src_sg_walk, 0, 0);
                scatterwalk_done(&assoc_sg_walk, 0, 0);
        } else {
-               scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1);
+               scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1);
                kfree(src);
        }
        return retval;
index 0dbc08282291044216456e6c14a802d56a0e40d8..72ba21a8b5fc2ff8b76c6c3e53b331ca6a558339 100644 (file)
@@ -370,7 +370,7 @@ static inline void drop_fpu(struct task_struct *tsk)
        preempt_disable();
        tsk->thread.fpu_counter = 0;
        __drop_fpu(tsk);
-       clear_used_math();
+       clear_stopped_child_used_math(tsk);
        preempt_enable();
 }
 
index 95e11f79f123c6aadd5ed8888a51e1870405deeb..f97fbe3abb67f5059d4e6f0a37261d6113df19de 100644 (file)
@@ -51,8 +51,6 @@ extern int devmem_is_allowed(unsigned long pagenr);
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
-extern bool kaslr_enabled;
-
 static inline phys_addr_t get_max_mapped(void)
 {
        return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
index fa1195dae42541aaa1d836782a3a65aa25640e74..164e3f8d3c3dbb6eb4fc0ea60e01cae15fe5116e 100644 (file)
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
+extern bool mp_should_keep_irq(struct device *dev);
+
 struct pci_raw_ops {
        int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
                                                int reg, int len, u32 *val);
index 44e6dd7e36a23becd48def85b218b1d70ac938e6..225b0988043a0a78ac9092a9af7a265122c685cd 100644 (file)
@@ -7,7 +7,6 @@
 #define SETUP_DTB                      2
 #define SETUP_PCI                      3
 #define SETUP_EFI                      4
-#define SETUP_KASLR                    5
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK       0x07FF
index 3d525c6124f6c720e02d2761b283151be97cf6d7..803b684676ff3d0bcc6a17c530a457efcf485fca 100644 (file)
@@ -1337,6 +1337,26 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
        return 0;
 }
 
+/*
+ * ACPI offers an alternative platform interface model that removes
+ * ACPI hardware requirements for platforms that do not implement
+ * the PC Architecture.
+ *
+ * We initialize the Hardware-reduced ACPI model here:
+ */
+static void __init acpi_reduced_hw_init(void)
+{
+       if (acpi_gbl_reduced_hardware) {
+               /*
+                * Override x86_init functions and bypass legacy pic
+                * in Hardware-reduced ACPI mode
+                */
+               x86_init.timers.timer_init      = x86_init_noop;
+               x86_init.irqs.pre_vector_init   = x86_init_noop;
+               legacy_pic                      = &null_legacy_pic;
+       }
+}
+
 /*
  * If your system is blacklisted here, but you find that acpi=force
  * works for you, please contact linux-acpi@vger.kernel.org
@@ -1536,6 +1556,11 @@ int __init early_acpi_boot_init(void)
         */
        early_acpi_process_madt();
 
+       /*
+        * Hardware-reduced ACPI mode initialization:
+        */
+       acpi_reduced_hw_init();
+
        return 0;
 }
 
index c2fd21fed00284066ab138354a4daefbc1b775ac..017149cded0760ccc842db2a50d3c2013321aa52 100644 (file)
@@ -37,10 +37,12 @@ static const struct apic apic_numachip;
 static unsigned int get_apic_id(unsigned long x)
 {
        unsigned long value;
-       unsigned int id;
+       unsigned int id = (x >> 24) & 0xff;
 
-       rdmsrl(MSR_FAM10H_NODE_ID, value);
-       id = ((x >> 24) & 0xffU) | ((value << 2) & 0xff00U);
+       if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) {
+               rdmsrl(MSR_FAM10H_NODE_ID, value);
+               id |= (value << 2) & 0xff00;
+       }
 
        return id;
 }
@@ -155,10 +157,18 @@ static int __init numachip_probe(void)
 
 static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
 {
-       if (c->phys_proc_id != node) {
-               c->phys_proc_id = node;
-               per_cpu(cpu_llc_id, smp_processor_id()) = node;
+       u64 val;
+       u32 nodes = 1;
+
+       this_cpu_write(cpu_llc_id, node);
+
+       /* Account for nodes per socket in multi-core-module processors */
+       if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) {
+               rdmsrl(MSR_FAM10H_NODE_ID, val);
+               nodes = ((val >> 3) & 7) + 1;
        }
+
+       c->phys_proc_id = node / nodes;
 }
 
 static int __init numachip_system_init(void)
index 9bbb9b35c144a4f721ed4e7dcfc07aee6abdc2cb..d1ac80b72c72184a0b999c2b299b5e265d26de7a 100644 (file)
@@ -47,13 +47,21 @@ do {                                                        \
 
 #ifdef CONFIG_RANDOMIZE_BASE
 static unsigned long module_load_offset;
+static int randomize_modules = 1;
 
 /* Mutex protects the module_load_offset. */
 static DEFINE_MUTEX(module_kaslr_mutex);
 
+static int __init parse_nokaslr(char *p)
+{
+       randomize_modules = 0;
+       return 0;
+}
+early_param("nokaslr", parse_nokaslr);
+
 static unsigned long int get_module_load_offset(void)
 {
-       if (kaslr_enabled) {
+       if (randomize_modules) {
                mutex_lock(&module_kaslr_mutex);
                /*
                 * Calculate the module_load_offset the first time this
index 98dc9317286e1e0fad25f3d10efaa3134a9134c0..0a2421cca01fad095bbb7caa8e7c779d910d751b 100644 (file)
 unsigned long max_low_pfn_mapped;
 unsigned long max_pfn_mapped;
 
-bool __read_mostly kaslr_enabled = false;
-
 #ifdef CONFIG_DMI
 RESERVE_BRK(dmi_alloc, 65536);
 #endif
@@ -427,11 +425,6 @@ static void __init reserve_initrd(void)
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
-static void __init parse_kaslr_setup(u64 pa_data, u32 data_len)
-{
-       kaslr_enabled = (bool)(pa_data + sizeof(struct setup_data));
-}
-
 static void __init parse_setup_data(void)
 {
        struct setup_data *data;
@@ -457,9 +450,6 @@ static void __init parse_setup_data(void)
                case SETUP_EFI:
                        parse_efi_setup(pa_data, data_len);
                        break;
-               case SETUP_KASLR:
-                       parse_kaslr_setup(pa_data, data_len);
-                       break;
                default:
                        break;
                }
@@ -842,14 +832,10 @@ static void __init trim_low_memory_range(void)
 static int
 dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
 {
-       if (kaslr_enabled)
-               pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
-                        (unsigned long)&_text - __START_KERNEL,
-                        __START_KERNEL,
-                        __START_KERNEL_map,
-                        MODULES_VADDR-1);
-       else
-               pr_emerg("Kernel Offset: disabled\n");
+       pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
+                "(relocation range: 0x%lx-0x%lx)\n",
+                (unsigned long)&_text - __START_KERNEL, __START_KERNEL,
+                __START_KERNEL_map, MODULES_VADDR-1);
 
        return 0;
 }
index 9d2073e2ecc92f5c97d51178236d8b2bc63ac029..4ff5d162ff9fd55381259ff8dd96f84064ecea72 100644 (file)
@@ -384,7 +384,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
                goto exit;
        conditional_sti(regs);
 
-       if (!user_mode(regs))
+       if (!user_mode_vm(regs))
                die("bounds", regs, error_code);
 
        if (!cpu_feature_enabled(X86_FEATURE_MPX)) {
@@ -637,7 +637,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
         * then it's very likely the result of an icebp/int01 trap.
         * User wants a sigtrap for that.
         */
-       if (!dr6 && user_mode(regs))
+       if (!dr6 && user_mode_vm(regs))
                user_icebp = 1;
 
        /* Catch kmemcheck conditions first of all! */
index 34f66e58a896693d392e4ed074b1f9ca664974d3..cdc6cf90307800abb83f1b4b516ba389212c3dd0 100644 (file)
@@ -379,7 +379,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                 * thread's fpu state, reconstruct fxstate from the fsave
                 * header. Sanitize the copied state etc.
                 */
-               struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+               struct fpu *fpu = &tsk->thread.fpu;
                struct user_i387_ia32_struct env;
                int err = 0;
 
@@ -393,14 +393,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                 */
                drop_fpu(tsk);
 
-               if (__copy_from_user(xsave, buf_fx, state_size) ||
+               if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) ||
                    __copy_from_user(&env, buf, sizeof(env))) {
+                       fpu_finit(fpu);
                        err = -1;
                } else {
                        sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only);
-                       set_used_math();
                }
 
+               set_used_math();
                if (use_eager_fpu()) {
                        preempt_disable();
                        math_state_restore();
index cc31f7c06d3ddc8ab4ef61c775510e2dcbfde518..9541ba34126b90123ddfe383453145ddfcf789c4 100644 (file)
@@ -507,6 +507,7 @@ static int picdev_read(struct kvm_pic *s,
                return -EOPNOTSUPP;
 
        if (len != 1) {
+               memset(val, 0, len);
                pr_pic_unimpl("non byte read\n");
                return 0;
        }
index b1947e0f3e100d7552add9688125d9c86d29a8ab..46d4449772bc714daa658ea6424fb45659095c70 100644 (file)
@@ -422,6 +422,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
                        struct kvm_ioapic *ioapic, int vector, int trigger_mode)
 {
        int i;
+       struct kvm_lapic *apic = vcpu->arch.apic;
 
        for (i = 0; i < IOAPIC_NUM_PINS; i++) {
                union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i];
@@ -443,7 +444,8 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
                kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);
                spin_lock(&ioapic->lock);
 
-               if (trigger_mode != IOAPIC_LEVEL_TRIG)
+               if (trigger_mode != IOAPIC_LEVEL_TRIG ||
+                   kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
                        continue;
 
                ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
index bd4e34de24c7a0860de0adf88d3b85fd94f8ddae..4ee827d7bf36f730c25d358f709aa99cda93260a 100644 (file)
@@ -833,8 +833,7 @@ int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
 
 static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
 {
-       if (!(kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) &&
-           kvm_ioapic_handles_vector(apic->vcpu->kvm, vector)) {
+       if (kvm_ioapic_handles_vector(apic->vcpu->kvm, vector)) {
                int trigger_mode;
                if (apic_test_vector(vector, apic->regs + APIC_TMR))
                        trigger_mode = IOAPIC_LEVEL_TRIG;
index f7b20b417a3a4296b446ee4d35ee5dfcdef86be4..ae4f6d35d19c268315745741150dd6d1a7df5222 100644 (file)
@@ -2168,7 +2168,10 @@ static void vmx_set_msr_bitmap(struct kvm_vcpu *vcpu)
 {
        unsigned long *msr_bitmap;
 
-       if (irqchip_in_kernel(vcpu->kvm) && apic_x2apic_mode(vcpu->arch.apic)) {
+       if (is_guest_mode(vcpu))
+               msr_bitmap = vmx_msr_bitmap_nested;
+       else if (irqchip_in_kernel(vcpu->kvm) &&
+               apic_x2apic_mode(vcpu->arch.apic)) {
                if (is_long_mode(vcpu))
                        msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
                else
@@ -2476,8 +2479,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
        if (enable_ept) {
                /* nested EPT: emulate EPT also to L1 */
                vmx->nested.nested_vmx_secondary_ctls_high |=
-                       SECONDARY_EXEC_ENABLE_EPT |
-                       SECONDARY_EXEC_UNRESTRICTED_GUEST;
+                       SECONDARY_EXEC_ENABLE_EPT;
                vmx->nested.nested_vmx_ept_caps = VMX_EPT_PAGE_WALK_4_BIT |
                         VMX_EPTP_WB_BIT | VMX_EPT_2MB_PAGE_BIT |
                         VMX_EPT_INVEPT_BIT;
@@ -2491,6 +2493,10 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
        } else
                vmx->nested.nested_vmx_ept_caps = 0;
 
+       if (enable_unrestricted_guest)
+               vmx->nested.nested_vmx_secondary_ctls_high |=
+                       SECONDARY_EXEC_UNRESTRICTED_GUEST;
+
        /* miscellaneous data */
        rdmsr(MSR_IA32_VMX_MISC,
                vmx->nested.nested_vmx_misc_low,
@@ -9218,9 +9224,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
        }
 
        if (cpu_has_vmx_msr_bitmap() &&
-           exec_control & CPU_BASED_USE_MSR_BITMAPS &&
-           nested_vmx_merge_msr_bitmap(vcpu, vmcs12)) {
-               vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_nested));
+           exec_control & CPU_BASED_USE_MSR_BITMAPS) {
+               nested_vmx_merge_msr_bitmap(vcpu, vmcs12);
+               /* MSR_BITMAP will be set by following vmx_set_efer. */
        } else
                exec_control &= ~CPU_BASED_USE_MSR_BITMAPS;
 
index bd7a70be41b35fa93ad952060fc2c7f432e5628e..32bf19ef3115f65c9dffc23a655be2763babcaff 100644 (file)
@@ -2744,7 +2744,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_USER_NMI:
        case KVM_CAP_REINJECT_CONTROL:
        case KVM_CAP_IRQ_INJECT_STATUS:
-       case KVM_CAP_IRQFD:
        case KVM_CAP_IOEVENTFD:
        case KVM_CAP_IOEVENTFD_NO_LENGTH:
        case KVM_CAP_PIT2:
index 3d2612b68694efd294ca214d478c7777030f4b03..2fb384724ebb52d1cf0ba6131b418e81609ca55c 100644 (file)
@@ -513,31 +513,6 @@ void __init pcibios_set_cache_line_size(void)
        }
 }
 
-/*
- * Some device drivers assume dev->irq won't change after calling
- * pci_disable_device(). So delay releasing of IRQ resource to driver
- * unbinding time. Otherwise it will break PM subsystem and drivers
- * like xen-pciback etc.
- */
-static int pci_irq_notifier(struct notifier_block *nb, unsigned long action,
-                           void *data)
-{
-       struct pci_dev *dev = to_pci_dev(data);
-
-       if (action != BUS_NOTIFY_UNBOUND_DRIVER)
-               return NOTIFY_DONE;
-
-       if (pcibios_disable_irq)
-               pcibios_disable_irq(dev);
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block pci_irq_nb = {
-       .notifier_call = pci_irq_notifier,
-       .priority = INT_MIN,
-};
-
 int __init pcibios_init(void)
 {
        if (!raw_pci_ops) {
@@ -550,9 +525,6 @@ int __init pcibios_init(void)
 
        if (pci_bf_sort >= pci_force_bf)
                pci_sort_breadthfirst();
-
-       bus_register_notifier(&pci_bus_type, &pci_irq_nb);
-
        return 0;
 }
 
@@ -711,6 +683,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return 0;
 }
 
+void pcibios_disable_device (struct pci_dev *dev)
+{
+       if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+               pcibios_disable_irq(dev);
+}
+
 int pci_ext_cfg_avail(void)
 {
        if (raw_pci_ext_ops)
index efb849323c745899f5e665364ceec36a1d15cb9d..852aa4c92da027cb07fb64c77c855aaf0877a1da 100644 (file)
@@ -234,10 +234,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (dev->irq_managed && dev->irq > 0) {
+       if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+           dev->irq > 0) {
                mp_unmap_irq(dev->irq);
                dev->irq_managed = 0;
-               dev->irq = 0;
        }
 }
 
index e71b3dbd87b8f688d3f2cbfa995421bd516ba581..5dc6ca5e174131d2c7208ea1ed86739ef4532d22 100644 (file)
@@ -1256,9 +1256,22 @@ static int pirq_enable_irq(struct pci_dev *dev)
        return 0;
 }
 
+bool mp_should_keep_irq(struct device *dev)
+{
+       if (dev->power.is_prepared)
+               return true;
+#ifdef CONFIG_PM
+       if (dev->power.runtime_status == RPM_SUSPENDING)
+               return true;
+#endif
+
+       return false;
+}
+
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
+       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
+           dev->irq_managed && dev->irq) {
                mp_unmap_irq(dev->irq);
                dev->irq = 0;
                dev->irq_managed = 0;
index 31776d0efc8c40fa0aa6989731b1ddf23229029c..d7ec4e251c0a2e53572438891508dfeb4a3a016a 100644 (file)
@@ -17,6 +17,7 @@
        .text
        .globl __kernel_sigreturn
        .type __kernel_sigreturn,@function
+       nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */
        ALIGN
 __kernel_sigreturn:
 .LSTART_sigreturn:
index e7f718d6918a6a29b775aa97f7a40dc654d47136..b1def411c0b89cbf7847b767063c5c2ab528e8a8 100644 (file)
@@ -485,6 +485,14 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        if (!pin || !dev->irq_managed || dev->irq <= 0)
                return;
 
+       /* Keep IOAPIC pin configuration when suspending */
+       if (dev->dev.power.is_prepared)
+               return;
+#ifdef CONFIG_PM
+       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
+               return;
+#endif
+
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
                return;
@@ -505,6 +513,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        if (gsi >= 0) {
                acpi_unregister_gsi(gsi);
                dev->irq_managed = 0;
-               dev->irq = 0;
        }
 }
index 4c35f0822d06e54dd5399a285d22cbcfe174b115..ef150ebb4c304efa1cbf5fb6e23a2a9da036ae91 100644 (file)
@@ -4737,7 +4737,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
                return NULL;
 
        /* libsas case */
-       if (!ap->scsi_host) {
+       if (ap->flags & ATA_FLAG_SAS_HOST) {
                tag = ata_sas_allocate_tag(ap);
                if (tag < 0)
                        return NULL;
@@ -4776,7 +4776,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
        tag = qc->tag;
        if (likely(ata_tag_valid(tag))) {
                qc->tag = ATA_TAG_POISON;
-               if (!ap->scsi_host)
+               if (ap->flags & ATA_FLAG_SAS_HOST)
                        ata_sas_free_tag(tag, ap);
        }
 }
index beb8b27d4621a6d9f839065c1296fa8ab67f3032..a13587b5c2be32b912f9fe0fd7544761a280bd57 100644 (file)
@@ -243,4 +243,12 @@ extern struct regcache_ops regcache_rbtree_ops;
 extern struct regcache_ops regcache_lzo_ops;
 extern struct regcache_ops regcache_flat_ops;
 
+static inline const char *regmap_name(const struct regmap *map)
+{
+       if (map->dev)
+               return dev_name(map->dev);
+
+       return map->name;
+}
+
 #endif
index d453a2c98ad0a6529170dc5a8f21bab9204255f7..81751a49d8bf2334612350bba52406b9af352258 100644 (file)
@@ -307,7 +307,7 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
        if (pos == 0) {
                memmove(blk + offset * map->cache_word_size,
                        blk, rbnode->blklen * map->cache_word_size);
-               bitmap_shift_right(present, present, offset, blklen);
+               bitmap_shift_left(present, present, offset, blklen);
        }
 
        /* update the rbnode block, its size and the base register */
index f373c35f9e1db239874589464b6375ebfe5d769a..87db9893b463ba505acc3c28e253b5a08cf20c90 100644 (file)
@@ -218,7 +218,7 @@ int regcache_read(struct regmap *map,
                ret = map->cache_ops->read(map, reg, value);
 
                if (ret == 0)
-                       trace_regmap_reg_read_cache(map->dev, reg, *value);
+                       trace_regmap_reg_read_cache(map, reg, *value);
 
                return ret;
        }
@@ -311,7 +311,7 @@ int regcache_sync(struct regmap *map)
        dev_dbg(map->dev, "Syncing %s cache\n",
                map->cache_ops->name);
        name = map->cache_ops->name;
-       trace_regcache_sync(map->dev, name, "start");
+       trace_regcache_sync(map, name, "start");
 
        if (!map->cache_dirty)
                goto out;
@@ -346,7 +346,7 @@ int regcache_sync(struct regmap *map)
 
        regmap_async_complete(map);
 
-       trace_regcache_sync(map->dev, name, "stop");
+       trace_regcache_sync(map, name, "stop");
 
        return ret;
 }
@@ -381,7 +381,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
        name = map->cache_ops->name;
        dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max);
 
-       trace_regcache_sync(map->dev, name, "start region");
+       trace_regcache_sync(map, name, "start region");
 
        if (!map->cache_dirty)
                goto out;
@@ -401,7 +401,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
 
        regmap_async_complete(map);
 
-       trace_regcache_sync(map->dev, name, "stop region");
+       trace_regcache_sync(map, name, "stop region");
 
        return ret;
 }
@@ -428,7 +428,7 @@ int regcache_drop_region(struct regmap *map, unsigned int min,
 
        map->lock(map->lock_arg);
 
-       trace_regcache_drop_region(map->dev, min, max);
+       trace_regcache_drop_region(map, min, max);
 
        ret = map->cache_ops->drop(map, min, max);
 
@@ -455,7 +455,7 @@ void regcache_cache_only(struct regmap *map, bool enable)
        map->lock(map->lock_arg);
        WARN_ON(map->cache_bypass && enable);
        map->cache_only = enable;
-       trace_regmap_cache_only(map->dev, enable);
+       trace_regmap_cache_only(map, enable);
        map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_cache_only);
@@ -493,7 +493,7 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
        map->lock(map->lock_arg);
        WARN_ON(map->cache_only && enable);
        map->cache_bypass = enable;
-       trace_regmap_cache_bypass(map->dev, enable);
+       trace_regmap_cache_bypass(map, enable);
        map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_cache_bypass);
@@ -608,7 +608,8 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
        for (i = start; i < end; i++) {
                regtmp = block_base + (i * map->reg_stride);
 
-               if (!regcache_reg_present(cache_present, i))
+               if (!regcache_reg_present(cache_present, i) ||
+                   !regmap_writeable(map, regtmp))
                        continue;
 
                val = regcache_get_val(map, block, i);
@@ -677,7 +678,8 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
        for (i = start; i < end; i++) {
                regtmp = block_base + (i * map->reg_stride);
 
-               if (!regcache_reg_present(cache_present, i)) {
+               if (!regcache_reg_present(cache_present, i) ||
+                   !regmap_writeable(map, regtmp)) {
                        ret = regcache_sync_block_raw_flush(map, &data,
                                                            base, regtmp);
                        if (ret != 0)
index 6299a50a59607f6d5598eac804817cef47e8c106..a6c3f75b4b01e1145c6eb5bb9816182a0f9c9fde 100644 (file)
@@ -499,7 +499,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
                goto err_alloc;
        }
 
-       ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags,
+       ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
+                                  irq_flags | IRQF_ONESHOT,
                                   chip->name, d);
        if (ret != 0) {
                dev_err(map->dev, "Failed to request IRQ %d for %s: %d\n",
index f99b098ddabfbd23dae3ab3ee7733b9ff24e28ef..dbfe6a69c3daa67969df7c670f9e5144a053afb6 100644 (file)
@@ -1281,7 +1281,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
        if (map->async && map->bus->async_write) {
                struct regmap_async *async;
 
-               trace_regmap_async_write_start(map->dev, reg, val_len);
+               trace_regmap_async_write_start(map, reg, val_len);
 
                spin_lock_irqsave(&map->async_lock, flags);
                async = list_first_entry_or_null(&map->async_free,
@@ -1339,8 +1339,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
                return ret;
        }
 
-       trace_regmap_hw_write_start(map->dev, reg,
-                                   val_len / map->format.val_bytes);
+       trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes);
 
        /* If we're doing a single register write we can probably just
         * send the work_buf directly, otherwise try to do a gather
@@ -1372,8 +1371,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
                kfree(buf);
        }
 
-       trace_regmap_hw_write_done(map->dev, reg,
-                                  val_len / map->format.val_bytes);
+       trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes);
 
        return ret;
 }
@@ -1407,12 +1405,12 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
 
        map->format.format_write(map, reg, val);
 
-       trace_regmap_hw_write_start(map->dev, reg, 1);
+       trace_regmap_hw_write_start(map, reg, 1);
 
        ret = map->bus->write(map->bus_context, map->work_buf,
                              map->format.buf_size);
 
-       trace_regmap_hw_write_done(map->dev, reg, 1);
+       trace_regmap_hw_write_done(map, reg, 1);
 
        return ret;
 }
@@ -1470,7 +1468,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
                dev_info(map->dev, "%x <= %x\n", reg, val);
 #endif
 
-       trace_regmap_reg_write(map->dev, reg, val);
+       trace_regmap_reg_write(map, reg, val);
 
        return map->reg_write(context, reg, val);
 }
@@ -1773,7 +1771,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
        for (i = 0; i < num_regs; i++) {
                int reg = regs[i].reg;
                int val = regs[i].def;
-               trace_regmap_hw_write_start(map->dev, reg, 1);
+               trace_regmap_hw_write_start(map, reg, 1);
                map->format.format_reg(u8, reg, map->reg_shift);
                u8 += reg_bytes + pad_bytes;
                map->format.format_val(u8, val, 0);
@@ -1788,7 +1786,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
 
        for (i = 0; i < num_regs; i++) {
                int reg = regs[i].reg;
-               trace_regmap_hw_write_done(map->dev, reg, 1);
+               trace_regmap_hw_write_done(map, reg, 1);
        }
        return ret;
 }
@@ -2059,15 +2057,13 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
         */
        u8[0] |= map->read_flag_mask;
 
-       trace_regmap_hw_read_start(map->dev, reg,
-                                  val_len / map->format.val_bytes);
+       trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
 
        ret = map->bus->read(map->bus_context, map->work_buf,
                             map->format.reg_bytes + map->format.pad_bytes,
                             val, val_len);
 
-       trace_regmap_hw_read_done(map->dev, reg,
-                                 val_len / map->format.val_bytes);
+       trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
 
        return ret;
 }
@@ -2123,7 +2119,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
                        dev_info(map->dev, "%x => %x\n", reg, *val);
 #endif
 
-               trace_regmap_reg_read(map->dev, reg, *val);
+               trace_regmap_reg_read(map, reg, *val);
 
                if (!map->cache_bypass)
                        regcache_write(map, reg, *val);
@@ -2480,7 +2476,7 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret)
        struct regmap *map = async->map;
        bool wake;
 
-       trace_regmap_async_io_complete(map->dev);
+       trace_regmap_async_io_complete(map);
 
        spin_lock(&map->async_lock);
        list_move(&async->list, &map->async_free);
@@ -2525,7 +2521,7 @@ int regmap_async_complete(struct regmap *map)
        if (!map->bus || !map->bus->async_write)
                return 0;
 
-       trace_regmap_async_complete_start(map->dev);
+       trace_regmap_async_complete_start(map);
 
        wait_event(map->async_waitq, regmap_async_is_done(map));
 
@@ -2534,7 +2530,7 @@ int regmap_async_complete(struct regmap *map)
        map->async_ret = 0;
        spin_unlock_irqrestore(&map->async_lock, flags);
 
-       trace_regmap_async_complete_done(map->dev);
+       trace_regmap_async_complete_done(map);
 
        return ret;
 }
index fae2dbbf57459fe4f4ac01bb0415a02abbda9e18..72d7028f779b55801795ef0fe49d9dda8cde7970 100644 (file)
@@ -142,6 +142,7 @@ struct ports_device {
         * notification
         */
        struct work_struct control_work;
+       struct work_struct config_work;
 
        struct list_head ports;
 
@@ -1837,10 +1838,21 @@ static void config_intr(struct virtio_device *vdev)
 
        portdev = vdev->priv;
 
+       if (!use_multiport(portdev))
+               schedule_work(&portdev->config_work);
+}
+
+static void config_work_handler(struct work_struct *work)
+{
+       struct ports_device *portdev;
+
+       portdev = container_of(work, struct ports_device, control_work);
        if (!use_multiport(portdev)) {
+               struct virtio_device *vdev;
                struct port *port;
                u16 rows, cols;
 
+               vdev = portdev->vdev;
                virtio_cread(vdev, struct virtio_console_config, cols, &cols);
                virtio_cread(vdev, struct virtio_console_config, rows, &rows);
 
@@ -2040,12 +2052,14 @@ static int virtcons_probe(struct virtio_device *vdev)
 
        virtio_device_ready(portdev->vdev);
 
+       INIT_WORK(&portdev->config_work, &config_work_handler);
+       INIT_WORK(&portdev->control_work, &control_work_handler);
+
        if (multiport) {
                unsigned int nr_added_bufs;
 
                spin_lock_init(&portdev->c_ivq_lock);
                spin_lock_init(&portdev->c_ovq_lock);
-               INIT_WORK(&portdev->control_work, &control_work_handler);
 
                nr_added_bufs = fill_queue(portdev->c_ivq,
                                           &portdev->c_ivq_lock);
@@ -2113,6 +2127,8 @@ static void virtcons_remove(struct virtio_device *vdev)
        /* Finish up work that's lined up */
        if (use_multiport(portdev))
                cancel_work_sync(&portdev->control_work);
+       else
+               cancel_work_sync(&portdev->config_work);
 
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
                unplug_port(port);
@@ -2164,6 +2180,7 @@ static int virtcons_freeze(struct virtio_device *vdev)
 
        virtqueue_disable_cb(portdev->c_ivq);
        cancel_work_sync(&portdev->control_work);
+       cancel_work_sync(&portdev->config_work);
        /*
         * Once more: if control_work_handler() was running, it would
         * enable the cb as the last step.
index bba62f9deefbd0f71d59409daf85857cc2caa983..ec57ba2bbd87ac9f2a251e350598fa52019d7815 100644 (file)
@@ -225,12 +225,12 @@ static int __init efm32_clockevent_init(struct device_node *np)
        clock_event_ddata.base = base;
        clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ);
 
-       setup_irq(irq, &efm32_clock_event_irq);
-
        clockevents_config_and_register(&clock_event_ddata.evtdev,
                                        DIV_ROUND_CLOSEST(rate, 1024),
                                        0xf, 0xffff);
 
+       setup_irq(irq, &efm32_clock_event_irq);
+
        return 0;
 
 err_get_irq:
index 02268448dc8540a9f53113f28c29e6a292209a5a..5dcbf90b8015ce40787d2acf27a53a142d4aed8d 100644 (file)
@@ -178,10 +178,6 @@ static void __init sun5i_timer_init(struct device_node *node)
 
        ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
 
-       ret = setup_irq(irq, &sun5i_timer_irq);
-       if (ret)
-               pr_warn("failed to setup irq %d\n", irq);
-
        /* Enable timer0 interrupt */
        val = readl(timer_base + TIMER_IRQ_EN_REG);
        writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
@@ -191,6 +187,10 @@ static void __init sun5i_timer_init(struct device_node *node)
 
        clockevents_config_and_register(&sun5i_clockevent, rate,
                                        TIMER_SYNC_TICKS, 0xffffffff);
+
+       ret = setup_irq(irq, &sun5i_timer_irq);
+       if (ret)
+               pr_warn("failed to setup irq %d\n", irq);
 }
 CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
                       sun5i_timer_init);
index 38e68618513a4728fe637a46b6a6ce79edb54730..980151f34707b2560aab8b1dbe84457b07308949 100644 (file)
@@ -37,11 +37,11 @@ static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
                deepidle = true;
 
        ret = mvebu_v7_cpu_suspend(deepidle);
+       cpu_pm_exit();
+
        if (ret)
                return ret;
 
-       cpu_pm_exit();
-
        return index;
 }
 
@@ -50,17 +50,17 @@ static struct cpuidle_driver armadaxp_idle_driver = {
        .states[0]              = ARM_CPUIDLE_WFI_STATE,
        .states[1]              = {
                .enter                  = mvebu_v7_enter_idle,
-               .exit_latency           = 10,
+               .exit_latency           = 100,
                .power_usage            = 50,
-               .target_residency       = 100,
+               .target_residency       = 1000,
                .name                   = "MV CPU IDLE",
                .desc                   = "CPU power down",
        },
        .states[2]              = {
                .enter                  = mvebu_v7_enter_idle,
-               .exit_latency           = 100,
+               .exit_latency           = 1000,
                .power_usage            = 5,
-               .target_residency       = 1000,
+               .target_residency       = 10000,
                .flags                  = MVEBU_V7_FLAG_DEEP_IDLE,
                .name                   = "MV CPU DEEP IDLE",
                .desc                   = "CPU and L2 Fabric power down",
index 4a5fd245014e6666721c111b85515b2e1b05f74c..83aa55d6fa5d65e6243abc13e29c1d4766768eeb 100644 (file)
 
 #define DRIVER_NAME    "pl08xdmac"
 
+#define PL80X_DMA_BUSWIDTHS \
+       BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
+       BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+       BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+       BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)
+
 static struct amba_driver pl08x_amba_driver;
 struct pl08x_driver_data;
 
@@ -2070,6 +2076,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        pl08x->memcpy.device_pause = pl08x_pause;
        pl08x->memcpy.device_resume = pl08x_resume;
        pl08x->memcpy.device_terminate_all = pl08x_terminate_all;
+       pl08x->memcpy.src_addr_widths = PL80X_DMA_BUSWIDTHS;
+       pl08x->memcpy.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
+       pl08x->memcpy.directions = BIT(DMA_MEM_TO_MEM);
+       pl08x->memcpy.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
 
        /* Initialize slave engine */
        dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
@@ -2086,6 +2096,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        pl08x->slave.device_pause = pl08x_pause;
        pl08x->slave.device_resume = pl08x_resume;
        pl08x->slave.device_terminate_all = pl08x_terminate_all;
+       pl08x->slave.src_addr_widths = PL80X_DMA_BUSWIDTHS;
+       pl08x->slave.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
+       pl08x->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       pl08x->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
 
        /* Get the platform data */
        pl08x->pd = dev_get_platdata(&adev->dev);
index 1e1a4c5675426048dcef03616c15d8e744db2c6e..0b4fc6fb48ce7c5cec62d9a1ef4291e0b175cfaf 100644 (file)
@@ -238,93 +238,126 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
 }
 
 /*
- * atc_get_current_descriptors -
- * locate the descriptor which equal to physical address in DSCR
- * @atchan: the channel we want to start
- * @dscr_addr: physical descriptor address in DSCR
+ * atc_get_desc_by_cookie - get the descriptor of a cookie
+ * @atchan: the DMA channel
+ * @cookie: the cookie to get the descriptor for
  */
-static struct at_desc *atc_get_current_descriptors(struct at_dma_chan *atchan,
-                                                       u32 dscr_addr)
+static struct at_desc *atc_get_desc_by_cookie(struct at_dma_chan *atchan,
+                                               dma_cookie_t cookie)
 {
-       struct at_desc  *desc, *_desc, *child, *desc_cur = NULL;
+       struct at_desc *desc, *_desc;
 
-       list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
-               if (desc->lli.dscr == dscr_addr) {
-                       desc_cur = desc;
-                       break;
-               }
+       list_for_each_entry_safe(desc, _desc, &atchan->queue, desc_node) {
+               if (desc->txd.cookie == cookie)
+                       return desc;
+       }
 
-               list_for_each_entry(child, &desc->tx_list, desc_node) {
-                       if (child->lli.dscr == dscr_addr) {
-                               desc_cur = child;
-                               break;
-                       }
-               }
+       list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
+               if (desc->txd.cookie == cookie)
+                       return desc;
        }
 
-       return desc_cur;
+       return NULL;
 }
 
-/*
- * atc_get_bytes_left -
- * Get the number of bytes residue in dma buffer,
- * @chan: the channel we want to start
+/**
+ * atc_calc_bytes_left - calculates the number of bytes left according to the
+ * value read from CTRLA.
+ *
+ * @current_len: the number of bytes left before reading CTRLA
+ * @ctrla: the value of CTRLA
+ * @desc: the descriptor containing the transfer width
+ */
+static inline int atc_calc_bytes_left(int current_len, u32 ctrla,
+                                       struct at_desc *desc)
+{
+       return current_len - ((ctrla & ATC_BTSIZE_MAX) << desc->tx_width);
+}
+
+/**
+ * atc_calc_bytes_left_from_reg - calculates the number of bytes left according
+ * to the current value of CTRLA.
+ *
+ * @current_len: the number of bytes left before reading CTRLA
+ * @atchan: the channel to read CTRLA for
+ * @desc: the descriptor containing the transfer width
+ */
+static inline int atc_calc_bytes_left_from_reg(int current_len,
+                       struct at_dma_chan *atchan, struct at_desc *desc)
+{
+       u32 ctrla = channel_readl(atchan, CTRLA);
+
+       return atc_calc_bytes_left(current_len, ctrla, desc);
+}
+
+/**
+ * atc_get_bytes_left - get the number of bytes residue for a cookie
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
  */
-static int atc_get_bytes_left(struct dma_chan *chan)
+static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
-       struct at_dma           *atdma = to_at_dma(chan->device);
-       int     chan_id = atchan->chan_common.chan_id;
        struct at_desc *desc_first = atc_first_active(atchan);
-       struct at_desc *desc_cur;
-       int ret = 0, count = 0;
+       struct at_desc *desc;
+       int ret;
+       u32 ctrla, dscr;
 
        /*
-        * Initialize necessary values in the first time.
-        * remain_desc record remain desc length.
+        * If the cookie doesn't match to the currently running transfer then
+        * we can return the total length of the associated DMA transfer,
+        * because it is still queued.
         */
-       if (atchan->remain_desc == 0)
-               /* First descriptor embedds the transaction length */
-               atchan->remain_desc = desc_first->len;
+       desc = atc_get_desc_by_cookie(atchan, cookie);
+       if (desc == NULL)
+               return -EINVAL;
+       else if (desc != desc_first)
+               return desc->total_len;
 
-       /*
-        * This happens when current descriptor transfer complete.
-        * The residual buffer size should reduce current descriptor length.
-        */
-       if (unlikely(test_bit(ATC_IS_BTC, &atchan->status))) {
-               clear_bit(ATC_IS_BTC, &atchan->status);
-               desc_cur = atc_get_current_descriptors(atchan,
-                                               channel_readl(atchan, DSCR));
-               if (!desc_cur) {
-                       ret = -EINVAL;
-                       goto out;
-               }
+       /* cookie matches to the currently running transfer */
+       ret = desc_first->total_len;
 
-               count = (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
-                       << desc_first->tx_width;
-               if (atchan->remain_desc < count) {
-                       ret = -EINVAL;
-                       goto out;
+       if (desc_first->lli.dscr) {
+               /* hardware linked list transfer */
+
+               /*
+                * Calculate the residue by removing the length of the child
+                * descriptors already transferred from the total length.
+                * To get the current child descriptor we can use the value of
+                * the channel's DSCR register and compare it against the value
+                * of the hardware linked list structure of each child
+                * descriptor.
+                */
+
+               ctrla = channel_readl(atchan, CTRLA);
+               rmb(); /* ensure CTRLA is read before DSCR */
+               dscr = channel_readl(atchan, DSCR);
+
+               /* for the first descriptor we can be more accurate */
+               if (desc_first->lli.dscr == dscr)
+                       return atc_calc_bytes_left(ret, ctrla, desc_first);
+
+               ret -= desc_first->len;
+               list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
+                       if (desc->lli.dscr == dscr)
+                               break;
+
+                       ret -= desc->len;
                }
 
-               atchan->remain_desc -= count;
-               ret = atchan->remain_desc;
-       } else {
                /*
-                * Get residual bytes when current
-                * descriptor transfer in progress.
+                * For the last descriptor in the chain we can calculate
+                * the remaining bytes using the channel's register.
+                * Note that the transfer width of the first and last
+                * descriptor may differ.
                 */
-               count = (channel_readl(atchan, CTRLA) & ATC_BTSIZE_MAX)
-                               << (desc_first->tx_width);
-               ret = atchan->remain_desc - count;
+               if (!desc->lli.dscr)
+                       ret = atc_calc_bytes_left_from_reg(ret, atchan, desc);
+       } else {
+               /* single transfer */
+               ret = atc_calc_bytes_left_from_reg(ret, atchan, desc_first);
        }
-       /*
-        * Check fifo empty.
-        */
-       if (!(dma_readl(atdma, CHSR) & AT_DMA_EMPT(chan_id)))
-               atc_issue_pending(chan);
 
-out:
        return ret;
 }
 
@@ -539,8 +572,6 @@ static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
                                        /* Give information to tasklet */
                                        set_bit(ATC_IS_ERROR, &atchan->status);
                                }
-                               if (pending & AT_DMA_BTC(i))
-                                       set_bit(ATC_IS_BTC, &atchan->status);
                                tasklet_schedule(&atchan->tasklet);
                                ret = IRQ_HANDLED;
                        }
@@ -653,14 +684,18 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                desc->lli.ctrlb = ctrlb;
 
                desc->txd.cookie = 0;
+               desc->len = xfer_count << src_width;
 
                atc_desc_chain(&first, &prev, desc);
        }
 
        /* First descriptor of the chain embedds additional information */
        first->txd.cookie = -EBUSY;
-       first->len = len;
+       first->total_len = len;
+
+       /* set transfer width for the calculation of the residue */
        first->tx_width = src_width;
+       prev->tx_width = src_width;
 
        /* set end-of-link to the last link descriptor of list*/
        set_desc_eol(desc);
@@ -752,6 +787,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                                        | ATC_SRC_WIDTH(mem_width)
                                        | len >> mem_width;
                        desc->lli.ctrlb = ctrlb;
+                       desc->len = len;
 
                        atc_desc_chain(&first, &prev, desc);
                        total_len += len;
@@ -792,6 +828,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                                        | ATC_DST_WIDTH(mem_width)
                                        | len >> reg_width;
                        desc->lli.ctrlb = ctrlb;
+                       desc->len = len;
 
                        atc_desc_chain(&first, &prev, desc);
                        total_len += len;
@@ -806,8 +843,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
        /* First descriptor of the chain embedds additional information */
        first->txd.cookie = -EBUSY;
-       first->len = total_len;
+       first->total_len = total_len;
+
+       /* set transfer width for the calculation of the residue */
        first->tx_width = reg_width;
+       prev->tx_width = reg_width;
 
        /* first link descriptor of list is responsible of flags */
        first->txd.flags = flags; /* client is in control of this ack */
@@ -872,6 +912,7 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
                                | ATC_FC_MEM2PER
                                | ATC_SIF(atchan->mem_if)
                                | ATC_DIF(atchan->per_if);
+               desc->len = period_len;
                break;
 
        case DMA_DEV_TO_MEM:
@@ -883,6 +924,7 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
                                | ATC_FC_PER2MEM
                                | ATC_SIF(atchan->per_if)
                                | ATC_DIF(atchan->mem_if);
+               desc->len = period_len;
                break;
 
        default:
@@ -964,7 +1006,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 
        /* First descriptor of the chain embedds additional information */
        first->txd.cookie = -EBUSY;
-       first->len = buf_len;
+       first->total_len = buf_len;
        first->tx_width = reg_width;
 
        return &first->txd;
@@ -1118,7 +1160,7 @@ atc_tx_status(struct dma_chan *chan,
        spin_lock_irqsave(&atchan->lock, flags);
 
        /*  Get number of bytes left in the active transactions */
-       bytes = atc_get_bytes_left(chan);
+       bytes = atc_get_bytes_left(chan, cookie);
 
        spin_unlock_irqrestore(&atchan->lock, flags);
 
@@ -1214,7 +1256,6 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
 
        spin_lock_irqsave(&atchan->lock, flags);
        atchan->descs_allocated = i;
-       atchan->remain_desc = 0;
        list_splice(&tmp_list, &atchan->free_list);
        dma_cookie_init(chan);
        spin_unlock_irqrestore(&atchan->lock, flags);
@@ -1257,7 +1298,6 @@ static void atc_free_chan_resources(struct dma_chan *chan)
        list_splice_init(&atchan->free_list, &list);
        atchan->descs_allocated = 0;
        atchan->status = 0;
-       atchan->remain_desc = 0;
 
        dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
 }
index d6bba6c636c2b9ab4f05331084e07f59b797f1aa..2727ca560572586482cb53a0f38522e0b66abfe3 100644 (file)
@@ -181,8 +181,9 @@ struct at_lli {
  * @at_lli: hardware lli structure
  * @txd: support for the async_tx api
  * @desc_node: node on the channed descriptors list
- * @len: total transaction bytecount
+ * @len: descriptor byte count
  * @tx_width: transfer width
+ * @total_len: total transaction byte count
  */
 struct at_desc {
        /* FIRST values the hardware uses */
@@ -194,6 +195,7 @@ struct at_desc {
        struct list_head                desc_node;
        size_t                          len;
        u32                             tx_width;
+       size_t                          total_len;
 };
 
 static inline struct at_desc *
@@ -213,7 +215,6 @@ txd_to_at_desc(struct dma_async_tx_descriptor *txd)
 enum atc_status {
        ATC_IS_ERROR = 0,
        ATC_IS_PAUSED = 1,
-       ATC_IS_BTC = 2,
        ATC_IS_CYCLIC = 24,
 };
 
@@ -231,7 +232,6 @@ enum atc_status {
  * @save_cfg: configuration register that is saved on suspend/resume cycle
  * @save_dscr: for cyclic operations, preserve next descriptor address in
  *             the cyclic list on suspend/resume cycle
- * @remain_desc: to save remain desc length
  * @dma_sconfig: configuration for slave transfers, passed via
  * .device_config
  * @lock: serializes enqueue/dequeue operations to descriptors lists
@@ -251,7 +251,6 @@ struct at_dma_chan {
        struct tasklet_struct   tasklet;
        u32                     save_cfg;
        u32                     save_dscr;
-       u32                     remain_desc;
        struct dma_slave_config dma_sconfig;
 
        spinlock_t              lock;
index 6565a361e7e51c7e80bbbc6d920880b47aa71af8..b2c3ae07142910a39c90b7ed47f718af35821021 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "internal.h"
 
+#define DRV_NAME       "dw_dmac"
+
 static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
                                        struct of_dma *ofdma)
 {
@@ -284,7 +286,7 @@ static struct platform_driver dw_driver = {
        .remove         = dw_remove,
        .shutdown       = dw_shutdown,
        .driver = {
-               .name   = "dw_dmac",
+               .name   = DRV_NAME,
                .pm     = &dw_dev_pm_ops,
                .of_match_table = of_match_ptr(dw_dma_of_id_table),
                .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
@@ -305,3 +307,4 @@ module_exit(dw_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver");
+MODULE_ALIAS("platform:" DRV_NAME);
index 18c0a131e4e41d21ec9ffab272f26258fb483011..66a0efb9651d3d8f3240701fafe2299b9abca598 100644 (file)
@@ -531,6 +531,10 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
                dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
        }
 
+       /* Set bits of CONFIG register with dynamic context switching */
+       if (readl(sdma->regs + SDMA_H_CONFIG) == 0)
+               writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+
        return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1394,9 +1398,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
        writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-       /* Set bits of CONFIG register with given context switching mode */
-       writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
-
        /* Initializes channel's priorities */
        sdma_set_channel_priority(&sdma->channel[0], 7);
 
index 910ff8ab9c9cfb018c6a18e8ae3126767b6e2580..d8135adb2238012460cfb67165d0f322f809230a 100644 (file)
@@ -645,6 +645,7 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
        pr_debug("     sdma queue id: %d\n", q->properties.sdma_queue_id);
        pr_debug("     sdma engine id: %d\n", q->properties.sdma_engine_id);
 
+       init_sdma_vm(dqm, q, qpd);
        retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj,
                                &q->gart_mqd_addr, &q->properties);
        if (retval != 0) {
@@ -652,7 +653,14 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
                return retval;
        }
 
-       init_sdma_vm(dqm, q, qpd);
+       retval = mqd->load_mqd(mqd, q->mqd, 0,
+                               0, NULL);
+       if (retval != 0) {
+               deallocate_sdma_queue(dqm, q->sdma_id);
+               mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj);
+               return retval;
+       }
+
        return 0;
 }
 
index e415a2a9207eb4605632f91e97e2a271809c04d1..c7d298e62c96bc026154fbe48c4cc7a3828abdb9 100644 (file)
@@ -44,7 +44,7 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
        BUG_ON(!kq || !dev);
        BUG_ON(type != KFD_QUEUE_TYPE_DIQ && type != KFD_QUEUE_TYPE_HIQ);
 
-       pr_debug("kfd: In func %s initializing queue type %d size %d\n",
+       pr_debug("amdkfd: In func %s initializing queue type %d size %d\n",
                        __func__, KFD_QUEUE_TYPE_HIQ, queue_size);
 
        nop.opcode = IT_NOP;
@@ -69,12 +69,16 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
 
        prop.doorbell_ptr = kfd_get_kernel_doorbell(dev, &prop.doorbell_off);
 
-       if (prop.doorbell_ptr == NULL)
+       if (prop.doorbell_ptr == NULL) {
+               pr_err("amdkfd: error init doorbell");
                goto err_get_kernel_doorbell;
+       }
 
        retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq);
-       if (retval != 0)
+       if (retval != 0) {
+               pr_err("amdkfd: error init pq queues size (%d)\n", queue_size);
                goto err_pq_allocate_vidmem;
+       }
 
        kq->pq_kernel_addr = kq->pq->cpu_ptr;
        kq->pq_gpu_addr = kq->pq->gpu_addr;
@@ -165,10 +169,8 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
 err_eop_allocate_vidmem:
        kfd_gtt_sa_free(dev, kq->pq);
 err_pq_allocate_vidmem:
-       pr_err("kfd: error init pq\n");
        kfd_release_kernel_doorbell(dev, prop.doorbell_ptr);
 err_get_kernel_doorbell:
-       pr_err("kfd: error init doorbell");
        return false;
 
 }
@@ -187,6 +189,8 @@ static void uninitialize(struct kernel_queue *kq)
        else if (kq->queue->properties.type == KFD_QUEUE_TYPE_DIQ)
                kfd_gtt_sa_free(kq->dev, kq->fence_mem_obj);
 
+       kq->mqd->uninit_mqd(kq->mqd, kq->queue->mqd, kq->queue->mqd_mem_obj);
+
        kfd_gtt_sa_free(kq->dev, kq->rptr_mem);
        kfd_gtt_sa_free(kq->dev, kq->wptr_mem);
        kq->ops_asic_specific.uninitialize(kq);
@@ -211,7 +215,7 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
        queue_address = (unsigned int *)kq->pq_kernel_addr;
        queue_size_dwords = kq->queue->properties.queue_size / sizeof(uint32_t);
 
-       pr_debug("kfd: In func %s\nrptr: %d\nwptr: %d\nqueue_address 0x%p\n",
+       pr_debug("amdkfd: In func %s\nrptr: %d\nwptr: %d\nqueue_address 0x%p\n",
                        __func__, rptr, wptr, queue_address);
 
        available_size = (rptr - 1 - wptr + queue_size_dwords) %
@@ -296,7 +300,7 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
        }
 
        if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE) == false) {
-               pr_err("kfd: failed to init kernel queue\n");
+               pr_err("amdkfd: failed to init kernel queue\n");
                kfree(kq);
                return NULL;
        }
@@ -319,7 +323,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev)
 
        BUG_ON(!dev);
 
-       pr_err("kfd: starting kernel queue test\n");
+       pr_err("amdkfd: starting kernel queue test\n");
 
        kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ);
        BUG_ON(!kq);
@@ -330,7 +334,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev)
                buffer[i] = kq->nop_packet;
        kq->ops.submit_packet(kq);
 
-       pr_err("kfd: ending kernel queue test\n");
+       pr_err("amdkfd: ending kernel queue test\n");
 }
 
 
index a5e74612100e4ea02de3ab01ffceef42d8f2f61d..0a6780367d28689f907a4b750f1ee5fc2ef403d9 100644 (file)
@@ -50,7 +50,7 @@ config DRM_EXYNOS_DSI
 
 config DRM_EXYNOS_DP
        bool "EXYNOS DRM DP driver support"
-       depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7DECON) && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
+       depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
        default DRM_EXYNOS
        select DRM_PANEL
        help
index 63f02e2380ae1a24746ed87153a1703491f23dff..970046199608484365195ecdd78d27fecc57ed4b 100644 (file)
@@ -888,8 +888,8 @@ static int decon_probe(struct platform_device *pdev)
        of_node_put(i80_if_timings);
 
        ctx->regs = of_iomap(dev->of_node, 0);
-       if (IS_ERR(ctx->regs)) {
-               ret = PTR_ERR(ctx->regs);
+       if (!ctx->regs) {
+               ret = -ENOMEM;
                goto err_del_component;
        }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
deleted file mode 100644 (file)
index ba9b3d5..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *     Inki Dae <inki.dae@samsung.com>
- *     Joonyoung Shim <jy0922.shim@samsung.com>
- *     Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-
-#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
-
-#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
-                               drm_connector)
-
-struct exynos_drm_connector {
-       struct drm_connector            drm_connector;
-       uint32_t                        encoder_id;
-       struct exynos_drm_display       *display;
-};
-
-static int exynos_drm_connector_get_modes(struct drm_connector *connector)
-{
-       struct exynos_drm_connector *exynos_connector =
-                                       to_exynos_connector(connector);
-       struct exynos_drm_display *display = exynos_connector->display;
-       struct edid *edid = NULL;
-       unsigned int count = 0;
-       int ret;
-
-       /*
-        * if get_edid() exists then get_edid() callback of hdmi side
-        * is called to get edid data through i2c interface else
-        * get timing from the FIMD driver(display controller).
-        *
-        * P.S. in case of lcd panel, count is always 1 if success
-        * because lcd panel has only one mode.
-        */
-       if (display->ops->get_edid) {
-               edid = display->ops->get_edid(display, connector);
-               if (IS_ERR_OR_NULL(edid)) {
-                       ret = PTR_ERR(edid);
-                       edid = NULL;
-                       DRM_ERROR("Panel operation get_edid failed %d\n", ret);
-                       goto out;
-               }
-
-               count = drm_add_edid_modes(connector, edid);
-               if (!count) {
-                       DRM_ERROR("Add edid modes failed %d\n", count);
-                       goto out;
-               }
-
-               drm_mode_connector_update_edid_property(connector, edid);
-       } else {
-               struct exynos_drm_panel_info *panel;
-               struct drm_display_mode *mode = drm_mode_create(connector->dev);
-               if (!mode) {
-                       DRM_ERROR("failed to create a new display mode.\n");
-                       return 0;
-               }
-
-               if (display->ops->get_panel)
-                       panel = display->ops->get_panel(display);
-               else {
-                       drm_mode_destroy(connector->dev, mode);
-                       return 0;
-               }
-
-               drm_display_mode_from_videomode(&panel->vm, mode);
-               mode->width_mm = panel->width_mm;
-               mode->height_mm = panel->height_mm;
-               connector->display_info.width_mm = mode->width_mm;
-               connector->display_info.height_mm = mode->height_mm;
-
-               mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-               drm_mode_set_name(mode);
-               drm_mode_probed_add(connector, mode);
-
-               count = 1;
-       }
-
-out:
-       kfree(edid);
-       return count;
-}
-
-static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
-                                           struct drm_display_mode *mode)
-{
-       struct exynos_drm_connector *exynos_connector =
-                                       to_exynos_connector(connector);
-       struct exynos_drm_display *display = exynos_connector->display;
-       int ret = MODE_BAD;
-
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       if (display->ops->check_mode)
-               if (!display->ops->check_mode(display, mode))
-                       ret = MODE_OK;
-
-       return ret;
-}
-
-static struct drm_encoder *exynos_drm_best_encoder(
-               struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct exynos_drm_connector *exynos_connector =
-                                       to_exynos_connector(connector);
-       return drm_encoder_find(dev, exynos_connector->encoder_id);
-}
-
-static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
-       .get_modes      = exynos_drm_connector_get_modes,
-       .mode_valid     = exynos_drm_connector_mode_valid,
-       .best_encoder   = exynos_drm_best_encoder,
-};
-
-static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
-                               unsigned int max_width, unsigned int max_height)
-{
-       struct exynos_drm_connector *exynos_connector =
-                                       to_exynos_connector(connector);
-       struct exynos_drm_display *display = exynos_connector->display;
-       unsigned int width, height;
-
-       width = max_width;
-       height = max_height;
-
-       /*
-        * if specific driver want to find desired_mode using maxmum
-        * resolution then get max width and height from that driver.
-        */
-       if (display->ops->get_max_resol)
-               display->ops->get_max_resol(display, &width, &height);
-
-       return drm_helper_probe_single_connector_modes(connector, width,
-                                                       height);
-}
-
-/* get detection status of display device. */
-static enum drm_connector_status
-exynos_drm_connector_detect(struct drm_connector *connector, bool force)
-{
-       struct exynos_drm_connector *exynos_connector =
-                                       to_exynos_connector(connector);
-       struct exynos_drm_display *display = exynos_connector->display;
-       enum drm_connector_status status = connector_status_disconnected;
-
-       if (display->ops->is_connected) {
-               if (display->ops->is_connected(display))
-                       status = connector_status_connected;
-               else
-                       status = connector_status_disconnected;
-       }
-
-       return status;
-}
-
-static void exynos_drm_connector_destroy(struct drm_connector *connector)
-{
-       struct exynos_drm_connector *exynos_connector =
-               to_exynos_connector(connector);
-
-       drm_connector_unregister(connector);
-       drm_connector_cleanup(connector);
-       kfree(exynos_connector);
-}
-
-static struct drm_connector_funcs exynos_connector_funcs = {
-       .dpms           = drm_helper_connector_dpms,
-       .fill_modes     = exynos_drm_connector_fill_modes,
-       .detect         = exynos_drm_connector_detect,
-       .destroy        = exynos_drm_connector_destroy,
-};
-
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
-                                                  struct drm_encoder *encoder)
-{
-       struct exynos_drm_connector *exynos_connector;
-       struct exynos_drm_display *display = exynos_drm_get_display(encoder);
-       struct drm_connector *connector;
-       int type;
-       int err;
-
-       exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
-       if (!exynos_connector)
-               return NULL;
-
-       connector = &exynos_connector->drm_connector;
-
-       switch (display->type) {
-       case EXYNOS_DISPLAY_TYPE_HDMI:
-               type = DRM_MODE_CONNECTOR_HDMIA;
-               connector->interlace_allowed = true;
-               connector->polled = DRM_CONNECTOR_POLL_HPD;
-               break;
-       case EXYNOS_DISPLAY_TYPE_VIDI:
-               type = DRM_MODE_CONNECTOR_VIRTUAL;
-               connector->polled = DRM_CONNECTOR_POLL_HPD;
-               break;
-       default:
-               type = DRM_MODE_CONNECTOR_Unknown;
-               break;
-       }
-
-       drm_connector_init(dev, connector, &exynos_connector_funcs, type);
-       drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
-
-       err = drm_connector_register(connector);
-       if (err)
-               goto err_connector;
-
-       exynos_connector->encoder_id = encoder->base.id;
-       exynos_connector->display = display;
-       connector->dpms = DRM_MODE_DPMS_OFF;
-       connector->encoder = encoder;
-
-       err = drm_mode_connector_attach_encoder(connector, encoder);
-       if (err) {
-               DRM_ERROR("failed to attach a connector to a encoder\n");
-               goto err_sysfs;
-       }
-
-       DRM_DEBUG_KMS("connector has been created\n");
-
-       return connector;
-
-err_sysfs:
-       drm_connector_unregister(connector);
-err_connector:
-       drm_connector_cleanup(connector);
-       kfree(exynos_connector);
-       return NULL;
-}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
deleted file mode 100644 (file)
index 4eb20d7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *     Inki Dae <inki.dae@samsung.com>
- *     Joonyoung Shim <jy0922.shim@samsung.com>
- *     Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef _EXYNOS_DRM_CONNECTOR_H_
-#define _EXYNOS_DRM_CONNECTOR_H_
-
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
-                                                  struct drm_encoder *encoder);
-
-#endif
index 925fc69af1a0c28a083171cdba563537ee3741da..c300e22da8ac5f2f4294c27543e62291ee0a8739 100644 (file)
@@ -284,14 +284,9 @@ static void fimd_clear_channel(struct fimd_context *ctx)
        }
 }
 
-static int fimd_ctx_initialize(struct fimd_context *ctx,
+static int fimd_iommu_attach_devices(struct fimd_context *ctx,
                        struct drm_device *drm_dev)
 {
-       struct exynos_drm_private *priv;
-       priv = drm_dev->dev_private;
-
-       ctx->drm_dev = drm_dev;
-       ctx->pipe = priv->pipe++;
 
        /* attach this sub driver to iommu mapping if supported. */
        if (is_drm_iommu_supported(ctx->drm_dev)) {
@@ -313,7 +308,7 @@ static int fimd_ctx_initialize(struct fimd_context *ctx,
        return 0;
 }
 
-static void fimd_ctx_remove(struct fimd_context *ctx)
+static void fimd_iommu_detach_devices(struct fimd_context *ctx)
 {
        /* detach this sub driver from iommu mapping if supported. */
        if (is_drm_iommu_supported(ctx->drm_dev))
@@ -1056,25 +1051,23 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
 {
        struct fimd_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
+       struct exynos_drm_private *priv = drm_dev->dev_private;
        int ret;
 
-       ret = fimd_ctx_initialize(ctx, drm_dev);
-       if (ret) {
-               DRM_ERROR("fimd_ctx_initialize failed.\n");
-               return ret;
-       }
+       ctx->drm_dev = drm_dev;
+       ctx->pipe = priv->pipe++;
 
        ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
                                           EXYNOS_DISPLAY_TYPE_LCD,
                                           &fimd_crtc_ops, ctx);
-       if (IS_ERR(ctx->crtc)) {
-               fimd_ctx_remove(ctx);
-               return PTR_ERR(ctx->crtc);
-       }
 
        if (ctx->display)
                exynos_drm_create_enc_conn(drm_dev, ctx->display);
 
+       ret = fimd_iommu_attach_devices(ctx, drm_dev);
+       if (ret)
+               return ret;
+
        return 0;
 
 }
@@ -1086,10 +1079,10 @@ static void fimd_unbind(struct device *dev, struct device *master,
 
        fimd_dpms(ctx->crtc, DRM_MODE_DPMS_OFF);
 
+       fimd_iommu_detach_devices(ctx);
+
        if (ctx->display)
                exynos_dpi_remove(ctx->display);
-
-       fimd_ctx_remove(ctx);
 }
 
 static const struct component_ops fimd_component_ops = {
index a5616872eee7f9defdebe63025b9e92f10060fc7..8ad5b7294eb4801c189fa3b2cdf90ebb24606fd3 100644 (file)
@@ -175,7 +175,7 @@ static int exynos_disable_plane(struct drm_plane *plane)
        struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
 
-       if (exynos_crtc->ops->win_disable)
+       if (exynos_crtc && exynos_crtc->ops->win_disable)
                exynos_crtc->ops->win_disable(exynos_crtc,
                                              exynos_plane->zpos);
 
index 9943c20a741d46bc8f40452bdf87dcfa15d50d8c..6d22128d97b1b8ce732208fe93ed897dc0a2cdcd 100644 (file)
@@ -37,6 +37,7 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -2416,6 +2417,14 @@ intel_alloc_plane_obj(struct intel_crtc *crtc,
        return false;
 }
 
+/* Update plane->state->fb to match plane->fb after driver-internal updates */
+static void
+update_state_fb(struct drm_plane *plane)
+{
+       if (plane->fb != plane->state->fb)
+               drm_atomic_set_fb_for_plane(plane->state, plane->fb);
+}
+
 static void
 intel_find_plane_obj(struct intel_crtc *intel_crtc,
                     struct intel_initial_plane_config *plane_config)
@@ -2462,6 +2471,8 @@ intel_find_plane_obj(struct intel_crtc *intel_crtc,
                        break;
                }
        }
+
+       update_state_fb(intel_crtc->base.primary);
 }
 
 static void i9xx_update_primary_plane(struct drm_crtc *crtc,
@@ -6602,6 +6613,10 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
+       val = I915_READ(DSPCNTR(plane));
+       if (!(val & DISPLAY_PLANE_ENABLE))
+               return;
+
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
@@ -6610,8 +6625,6 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb = &intel_fb->base;
 
-       val = I915_READ(DSPCNTR(plane));
-
        if (INTEL_INFO(dev)->gen >= 4)
                if (val & DISPPLANE_TILED)
                        plane_config->tiling = I915_TILING_X;
@@ -6650,6 +6663,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
                      plane_config->size);
 
        crtc->base.primary->fb = fb;
+       update_state_fb(crtc->base.primary);
 }
 
 static void chv_crtc_clock_get(struct intel_crtc *crtc,
@@ -7643,6 +7657,9 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        fb = &intel_fb->base;
 
        val = I915_READ(PLANE_CTL(pipe, 0));
+       if (!(val & PLANE_CTL_ENABLE))
+               goto error;
+
        if (val & PLANE_CTL_TILED_MASK)
                plane_config->tiling = I915_TILING_X;
 
@@ -7687,6 +7704,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
                      plane_config->size);
 
        crtc->base.primary->fb = fb;
+       update_state_fb(crtc->base.primary);
        return;
 
 error:
@@ -7730,6 +7748,10 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
+       val = I915_READ(DSPCNTR(pipe));
+       if (!(val & DISPLAY_PLANE_ENABLE))
+               return;
+
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
@@ -7738,8 +7760,6 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb = &intel_fb->base;
 
-       val = I915_READ(DSPCNTR(pipe));
-
        if (INTEL_INFO(dev)->gen >= 4)
                if (val & DISPPLANE_TILED)
                        plane_config->tiling = I915_TILING_X;
@@ -7778,6 +7798,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
                      plane_config->size);
 
        crtc->base.primary->fb = fb;
+       update_state_fb(crtc->base.primary);
 }
 
 static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
@@ -9816,6 +9837,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        drm_gem_object_reference(&obj->base);
 
        crtc->primary->fb = fb;
+       update_state_fb(crtc->primary);
 
        work->pending_flip_obj = obj;
 
@@ -9884,6 +9906,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
        crtc->primary->fb = old_fb;
+       update_state_fb(crtc->primary);
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
@@ -13718,6 +13741,7 @@ void intel_modeset_gem_init(struct drm_device *dev)
                                  to_intel_crtc(c)->pipe);
                        drm_framebuffer_unreference(c->primary->fb);
                        c->primary->fb = NULL;
+                       update_state_fb(c->primary);
                }
        }
        mutex_unlock(&dev->struct_mutex);
index 29bd539af183d6d366ef2cafd79c8a5b0ad49ea9..6efa8f38ff5472b42ec9895c7a5505c9992a50c1 100644 (file)
@@ -340,11 +340,13 @@ nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
                /* switch mmio to cpu's native endianness */
 #ifndef __BIG_ENDIAN
-               if (ioread32_native(map + 0x000004) != 0x00000000)
+               if (ioread32_native(map + 0x000004) != 0x00000000) {
 #else
-               if (ioread32_native(map + 0x000004) == 0x00000000)
+               if (ioread32_native(map + 0x000004) == 0x00000000) {
 #endif
                        iowrite32_native(0x01000001, map + 0x000004);
+                       ioread32_native(map);
+               }
 
                /* read boot0 and strapping information */
                boot0 = ioread32_native(map + 0x000000);
index 539561ed3281a1602348eb375b2c698ddb8f7afd..108d048da7643f0b97255edf06e205a72d672a48 100644 (file)
@@ -140,6 +140,49 @@ gm100_identify(struct nvkm_device *device)
                device->oclass[NVDEV_ENGINE_MSVLD  ] = &gk104_msvld_oclass;
                device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass;
                device->oclass[NVDEV_ENGINE_MSPPP  ] = &gf100_msppp_oclass;
+#endif
+               break;
+       case 0x126:
+               device->cname = "GM206";
+               device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nvkm_bios_oclass;
+               device->oclass[NVDEV_SUBDEV_GPIO   ] =  gk104_gpio_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] =  gm204_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_FUSE   ] = &gm107_fuse_oclass;
+#if 0
+               /* looks to be some non-trivial changes */
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &gk104_clk_oclass;
+               /* priv ring says no to 0x10eb14 writes */
+               device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
+#endif
+               device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm204_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_BUS    ] =  gf100_bus_oclass;
+               device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_LTC    ] =  gm107_ltc_oclass;
+               device->oclass[NVDEV_SUBDEV_IBUS   ] = &gk104_ibus_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_MMU    ] = &gf100_mmu_oclass;
+               device->oclass[NVDEV_SUBDEV_BAR    ] = &gf100_bar_oclass;
+               device->oclass[NVDEV_SUBDEV_PMU    ] =  gk208_pmu_oclass;
+#if 0
+               device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
+#endif
+               device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
+#if 0
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  gm107_gr_oclass;
+#endif
+               device->oclass[NVDEV_ENGINE_DISP   ] =  gm204_disp_oclass;
+#if 0
+               device->oclass[NVDEV_ENGINE_CE0    ] = &gm204_ce0_oclass;
+               device->oclass[NVDEV_ENGINE_CE1    ] = &gm204_ce1_oclass;
+               device->oclass[NVDEV_ENGINE_CE2    ] = &gm204_ce2_oclass;
+               device->oclass[NVDEV_ENGINE_MSVLD  ] = &gk104_msvld_oclass;
+               device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass;
+               device->oclass[NVDEV_ENGINE_MSPPP  ] = &gf100_msppp_oclass;
 #endif
                break;
        default:
index b038b6eb51db2f3104dea58562d14913f4c794ed..043e4296084c176695f6e39ff0f046bbe033b1c0 100644 (file)
@@ -502,72 +502,57 @@ nv04_fifo_intr(struct nvkm_subdev *subdev)
 {
        struct nvkm_device *device = nv_device(subdev);
        struct nv04_fifo_priv *priv = (void *)subdev;
-       uint32_t status, reassign;
-       int cnt = 0;
+       u32 mask = nv_rd32(priv, NV03_PFIFO_INTR_EN_0);
+       u32 stat = nv_rd32(priv, NV03_PFIFO_INTR_0) & mask;
+       u32 reassign, chid, get, sem;
 
        reassign = nv_rd32(priv, NV03_PFIFO_CACHES) & 1;
-       while ((status = nv_rd32(priv, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
-               uint32_t chid, get;
-
-               nv_wr32(priv, NV03_PFIFO_CACHES, 0);
-
-               chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max;
-               get  = nv_rd32(priv, NV03_PFIFO_CACHE1_GET);
+       nv_wr32(priv, NV03_PFIFO_CACHES, 0);
 
-               if (status & NV_PFIFO_INTR_CACHE_ERROR) {
-                       nv04_fifo_cache_error(device, priv, chid, get);
-                       status &= ~NV_PFIFO_INTR_CACHE_ERROR;
-               }
+       chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max;
+       get  = nv_rd32(priv, NV03_PFIFO_CACHE1_GET);
 
-               if (status & NV_PFIFO_INTR_DMA_PUSHER) {
-                       nv04_fifo_dma_pusher(device, priv, chid);
-                       status &= ~NV_PFIFO_INTR_DMA_PUSHER;
-               }
+       if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
+               nv04_fifo_cache_error(device, priv, chid, get);
+               stat &= ~NV_PFIFO_INTR_CACHE_ERROR;
+       }
 
-               if (status & NV_PFIFO_INTR_SEMAPHORE) {
-                       uint32_t sem;
+       if (stat & NV_PFIFO_INTR_DMA_PUSHER) {
+               nv04_fifo_dma_pusher(device, priv, chid);
+               stat &= ~NV_PFIFO_INTR_DMA_PUSHER;
+       }
 
-                       status &= ~NV_PFIFO_INTR_SEMAPHORE;
-                       nv_wr32(priv, NV03_PFIFO_INTR_0,
-                               NV_PFIFO_INTR_SEMAPHORE);
+       if (stat & NV_PFIFO_INTR_SEMAPHORE) {
+               stat &= ~NV_PFIFO_INTR_SEMAPHORE;
+               nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE);
 
-                       sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE);
-                       nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
+               sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE);
+               nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
 
-                       nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
-                       nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
-               }
+               nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
+               nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
+       }
 
-               if (device->card_type == NV_50) {
-                       if (status & 0x00000010) {
-                               status &= ~0x00000010;
-                               nv_wr32(priv, 0x002100, 0x00000010);
-                       }
-
-                       if (status & 0x40000000) {
-                               nv_wr32(priv, 0x002100, 0x40000000);
-                               nvkm_fifo_uevent(&priv->base);
-                               status &= ~0x40000000;
-                       }
+       if (device->card_type == NV_50) {
+               if (stat & 0x00000010) {
+                       stat &= ~0x00000010;
+                       nv_wr32(priv, 0x002100, 0x00000010);
                }
 
-               if (status) {
-                       nv_warn(priv, "unknown intr 0x%08x, ch %d\n",
-                               status, chid);
-                       nv_wr32(priv, NV03_PFIFO_INTR_0, status);
-                       status = 0;
+               if (stat & 0x40000000) {
+                       nv_wr32(priv, 0x002100, 0x40000000);
+                       nvkm_fifo_uevent(&priv->base);
+                       stat &= ~0x40000000;
                }
-
-               nv_wr32(priv, NV03_PFIFO_CACHES, reassign);
        }
 
-       if (status) {
-               nv_error(priv, "still angry after %d spins, halt\n", cnt);
-               nv_wr32(priv, 0x002140, 0);
-               nv_wr32(priv, 0x000140, 0);
+       if (stat) {
+               nv_warn(priv, "unknown intr 0x%08x\n", stat);
+               nv_mask(priv, NV03_PFIFO_INTR_EN_0, stat, 0x00000000);
+               nv_wr32(priv, NV03_PFIFO_INTR_0, stat);
        }
 
-       nv_wr32(priv, 0x000100, 0x00000100);
+       nv_wr32(priv, NV03_PFIFO_CACHES, reassign);
 }
 
 static int
index 2e7ec389eea7903e1480fce2b0a8901f6e8f1b4f..57e2c5b1312385ab1cf1a52b776f6b1170102bae 100644 (file)
@@ -1032,9 +1032,9 @@ gf100_grctx_generate_bundle(struct gf100_grctx *info)
        const int s = 8;
        const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
        mmio_refn(info, 0x408004, 0x00000000, s, b);
-       mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s));
        mmio_refn(info, 0x418808, 0x00000000, s, b);
-       mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s));
 }
 
 void
index b52300d8861a760b323fc00a89dd90c3e86738af..5e9454ba158fe816e7c381e7518a259efb1565d8 100644 (file)
@@ -851,9 +851,9 @@ gk104_grctx_generate_bundle(struct gf100_grctx *info)
        const int s = 8;
        const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
        mmio_refn(info, 0x408004, 0x00000000, s, b);
-       mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s));
        mmio_refn(info, 0x418808, 0x00000000, s, b);
-       mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s));
        mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
 }
 
index 956f4dce960c7912837c9e16889f6b3db4f6819d..b2fae6e389e24260bb5093ffdd9fa5d90982f277 100644 (file)
@@ -871,9 +871,9 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info)
        const int s = 8;
        const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
        mmio_refn(info, 0x408004, 0x00000000, s, b);
-       mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s));
        mmio_refn(info, 0x418e24, 0x00000000, s, b);
-       mmio_refn(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s), 0, b);
+       mmio_wr32(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s));
        mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
 }
 
index d1a89b2bd5c17393d08e441fb2fbeb643fdf5ff1..c4e1f085ee10b810c07ef1557a9438ac6a1eaa77 100644 (file)
@@ -74,7 +74,11 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info)
        u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
        if (ent) {
                if (ver >= 0x41) {
-                       if (!(nv_ro32(bios, ent) & 0x80000000))
+                       u32 ent_value = nv_ro32(bios, ent);
+                       u8 i2c_port = (ent_value >> 27) & 0x1f;
+                       u8 dpaux_port = (ent_value >> 22) & 0x1f;
+                       /* value 0x1f means unused according to DCB 4.x spec */
+                       if (i2c_port == 0x1f && dpaux_port == 0x1f)
                                info->type = DCB_I2C_UNUSED;
                        else
                                info->type = DCB_I2C_PMGR;
index 061eaa9c19c7c0d9add6d7fbf84145fc12afb5b7..122eb5693ba191a7458a3496e6bb96b06aee1ac7 100644 (file)
@@ -153,7 +153,7 @@ void radeon_kfd_device_init(struct radeon_device *rdev)
                        .compute_vmid_bitmap = 0xFF00,
 
                        .first_compute_pipe = 1,
-                       .compute_pipe_count = 8 - 1,
+                       .compute_pipe_count = 4 - 1,
                };
 
                radeon_doorbell_get_kfd_info(rdev,
index 43e09942823ec0fbd554800d36585eea91531989..318165d4855c4bf3aa9e4a23bddc38cc25481968 100644 (file)
@@ -173,17 +173,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
                else
                        rbo->placements[i].lpfn = 0;
        }
-
-       /*
-        * Use two-ended allocation depending on the buffer size to
-        * improve fragmentation quality.
-        * 512kb was measured as the most optimal number.
-        */
-       if (rbo->tbo.mem.size > 512 * 1024) {
-               for (i = 0; i < c; i++) {
-                       rbo->placements[i].flags |= TTM_PL_FLAG_TOPDOWN;
-               }
-       }
 }
 
 int radeon_bo_create(struct radeon_device *rdev,
index 7c669c328c4c7b4945dd22cde0f631aa51cb6b4b..56ce8c2b5530db20d851b585fa0c4f88ef81afa6 100644 (file)
@@ -1959,6 +1959,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
index 204312bfab2c6319985ce8d82d0a92900c746c65..9c4786759f16f4f397a839214600524b9826254c 100644 (file)
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_LOGITECH_T651    0xb00c
+#define USB_DEVICE_ID_LOGITECH_C077    0xc007
 #define USB_DEVICE_ID_LOGITECH_RECEIVER        0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
 #define USB_VENDOR_ID_TIVO             0x150a
 #define USB_DEVICE_ID_TIVO_SLIDE_BT    0x1200
 #define USB_DEVICE_ID_TIVO_SLIDE       0x1201
+#define USB_DEVICE_ID_TIVO_SLIDE_PRO   0x1203
 
 #define USB_VENDOR_ID_TOPSEED          0x0766
 #define USB_DEVICE_ID_TOPSEED_CYBERLINK        0x0204
index d790d8d71f7fc6829f405b7665cc37f0af1bf5a8..d9869692745399b0406dc62b66c1269295ee9835 100644 (file)
@@ -64,6 +64,7 @@ static const struct hid_device_id tivo_devices[] = {
        /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, tivo_devices);
index 9be99a67bfe2ec9f042e765904913628f8c2b654..a821277534611708973ccf080ad78f4136ef0df5 100644 (file)
@@ -78,6 +78,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
index 046351cf17f3432814b46e42f0892920c76f1b32..bbe32d66e5000157b4d3670c23350ff3fa1a0104 100644 (file)
@@ -551,9 +551,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
           (features->type == CINTIQ && !(data[1] & 0x40)))
                return 1;
 
-       if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+       if (wacom->shared) {
                wacom->shared->stylus_in_proximity = true;
 
+               if (wacom->shared->touch_down)
+                       return 1;
+       }
+
        /* in Range while exiting */
        if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
                input_report_key(input, BTN_TOUCH, 0);
@@ -1043,27 +1047,28 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        struct input_dev *input = wacom->input;
        unsigned char *data = wacom->data;
        int i;
-       int current_num_contacts = 0;
+       int current_num_contacts = data[61];
        int contacts_to_send = 0;
        int num_contacts_left = 4; /* maximum contacts per packet */
        int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
        int y_offset = 2;
+       static int contact_with_no_pen_down_count = 0;
 
        if (wacom->features.type == WACOM_27QHDT) {
                current_num_contacts = data[63];
                num_contacts_left = 10;
                byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
                y_offset = 0;
-       } else {
-               current_num_contacts = data[61];
        }
 
        /*
         * First packet resets the counter since only the first
         * packet in series will have non-zero current_num_contacts.
         */
-       if (current_num_contacts)
+       if (current_num_contacts) {
                wacom->num_contacts_left = current_num_contacts;
+               contact_with_no_pen_down_count = 0;
+       }
 
        contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
 
@@ -1096,15 +1101,16 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
                                input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
                                input_report_abs(input, ABS_MT_ORIENTATION, w > h);
                        }
+                       contact_with_no_pen_down_count++;
                }
        }
        input_mt_report_pointer_emulation(input, true);
 
        wacom->num_contacts_left -= contacts_to_send;
-       if (wacom->num_contacts_left <= 0)
+       if (wacom->num_contacts_left <= 0) {
                wacom->num_contacts_left = 0;
-
-       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
+               wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+       }
        return 1;
 }
 
@@ -1116,6 +1122,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
        int current_num_contacts = data[2];
        int contacts_to_send = 0;
        int x_offset = 0;
+       static int contact_with_no_pen_down_count = 0;
 
        /* MTTPC does not support Height and Width */
        if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
@@ -1125,8 +1132,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
         * First packet resets the counter since only the first
         * packet in series will have non-zero current_num_contacts.
         */
-       if (current_num_contacts)
+       if (current_num_contacts) {
                wacom->num_contacts_left = current_num_contacts;
+               contact_with_no_pen_down_count = 0;
+       }
 
        /* There are at most 5 contacts per packet */
        contacts_to_send = min(5, wacom->num_contacts_left);
@@ -1147,15 +1156,16 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
                        int y = get_unaligned_le16(&data[offset + x_offset + 9]);
                        input_report_abs(input, ABS_MT_POSITION_X, x);
                        input_report_abs(input, ABS_MT_POSITION_Y, y);
+                       contact_with_no_pen_down_count++;
                }
        }
        input_mt_report_pointer_emulation(input, true);
 
        wacom->num_contacts_left -= contacts_to_send;
-       if (wacom->num_contacts_left < 0)
+       if (wacom->num_contacts_left <= 0) {
                wacom->num_contacts_left = 0;
-
-       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
+               wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+       }
        return 1;
 }
 
@@ -1193,29 +1203,25 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
        unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       bool prox;
+       bool prox = !wacom->shared->stylus_in_proximity;
        int x = 0, y = 0;
 
        if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
                return 0;
 
-       if (!wacom->shared->stylus_in_proximity) {
-               if (len == WACOM_PKGLEN_TPC1FG) {
-                       prox = data[0] & 0x01;
-                       x = get_unaligned_le16(&data[1]);
-                       y = get_unaligned_le16(&data[3]);
-               } else if (len == WACOM_PKGLEN_TPC1FG_B) {
-                       prox = data[2] & 0x01;
-                       x = get_unaligned_le16(&data[3]);
-                       y = get_unaligned_le16(&data[5]);
-               } else {
-                       prox = data[1] & 0x01;
-                       x = le16_to_cpup((__le16 *)&data[2]);
-                       y = le16_to_cpup((__le16 *)&data[4]);
-               }
-       } else
-               /* force touch out when pen is in prox */
-               prox = 0;
+       if (len == WACOM_PKGLEN_TPC1FG) {
+               prox = prox && (data[0] & 0x01);
+               x = get_unaligned_le16(&data[1]);
+               y = get_unaligned_le16(&data[3]);
+       } else if (len == WACOM_PKGLEN_TPC1FG_B) {
+               prox = prox && (data[2] & 0x01);
+               x = get_unaligned_le16(&data[3]);
+               y = get_unaligned_le16(&data[5]);
+       } else {
+               prox = prox && (data[1] & 0x01);
+               x = le16_to_cpup((__le16 *)&data[2]);
+               y = le16_to_cpup((__le16 *)&data[4]);
+       }
 
        if (prox) {
                input_report_abs(input, ABS_X, x);
@@ -1613,6 +1619,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
        struct input_dev *pad_input = wacom->pad_input;
        unsigned char *data = wacom->data;
        int i;
+       int contact_with_no_pen_down_count = 0;
 
        if (data[0] != 0x02)
            return 0;
@@ -1640,6 +1647,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
                        }
                        input_report_abs(input, ABS_MT_POSITION_X, x);
                        input_report_abs(input, ABS_MT_POSITION_Y, y);
+                       contact_with_no_pen_down_count++;
                }
        }
 
@@ -1649,11 +1657,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
        input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
        input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
        input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
+       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
 
        return 1;
 }
 
-static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
+static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
 {
        struct wacom_features *features = &wacom->features;
        struct input_dev *input = wacom->input;
@@ -1661,7 +1670,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
        int slot = input_mt_get_slot_by_key(input, data[0]);
 
        if (slot < 0)
-               return;
+               return 0;
 
        touch = touch && !wacom->shared->stylus_in_proximity;
 
@@ -1693,7 +1702,9 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
                input_report_abs(input, ABS_MT_POSITION_Y, y);
                input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
                input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
+               last_touch_count++;
        }
+       return last_touch_count;
 }
 
 static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
@@ -1718,6 +1729,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
        unsigned char *data = wacom->data;
        int count = data[1] & 0x07;
        int i;
+       int contact_with_no_pen_down_count = 0;
 
        if (data[0] != 0x02)
            return 0;
@@ -1728,12 +1740,15 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
                int msg_id = data[offset];
 
                if (msg_id >= 2 && msg_id <= 17)
-                       wacom_bpt3_touch_msg(wacom, data + offset);
+                       contact_with_no_pen_down_count = 
+                           wacom_bpt3_touch_msg(wacom, data + offset,
+                                                contact_with_no_pen_down_count);
                else if (msg_id == 128)
                        wacom_bpt3_button_msg(wacom, data + offset);
 
        }
        input_mt_report_pointer_emulation(input, true);
+       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
 
        return 1;
 }
@@ -1759,6 +1774,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
                return 0;
        }
 
+       if (wacom->shared->touch_down)
+               return 0;
+
        prox = (data[1] & 0x20) == 0x20;
 
        /*
index 1793aea4a7d2c58192f6023d43e90c10daedbb52..6eb738ca6d2f353717aac1e63bade383f763afa5 100644 (file)
@@ -1793,11 +1793,11 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN,
                                         IDETAPE_DSC_RW_MAX);
        printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
-               "%lums tDSC%s\n",
+               "%ums tDSC%s\n",
                drive->name, tape->name, *(u16 *)&tape->caps[14],
                (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
                tape->buffer_size / 1024,
-               tape->best_dsc_rw_freq * 1000 / HZ,
+               jiffies_to_msecs(tape->best_dsc_rw_freq),
                (drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
 
        ide_proc_register_driver(drive, tape->driver);
index c7619716c31dd92cb5ddad4f77d98528392698b5..59040265e3614a23fc8508e88dd5b2138e7107e8 100644 (file)
@@ -64,6 +64,14 @@ enum {
 #define GUID_TBL_BLK_NUM_ENTRIES 8
 #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES)
 
+/* Counters should be saturate once they reach their maximum value */
+#define ASSIGN_32BIT_COUNTER(counter, value) do {\
+       if ((value) > U32_MAX)                   \
+               counter = cpu_to_be32(U32_MAX); \
+       else                                     \
+               counter = cpu_to_be32(value);    \
+} while (0)
+
 struct mlx4_mad_rcv_buf {
        struct ib_grh grh;
        u8 payload[256];
@@ -806,10 +814,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 static void edit_counter(struct mlx4_counter *cnt,
                                        struct ib_pma_portcounters *pma_cnt)
 {
-       pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2));
-       pma_cnt->port_rcv_data  = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2));
-       pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames));
-       pma_cnt->port_rcv_packets  = cpu_to_be32(be64_to_cpu(cnt->rx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
+                            (be64_to_cpu(cnt->tx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
+                            (be64_to_cpu(cnt->rx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
+                            be64_to_cpu(cnt->tx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
+                            be64_to_cpu(cnt->rx_frames));
 }
 
 static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
index ac6e2b710ea6fef928271869f0e170f2bbdb158d..b972c0b41799b51e2f554c1abc703d78e0c4636e 100644 (file)
@@ -2697,8 +2697,12 @@ static void handle_bonded_port_state_event(struct work_struct *work)
        spin_lock_bh(&ibdev->iboe.lock);
        for (i = 0; i < MLX4_MAX_PORTS; ++i) {
                struct net_device *curr_netdev = ibdev->iboe.netdevs[i];
+               enum ib_port_state curr_port_state;
 
-               enum ib_port_state curr_port_state =
+               if (!curr_netdev)
+                       continue;
+
+               curr_port_state =
                        (netif_running(curr_netdev) &&
                         netif_carrier_ok(curr_netdev)) ?
                        IB_PORT_ACTIVE : IB_PORT_DOWN;
index f2cceb6493a0aea304c838043735ac3889041438..dda605836546847afbdbdd4c77c976134a914a2e 100644 (file)
@@ -67,9 +67,6 @@
 #define X_MAX_POSITIVE 8176
 #define Y_MAX_POSITIVE 8176
 
-/* maximum ABS_MT_POSITION displacement (in mm) */
-#define DMAX 10
-
 /*****************************************************************************
  *     Stuff we need even when we do not want native Synaptics support
  ****************************************************************************/
@@ -123,32 +120,41 @@ void synaptics_reset(struct psmouse *psmouse)
 
 static bool cr48_profile_sensor;
 
+#define ANY_BOARD_ID 0
 struct min_max_quirk {
        const char * const *pnp_ids;
+       struct {
+               unsigned long int min, max;
+       } board_id;
        int x_min, x_max, y_min, y_max;
 };
 
 static const struct min_max_quirk min_max_pnpid_table[] = {
        {
                (const char * const []){"LEN0033", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1024, 5052, 2258, 4832
        },
        {
-               (const char * const []){"LEN0035", "LEN0042", NULL},
+               (const char * const []){"LEN0042", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1232, 5710, 1156, 4696
        },
        {
                (const char * const []){"LEN0034", "LEN0036", "LEN0037",
                                        "LEN0039", "LEN2002", "LEN2004",
                                        NULL},
+               {ANY_BOARD_ID, 2961},
                1024, 5112, 2024, 4832
        },
        {
                (const char * const []){"LEN2001", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1024, 5022, 2508, 4832
        },
        {
                (const char * const []){"LEN2006", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1264, 5675, 1171, 4688
        },
        { }
@@ -175,9 +181,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
        "LEN0041",
        "LEN0042", /* Yoga */
        "LEN0045",
-       "LEN0046",
        "LEN0047",
-       "LEN0048",
        "LEN0049",
        "LEN2000",
        "LEN2001", /* Edge E431 */
@@ -235,18 +239,39 @@ static int synaptics_model_id(struct psmouse *psmouse)
        return 0;
 }
 
+static int synaptics_more_extended_queries(struct psmouse *psmouse)
+{
+       struct synaptics_data *priv = psmouse->private;
+       unsigned char buf[3];
+
+       if (synaptics_send_cmd(psmouse, SYN_QUE_MEXT_CAPAB_10, buf))
+               return -1;
+
+       priv->ext_cap_10 = (buf[0]<<16) | (buf[1]<<8) | buf[2];
+
+       return 0;
+}
+
 /*
- * Read the board id from the touchpad
+ * Read the board id and the "More Extended Queries" from the touchpad
  * The board id is encoded in the "QUERY MODES" response
  */
-static int synaptics_board_id(struct psmouse *psmouse)
+static int synaptics_query_modes(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
        unsigned char bid[3];
 
+       /* firmwares prior 7.5 have no board_id encoded */
+       if (SYN_ID_FULL(priv->identity) < 0x705)
+               return 0;
+
        if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid))
                return -1;
        priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1];
+
+       if (SYN_MEXT_CAP_BIT(bid[0]))
+               return synaptics_more_extended_queries(psmouse);
+
        return 0;
 }
 
@@ -346,7 +371,6 @@ static int synaptics_resolution(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
        unsigned char resp[3];
-       int i;
 
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
@@ -358,17 +382,6 @@ static int synaptics_resolution(struct psmouse *psmouse)
                }
        }
 
-       for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
-               if (psmouse_matches_pnp_id(psmouse,
-                                          min_max_pnpid_table[i].pnp_ids)) {
-                       priv->x_min = min_max_pnpid_table[i].x_min;
-                       priv->x_max = min_max_pnpid_table[i].x_max;
-                       priv->y_min = min_max_pnpid_table[i].y_min;
-                       priv->y_max = min_max_pnpid_table[i].y_max;
-                       return 0;
-               }
-       }
-
        if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
            SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
                if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
@@ -377,23 +390,69 @@ static int synaptics_resolution(struct psmouse *psmouse)
                } else {
                        priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
                        priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+                       psmouse_info(psmouse,
+                                    "queried max coordinates: x [..%d], y [..%d]\n",
+                                    priv->x_max, priv->y_max);
                }
        }
 
-       if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
-           SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
+       if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) &&
+           (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 ||
+            /*
+             * Firmware v8.1 does not report proper number of extended
+             * capabilities, but has been proven to report correct min
+             * coordinates.
+             */
+            SYN_ID_FULL(priv->identity) == 0x801)) {
                if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
                        psmouse_warn(psmouse,
                                     "device claims to have min coordinates query, but I'm not able to read it.\n");
                } else {
                        priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
                        priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+                       psmouse_info(psmouse,
+                                    "queried min coordinates: x [%d..], y [%d..]\n",
+                                    priv->x_min, priv->y_min);
                }
        }
 
        return 0;
 }
 
+/*
+ * Apply quirk(s) if the hardware matches
+ */
+
+static void synaptics_apply_quirks(struct psmouse *psmouse)
+{
+       struct synaptics_data *priv = psmouse->private;
+       int i;
+
+       for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
+               if (!psmouse_matches_pnp_id(psmouse,
+                                           min_max_pnpid_table[i].pnp_ids))
+                       continue;
+
+               if (min_max_pnpid_table[i].board_id.min != ANY_BOARD_ID &&
+                   priv->board_id < min_max_pnpid_table[i].board_id.min)
+                       continue;
+
+               if (min_max_pnpid_table[i].board_id.max != ANY_BOARD_ID &&
+                   priv->board_id > min_max_pnpid_table[i].board_id.max)
+                       continue;
+
+               priv->x_min = min_max_pnpid_table[i].x_min;
+               priv->x_max = min_max_pnpid_table[i].x_max;
+               priv->y_min = min_max_pnpid_table[i].y_min;
+               priv->y_max = min_max_pnpid_table[i].y_max;
+               psmouse_info(psmouse,
+                            "quirked min/max coordinates: x [%d..%d], y [%d..%d]\n",
+                            priv->x_min, priv->x_max,
+                            priv->y_min, priv->y_max);
+               break;
+       }
+}
+
 static int synaptics_query_hardware(struct psmouse *psmouse)
 {
        if (synaptics_identify(psmouse))
@@ -402,13 +461,15 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
                return -1;
        if (synaptics_firmware_id(psmouse))
                return -1;
-       if (synaptics_board_id(psmouse))
+       if (synaptics_query_modes(psmouse))
                return -1;
        if (synaptics_capability(psmouse))
                return -1;
        if (synaptics_resolution(psmouse))
                return -1;
 
+       synaptics_apply_quirks(psmouse);
+
        return 0;
 }
 
@@ -516,18 +577,22 @@ static int synaptics_is_pt_packet(unsigned char *buf)
        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
 }
 
-static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
+static void synaptics_pass_pt_packet(struct psmouse *psmouse,
+                                    struct serio *ptport,
+                                    unsigned char *packet)
 {
+       struct synaptics_data *priv = psmouse->private;
        struct psmouse *child = serio_get_drvdata(ptport);
 
        if (child && child->state == PSMOUSE_ACTIVATED) {
-               serio_interrupt(ptport, packet[1], 0);
+               serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0);
                serio_interrupt(ptport, packet[4], 0);
                serio_interrupt(ptport, packet[5], 0);
                if (child->pktsize == 4)
                        serio_interrupt(ptport, packet[2], 0);
-       } else
+       } else {
                serio_interrupt(ptport, packet[1], 0);
+       }
 }
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
@@ -605,6 +670,18 @@ static void synaptics_parse_agm(const unsigned char buf[],
        }
 }
 
+static void synaptics_parse_ext_buttons(const unsigned char buf[],
+                                       struct synaptics_data *priv,
+                                       struct synaptics_hw_state *hw)
+{
+       unsigned int ext_bits =
+               (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+       unsigned int ext_mask = GENMASK(ext_bits - 1, 0);
+
+       hw->ext_buttons = buf[4] & ext_mask;
+       hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits;
+}
+
 static bool is_forcepad;
 
 static int synaptics_parse_hw_state(const unsigned char buf[],
@@ -691,28 +768,9 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
                }
 
-               if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
+               if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 &&
                    ((buf[0] ^ buf[3]) & 0x02)) {
-                       switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
-                       default:
-                               /*
-                                * if nExtBtn is greater than 8 it should be
-                                * considered invalid and treated as 0
-                                */
-                               break;
-                       case 8:
-                               hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
-                       case 6:
-                               hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
-                       case 4:
-                               hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
-                       case 2:
-                               hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
-                       }
+                       synaptics_parse_ext_buttons(buf, priv, hw);
                }
        } else {
                hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
@@ -774,12 +832,54 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
        }
 }
 
+static void synaptics_report_ext_buttons(struct psmouse *psmouse,
+                                        const struct synaptics_hw_state *hw)
+{
+       struct input_dev *dev = psmouse->dev;
+       struct synaptics_data *priv = psmouse->private;
+       int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+       char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       int i;
+
+       if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+               return;
+
+       /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
+       if (SYN_ID_FULL(priv->identity) == 0x801 &&
+           !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
+               return;
+
+       if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) {
+               for (i = 0; i < ext_bits; i++) {
+                       input_report_key(dev, BTN_0 + 2 * i,
+                               hw->ext_buttons & (1 << i));
+                       input_report_key(dev, BTN_1 + 2 * i,
+                               hw->ext_buttons & (1 << (i + ext_bits)));
+               }
+               return;
+       }
+
+       /*
+        * This generation of touchpads has the trackstick buttons
+        * physically wired to the touchpad. Re-route them through
+        * the pass-through interface.
+        */
+       if (!priv->pt_port)
+               return;
+
+       /* The trackstick expects at most 3 buttons */
+       priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons)      |
+                          SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 |
+                          SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2;
+
+       synaptics_pass_pt_packet(psmouse, priv->pt_port, buf);
+}
+
 static void synaptics_report_buttons(struct psmouse *psmouse,
                                     const struct synaptics_hw_state *hw)
 {
        struct input_dev *dev = psmouse->dev;
        struct synaptics_data *priv = psmouse->private;
-       int i;
 
        input_report_key(dev, BTN_LEFT, hw->left);
        input_report_key(dev, BTN_RIGHT, hw->right);
@@ -792,8 +892,7 @@ static void synaptics_report_buttons(struct psmouse *psmouse,
                input_report_key(dev, BTN_BACK, hw->down);
        }
 
-       for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-               input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
+       synaptics_report_ext_buttons(psmouse, hw);
 }
 
 static void synaptics_report_mt_data(struct psmouse *psmouse,
@@ -813,7 +912,7 @@ static void synaptics_report_mt_data(struct psmouse *psmouse,
                pos[i].y = synaptics_invert_y(hw[i]->y);
        }
 
-       input_mt_assign_slots(dev, slot, pos, nsemi, DMAX * priv->x_res);
+       input_mt_assign_slots(dev, slot, pos, nsemi, 0);
 
        for (i = 0; i < nsemi; i++) {
                input_mt_slot(dev, slot[i]);
@@ -1014,7 +1113,8 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
                if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
                    synaptics_is_pt_packet(psmouse->packet)) {
                        if (priv->pt_port)
-                               synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
+                               synaptics_pass_pt_packet(psmouse, priv->pt_port,
+                                                        psmouse->packet);
                } else
                        synaptics_process_packet(psmouse);
 
@@ -1116,8 +1216,9 @@ static void set_input_params(struct psmouse *psmouse,
                __set_bit(BTN_BACK, dev->keybit);
        }
 
-       for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-               __set_bit(BTN_0 + i, dev->keybit);
+       if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
+               for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+                       __set_bit(BTN_0 + i, dev->keybit);
 
        __clear_bit(EV_REL, dev->evbit);
        __clear_bit(REL_X, dev->relbit);
@@ -1125,7 +1226,8 @@ static void set_input_params(struct psmouse *psmouse,
 
        if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
-               if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids))
+               if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
+                   !SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
                        __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);
                /* Clickpads report only left button */
                __clear_bit(BTN_RIGHT, dev->keybit);
index aedc3299b14e2b753c1e9d51da95b0953ea081cb..ee4bd0d12b26fa2770445a381134b62124be6741 100644 (file)
@@ -22,6 +22,7 @@
 #define SYN_QUE_EXT_CAPAB_0C           0x0c
 #define SYN_QUE_EXT_MAX_COORDS         0x0d
 #define SYN_QUE_EXT_MIN_COORDS         0x0f
+#define SYN_QUE_MEXT_CAPAB_10          0x10
 
 /* synatics modes */
 #define SYN_BIT_ABSOLUTE_MODE          (1 << 7)
@@ -53,6 +54,7 @@
 #define SYN_EXT_CAP_REQUESTS(c)                (((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)    (((ec) & 0x00f000) >> 12)
 #define SYN_CAP_PRODUCT_ID(ec)         (((ec) & 0xff0000) >> 16)
+#define SYN_MEXT_CAP_BIT(m)            ((m) & (1 << 1))
 
 /*
  * The following describes response for the 0x0c query.
 #define SYN_CAP_REDUCED_FILTERING(ex0c)        ((ex0c) & 0x000400)
 #define SYN_CAP_IMAGE_SENSOR(ex0c)     ((ex0c) & 0x000800)
 
+/*
+ * The following descibes response for the 0x10 query.
+ *
+ * byte        mask    name                    meaning
+ * ----        ----    -------                 ------------
+ * 1   0x01    ext buttons are stick   buttons exported in the extended
+ *                                     capability are actually meant to be used
+ *                                     by the tracktick (pass-through).
+ * 1   0x02    SecurePad               the touchpad is a SecurePad, so it
+ *                                     contains a built-in fingerprint reader.
+ * 1   0xe0    more ext count          how many more extented queries are
+ *                                     available after this one.
+ * 2   0xff    SecurePad width         the width of the SecurePad fingerprint
+ *                                     reader.
+ * 3   0xff    SecurePad height        the height of the SecurePad fingerprint
+ *                                     reader.
+ */
+#define SYN_CAP_EXT_BUTTONS_STICK(ex10)        ((ex10) & 0x010000)
+#define SYN_CAP_SECUREPAD(ex10)                ((ex10) & 0x020000)
+
+#define SYN_CAP_EXT_BUTTON_STICK_L(eb) (!!((eb) & 0x01))
+#define SYN_CAP_EXT_BUTTON_STICK_M(eb) (!!((eb) & 0x02))
+#define SYN_CAP_EXT_BUTTON_STICK_R(eb) (!!((eb) & 0x04))
+
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)           ((m) & (1 << 7))
 #define SYN_MODE_RATE(m)               ((m) & (1 << 6))
@@ -143,6 +169,7 @@ struct synaptics_data {
        unsigned long int capabilities;         /* Capabilities */
        unsigned long int ext_cap;              /* Extended Capabilities */
        unsigned long int ext_cap_0c;           /* Ext Caps from 0x0c query */
+       unsigned long int ext_cap_10;           /* Ext Caps from 0x10 query */
        unsigned long int identity;             /* Identification */
        unsigned int x_res, y_res;              /* X/Y resolution in units/mm */
        unsigned int x_max, y_max;              /* Max coordinates (from FW) */
@@ -156,6 +183,7 @@ struct synaptics_data {
        bool disable_gesture;                   /* disable gestures */
 
        struct serio *pt_port;                  /* Pass-through serio port */
+       unsigned char pt_buttons;               /* Pass-through buttons */
 
        /*
         * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
index 6a7447c304acc39e6edc422bf8f6533acfde93b5..358a574d9e8be4d2bfed217b0448c89fe458d8f6 100644 (file)
@@ -1609,7 +1609,7 @@ icn_setup(char *line)
        if (ints[0] > 1)
                membase = (unsigned long)ints[2];
        if (str && *str) {
-               strcpy(sid, str);
+               strlcpy(sid, str, sizeof(sid));
                icn_id = sid;
                if ((p = strchr(sid, ','))) {
                        *p++ = 0;
index 37de0173b6d2324ed15de95442df37bc5a990e16..74adcd2c967ec8680d0cfd5c9d876c93074dbe10 100644 (file)
@@ -289,9 +289,16 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
        struct request_queue *q = bdev_get_queue(where->bdev);
        unsigned short logical_block_size = queue_logical_block_size(q);
        sector_t num_sectors;
+       unsigned int uninitialized_var(special_cmd_max_sectors);
 
-       /* Reject unsupported discard requests */
-       if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) {
+       /*
+        * Reject unsupported discard and write same requests.
+        */
+       if (rw & REQ_DISCARD)
+               special_cmd_max_sectors = q->limits.max_discard_sectors;
+       else if (rw & REQ_WRITE_SAME)
+               special_cmd_max_sectors = q->limits.max_write_same_sectors;
+       if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) {
                dec_count(io, region, -EOPNOTSUPP);
                return;
        }
@@ -317,7 +324,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                store_io_and_region_in_bio(bio, io, region);
 
                if (rw & REQ_DISCARD) {
-                       num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
+                       num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
                        bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
                        remaining -= num_sectors;
                } else if (rw & REQ_WRITE_SAME) {
@@ -326,7 +333,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                         */
                        dp->get_page(dp, &page, &len, &offset);
                        bio_add_page(bio, page, logical_block_size, offset);
-                       num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
+                       num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
                        bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
 
                        offset = 0;
index 8b204ae216ab62d354c814277dc413c34f0bf9a4..f83a0f3fc3656680c7bdba2dcd4bdaaac9f2f624 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/log2.h>
 #include <linux/dm-kcopyd.h>
 
+#include "dm.h"
+
 #include "dm-exception-store.h"
 
 #define DM_MSG_PREFIX "snapshots"
@@ -290,6 +292,16 @@ struct origin {
        struct list_head snapshots;
 };
 
+/*
+ * This structure is allocated for each origin target
+ */
+struct dm_origin {
+       struct dm_dev *dev;
+       struct dm_target *ti;
+       unsigned split_boundary;
+       struct list_head hash_list;
+};
+
 /*
  * Size of the hash table for origin volumes. If we make this
  * the size of the minors list then it should be nearly perfect
@@ -297,6 +309,7 @@ struct origin {
 #define ORIGIN_HASH_SIZE 256
 #define ORIGIN_MASK      0xFF
 static struct list_head *_origins;
+static struct list_head *_dm_origins;
 static struct rw_semaphore _origins_lock;
 
 static DECLARE_WAIT_QUEUE_HEAD(_pending_exceptions_done);
@@ -310,12 +323,22 @@ static int init_origin_hash(void)
        _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
                           GFP_KERNEL);
        if (!_origins) {
-               DMERR("unable to allocate memory");
+               DMERR("unable to allocate memory for _origins");
                return -ENOMEM;
        }
-
        for (i = 0; i < ORIGIN_HASH_SIZE; i++)
                INIT_LIST_HEAD(_origins + i);
+
+       _dm_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
+                             GFP_KERNEL);
+       if (!_dm_origins) {
+               DMERR("unable to allocate memory for _dm_origins");
+               kfree(_origins);
+               return -ENOMEM;
+       }
+       for (i = 0; i < ORIGIN_HASH_SIZE; i++)
+               INIT_LIST_HEAD(_dm_origins + i);
+
        init_rwsem(&_origins_lock);
 
        return 0;
@@ -324,6 +347,7 @@ static int init_origin_hash(void)
 static void exit_origin_hash(void)
 {
        kfree(_origins);
+       kfree(_dm_origins);
 }
 
 static unsigned origin_hash(struct block_device *bdev)
@@ -350,6 +374,30 @@ static void __insert_origin(struct origin *o)
        list_add_tail(&o->hash_list, sl);
 }
 
+static struct dm_origin *__lookup_dm_origin(struct block_device *origin)
+{
+       struct list_head *ol;
+       struct dm_origin *o;
+
+       ol = &_dm_origins[origin_hash(origin)];
+       list_for_each_entry (o, ol, hash_list)
+               if (bdev_equal(o->dev->bdev, origin))
+                       return o;
+
+       return NULL;
+}
+
+static void __insert_dm_origin(struct dm_origin *o)
+{
+       struct list_head *sl = &_dm_origins[origin_hash(o->dev->bdev)];
+       list_add_tail(&o->hash_list, sl);
+}
+
+static void __remove_dm_origin(struct dm_origin *o)
+{
+       list_del(&o->hash_list);
+}
+
 /*
  * _origins_lock must be held when calling this function.
  * Returns number of snapshots registered using the supplied cow device, plus:
@@ -1840,9 +1888,40 @@ static int snapshot_preresume(struct dm_target *ti)
 static void snapshot_resume(struct dm_target *ti)
 {
        struct dm_snapshot *s = ti->private;
-       struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
+       struct dm_snapshot *snap_src = NULL, *snap_dest = NULL, *snap_merging = NULL;
+       struct dm_origin *o;
+       struct mapped_device *origin_md = NULL;
+       bool must_restart_merging = false;
 
        down_read(&_origins_lock);
+
+       o = __lookup_dm_origin(s->origin->bdev);
+       if (o)
+               origin_md = dm_table_get_md(o->ti->table);
+       if (!origin_md) {
+               (void) __find_snapshots_sharing_cow(s, NULL, NULL, &snap_merging);
+               if (snap_merging)
+                       origin_md = dm_table_get_md(snap_merging->ti->table);
+       }
+       if (origin_md == dm_table_get_md(ti->table))
+               origin_md = NULL;
+       if (origin_md) {
+               if (dm_hold(origin_md))
+                       origin_md = NULL;
+       }
+
+       up_read(&_origins_lock);
+
+       if (origin_md) {
+               dm_internal_suspend_fast(origin_md);
+               if (snap_merging && test_bit(RUNNING_MERGE, &snap_merging->state_bits)) {
+                       must_restart_merging = true;
+                       stop_merge(snap_merging);
+               }
+       }
+
+       down_read(&_origins_lock);
+
        (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
        if (snap_src && snap_dest) {
                down_write(&snap_src->lock);
@@ -1851,8 +1930,16 @@ static void snapshot_resume(struct dm_target *ti)
                up_write(&snap_dest->lock);
                up_write(&snap_src->lock);
        }
+
        up_read(&_origins_lock);
 
+       if (origin_md) {
+               if (must_restart_merging)
+                       start_merge(snap_merging);
+               dm_internal_resume_fast(origin_md);
+               dm_put(origin_md);
+       }
+
        /* Now we have correct chunk size, reregister */
        reregister_snapshot(s);
 
@@ -2133,11 +2220,6 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
  * Origin: maps a linear range of a device, with hooks for snapshotting.
  */
 
-struct dm_origin {
-       struct dm_dev *dev;
-       unsigned split_boundary;
-};
-
 /*
  * Construct an origin mapping: <dev_path>
  * The context for an origin is merely a 'struct dm_dev *'
@@ -2166,6 +2248,7 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad_open;
        }
 
+       o->ti = ti;
        ti->private = o;
        ti->num_flush_bios = 1;
 
@@ -2180,6 +2263,7 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 static void origin_dtr(struct dm_target *ti)
 {
        struct dm_origin *o = ti->private;
+
        dm_put_device(ti, o->dev);
        kfree(o);
 }
@@ -2216,6 +2300,19 @@ static void origin_resume(struct dm_target *ti)
        struct dm_origin *o = ti->private;
 
        o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
+
+       down_write(&_origins_lock);
+       __insert_dm_origin(o);
+       up_write(&_origins_lock);
+}
+
+static void origin_postsuspend(struct dm_target *ti)
+{
+       struct dm_origin *o = ti->private;
+
+       down_write(&_origins_lock);
+       __remove_dm_origin(o);
+       up_write(&_origins_lock);
 }
 
 static void origin_status(struct dm_target *ti, status_type_t type,
@@ -2258,12 +2355,13 @@ static int origin_iterate_devices(struct dm_target *ti,
 
 static struct target_type origin_target = {
        .name    = "snapshot-origin",
-       .version = {1, 8, 1},
+       .version = {1, 9, 0},
        .module  = THIS_MODULE,
        .ctr     = origin_ctr,
        .dtr     = origin_dtr,
        .map     = origin_map,
        .resume  = origin_resume,
+       .postsuspend = origin_postsuspend,
        .status  = origin_status,
        .merge   = origin_merge,
        .iterate_devices = origin_iterate_devices,
@@ -2271,7 +2369,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 12, 0},
+       .version = {1, 13, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2285,7 +2383,7 @@ static struct target_type snapshot_target = {
 
 static struct target_type merge_target = {
        .name    = dm_snapshot_merge_target_name,
-       .version = {1, 2, 0},
+       .version = {1, 3, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
index 654773cb1eeea23b39db0fcf0e6fb00d91d9476d..921aafd12aee6754c373fbbd0df8941219b5c1eb 100644 (file)
@@ -2358,17 +2358,6 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
 
        case -ENODATA:
-               if (get_pool_mode(tc->pool) == PM_READ_ONLY) {
-                       /*
-                        * This block isn't provisioned, and we have no way
-                        * of doing so.
-                        */
-                       handle_unserviceable_bio(tc->pool, bio);
-                       cell_defer_no_holder(tc, virt_cell);
-                       return DM_MAPIO_SUBMITTED;
-               }
-               /* fall through */
-
        case -EWOULDBLOCK:
                thin_defer_cell(tc, virt_cell);
                return DM_MAPIO_SUBMITTED;
index 73f28802dc7abc3cb46dc38c8ef6fb5bb521e66b..9b641b38b857106000c6645035e7490c943f9233 100644 (file)
@@ -2616,6 +2616,19 @@ void dm_get(struct mapped_device *md)
        BUG_ON(test_bit(DMF_FREEING, &md->flags));
 }
 
+int dm_hold(struct mapped_device *md)
+{
+       spin_lock(&_minor_lock);
+       if (test_bit(DMF_FREEING, &md->flags)) {
+               spin_unlock(&_minor_lock);
+               return -EBUSY;
+       }
+       dm_get(md);
+       spin_unlock(&_minor_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dm_hold);
+
 const char *dm_device_name(struct mapped_device *md)
 {
        return md->name;
@@ -2638,10 +2651,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
        if (dm_request_based(md))
                flush_kthread_worker(&md->kworker);
 
+       /*
+        * Take suspend_lock so that presuspend and postsuspend methods
+        * do not race with internal suspend.
+        */
+       mutex_lock(&md->suspend_lock);
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
                dm_table_postsuspend_targets(map);
        }
+       mutex_unlock(&md->suspend_lock);
 
        /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
        dm_put_live_table(md, srcu_idx);
@@ -3115,6 +3134,7 @@ void dm_internal_suspend_fast(struct mapped_device *md)
        flush_workqueue(md->wq);
        dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
 }
+EXPORT_SYMBOL_GPL(dm_internal_suspend_fast);
 
 void dm_internal_resume_fast(struct mapped_device *md)
 {
@@ -3126,6 +3146,7 @@ void dm_internal_resume_fast(struct mapped_device *md)
 done:
        mutex_unlock(&md->suspend_lock);
 }
+EXPORT_SYMBOL_GPL(dm_internal_resume_fast);
 
 /*-----------------------------------------------------------------
  * Event notification.
index cadf9cc02b2561ade72800e9a0986d7e23b09163..717daad71fb101b2b97efd03b1bb41d8b35ecfe7 100644 (file)
@@ -5080,7 +5080,8 @@ int md_run(struct mddev *mddev)
        }
        if (err) {
                mddev_detach(mddev);
-               pers->free(mddev, mddev->private);
+               if (mddev->private)
+                       pers->free(mddev, mddev->private);
                module_put(pers->owner);
                bitmap_destroy(mddev);
                return err;
index a13f738a7b39f60fa340dec21612cf25b99570a7..3ed9f42ddca65e10351a1a453f16383e63c52634 100644 (file)
@@ -467,8 +467,6 @@ static int raid0_run(struct mddev *mddev)
        dump_zones(mddev);
 
        ret = md_integrity_register(mddev);
-       if (ret)
-               raid0_free(mddev, conf);
 
        return ret;
 }
index f38ec424872e362b934aaa6edd2fb21358bcb326..5615522f8d628b0f9d4b43d240d18d7bad02c835 100644 (file)
@@ -739,7 +739,7 @@ static int __init kempld_init(void)
                for (id = kempld_dmi_table;
                     id->matches[0].slot != DMI_NONE; id++)
                        if (strstr(id->ident, force_device_id))
-                               if (id->callback && id->callback(id))
+                               if (id->callback && !id->callback(id))
                                        break;
                if (id->matches[0].slot == DMI_NONE)
                        return -ENODEV;
index ede50244f265b14d950fba0448652960304fa971..dbd907d7170ebe990cb63fede374624ea03b6fd4 100644 (file)
@@ -196,18 +196,27 @@ EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
 int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
 {
        u16 value;
+       u8 *buf;
+       int ret;
 
        if (!data)
                return -EINVAL;
-       *data = 0;
+
+       buf = kzalloc(sizeof(u8), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
        value = swab16(addr);
 
-       return usb_control_msg(ucr->pusb_dev,
+       ret = usb_control_msg(ucr->pusb_dev,
                        usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, 0, data, 1, 100);
+                       value, 0, buf, 1, 100);
+       *data = *buf;
+
+       kfree(buf);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
 
@@ -288,18 +297,27 @@ static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
 int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
 {
        int ret;
+       u16 *buf;
 
        if (!status)
                return -EINVAL;
 
-       if (polling_pipe == 0)
+       if (polling_pipe == 0) {
+               buf = kzalloc(sizeof(u16), GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+
                ret = usb_control_msg(ucr->pusb_dev,
                                usb_rcvctrlpipe(ucr->pusb_dev, 0),
                                RTSX_USB_REQ_POLL,
                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0, 0, status, 2, 100);
-       else
+                               0, 0, buf, 2, 100);
+               *status = *buf;
+
+               kfree(buf);
+       } else {
                ret = rtsx_usb_get_status_with_bulk(ucr, status);
+       }
 
        /* usb_control_msg may return positive when success */
        if (ret < 0)
index e9f1d8d8461353cd88831c154ae6dc43fe994772..c53f14a7ce546533c300313a54078e1bad327bf9 100644 (file)
@@ -124,7 +124,7 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev)
                    PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) {
                        ret = PTR_ERR(pwrseq->reset_gpios[i]);
 
-                       while (--i)
+                       while (i--)
                                gpiod_put(pwrseq->reset_gpios[i]);
 
                        goto clk_put;
index da4c79259f67f3e2bd63a62570845eb10c89e989..16e34b37d134cee7797651f4ad8586db8d11faa1 100644 (file)
@@ -425,9 +425,10 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
                                        ubi_warn(ubi, "corrupted VID header at PEB %d, LEB %d:%d",
                                                 pnum, vol_id, lnum);
                                        err = -EBADMSG;
-                               } else
+                               } else {
                                        err = -EINVAL;
                                        ubi_ro_mode(ubi);
+                               }
                        }
                        goto out_free;
                } else if (err == UBI_IO_BITFLIPS)
index 98d73aab52fe962888a675d1293ae69f9731f7d0..58808f6514520c869631b356d6476f8cbc060a14 100644 (file)
@@ -131,7 +131,7 @@ config CAN_RCAR
 
 config CAN_XILINXCAN
        tristate "Xilinx CAN"
-       depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
+       depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST
        depends on COMMON_CLK && HAS_IOMEM
        ---help---
          Xilinx CAN driver. This driver supports both soft AXI CAN IP and
index a316fa4b91ab20aa0205b5fde1740784495ce6ca..e97a08ce0b90c298577fed09c96dc7a711076e5e 100644 (file)
@@ -14,6 +14,7 @@
  * Copyright (C) 2015 Valeo S.A.
  */
 
+#include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/completion.h>
 #include <linux/module.h>
@@ -467,10 +468,11 @@ struct kvaser_usb {
 struct kvaser_usb_net_priv {
        struct can_priv can;
 
-       atomic_t active_tx_urbs;
-       struct usb_anchor tx_submitted;
+       spinlock_t tx_contexts_lock;
+       int active_tx_contexts;
        struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
 
+       struct usb_anchor tx_submitted;
        struct completion start_comp, stop_comp;
 
        struct kvaser_usb *dev;
@@ -694,6 +696,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
        struct kvaser_usb_net_priv *priv;
        struct sk_buff *skb;
        struct can_frame *cf;
+       unsigned long flags;
        u8 channel, tid;
 
        channel = msg->u.tx_acknowledge_header.channel;
@@ -737,12 +740,15 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
 
        stats->tx_packets++;
        stats->tx_bytes += context->dlc;
-       can_get_echo_skb(priv->netdev, context->echo_index);
 
-       context->echo_index = MAX_TX_URBS;
-       atomic_dec(&priv->active_tx_urbs);
+       spin_lock_irqsave(&priv->tx_contexts_lock, flags);
 
+       can_get_echo_skb(priv->netdev, context->echo_index);
+       context->echo_index = MAX_TX_URBS;
+       --priv->active_tx_contexts;
        netif_wake_queue(priv->netdev);
+
+       spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
 }
 
 static void kvaser_usb_simple_msg_callback(struct urb *urb)
@@ -803,17 +809,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
        return 0;
 }
 
-static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
-{
-       int i;
-
-       usb_kill_anchored_urbs(&priv->tx_submitted);
-       atomic_set(&priv->active_tx_urbs, 0);
-
-       for (i = 0; i < MAX_TX_URBS; i++)
-               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
-}
-
 static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
                                                 const struct kvaser_usb_error_summary *es,
                                                 struct can_frame *cf)
@@ -1515,6 +1510,24 @@ static int kvaser_usb_open(struct net_device *netdev)
        return err;
 }
 
+static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv)
+{
+       int i;
+
+       priv->active_tx_contexts = 0;
+       for (i = 0; i < MAX_TX_URBS; i++)
+               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+/* This method might sleep. Do not call it in the atomic context
+ * of URB completions.
+ */
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+       usb_kill_anchored_urbs(&priv->tx_submitted);
+       kvaser_usb_reset_tx_urb_contexts(priv);
+}
+
 static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
 {
        int i;
@@ -1634,6 +1647,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        struct kvaser_msg *msg;
        int i, err, ret = NETDEV_TX_OK;
        u8 *msg_tx_can_flags = NULL;            /* GCC */
+       unsigned long flags;
 
        if (can_dropped_invalid_skb(netdev, skb))
                return NETDEV_TX_OK;
@@ -1687,12 +1701,21 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        if (cf->can_id & CAN_RTR_FLAG)
                *msg_tx_can_flags |= MSG_FLAG_REMOTE_FRAME;
 
+       spin_lock_irqsave(&priv->tx_contexts_lock, flags);
        for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
                if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
                        context = &priv->tx_contexts[i];
+
+                       context->echo_index = i;
+                       can_put_echo_skb(skb, netdev, context->echo_index);
+                       ++priv->active_tx_contexts;
+                       if (priv->active_tx_contexts >= MAX_TX_URBS)
+                               netif_stop_queue(netdev);
+
                        break;
                }
        }
+       spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
 
        /* This should never happen; it implies a flow control bug */
        if (!context) {
@@ -1704,7 +1727,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        }
 
        context->priv = priv;
-       context->echo_index = i;
        context->dlc = cf->can_dlc;
 
        msg->u.tx_can.tid = context->echo_index;
@@ -1716,18 +1738,17 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
                          kvaser_usb_write_bulk_callback, context);
        usb_anchor_urb(urb, &priv->tx_submitted);
 
-       can_put_echo_skb(skb, netdev, context->echo_index);
-
-       atomic_inc(&priv->active_tx_urbs);
-
-       if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
-               netif_stop_queue(netdev);
-
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (unlikely(err)) {
+               spin_lock_irqsave(&priv->tx_contexts_lock, flags);
+
                can_free_echo_skb(netdev, context->echo_index);
+               context->echo_index = MAX_TX_URBS;
+               --priv->active_tx_contexts;
+               netif_wake_queue(netdev);
+
+               spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
 
-               atomic_dec(&priv->active_tx_urbs);
                usb_unanchor_urb(urb);
 
                stats->tx_dropped++;
@@ -1854,7 +1875,7 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
        struct kvaser_usb *dev = usb_get_intfdata(intf);
        struct net_device *netdev;
        struct kvaser_usb_net_priv *priv;
-       int i, err;
+       int err;
 
        err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel);
        if (err)
@@ -1868,19 +1889,17 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
 
        priv = netdev_priv(netdev);
 
+       init_usb_anchor(&priv->tx_submitted);
        init_completion(&priv->start_comp);
        init_completion(&priv->stop_comp);
 
-       init_usb_anchor(&priv->tx_submitted);
-       atomic_set(&priv->active_tx_urbs, 0);
-
-       for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
-               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
-
        priv->dev = dev;
        priv->netdev = netdev;
        priv->channel = channel;
 
+       spin_lock_init(&priv->tx_contexts_lock);
+       kvaser_usb_reset_tx_urb_contexts(priv);
+
        priv->can.state = CAN_STATE_STOPPED;
        priv->can.clock.freq = CAN_USB_CLOCK;
        priv->can.bittiming_const = &kvaser_usb_bittiming_const;
index 11d6e6561df159c3dc9dff28fc504e945a77f47b..15a8190a6f75f61908f5ba968d37451e2f982897 100644 (file)
@@ -1543,7 +1543,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 {
        struct pcnet32_private *lp;
        int i, media;
-       int fdx, mii, fset, dxsuflo;
+       int fdx, mii, fset, dxsuflo, sram;
        int chip_version;
        char *chipname;
        struct net_device *dev;
@@ -1580,7 +1580,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        }
 
        /* initialize variables */
-       fdx = mii = fset = dxsuflo = 0;
+       fdx = mii = fset = dxsuflo = sram = 0;
        chip_version = (chip_version >> 12) & 0xffff;
 
        switch (chip_version) {
@@ -1613,6 +1613,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                chipname = "PCnet/FAST III 79C973";     /* PCI */
                fdx = 1;
                mii = 1;
+               sram = 1;
                break;
        case 0x2626:
                chipname = "PCnet/Home 79C978"; /* PCI */
@@ -1636,6 +1637,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                chipname = "PCnet/FAST III 79C975";     /* PCI */
                fdx = 1;
                mii = 1;
+               sram = 1;
                break;
        case 0x2628:
                chipname = "PCnet/PRO 79C976";
@@ -1664,6 +1666,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                dxsuflo = 1;
        }
 
+       /*
+        * The Am79C973/Am79C975 controllers come with 12K of SRAM
+        * which we can use for the Tx/Rx buffers but most importantly,
+        * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid
+        * Tx fifo underflows.
+        */
+       if (sram) {
+               /*
+                * The SRAM is being configured in two steps. First we
+                * set the SRAM size in the BCR25:SRAM_SIZE bits. According
+                * to the datasheet, each bit corresponds to a 512-byte
+                * page so we can have at most 24 pages. The SRAM_SIZE
+                * holds the value of the upper 8 bits of the 16-bit SRAM size.
+                * The low 8-bits start at 0x00 and end at 0xff. So the
+                * address range is from 0x0000 up to 0x17ff. Therefore,
+                * the SRAM_SIZE is set to 0x17. The next step is to set
+                * the BCR26:SRAM_BND midway through so the Tx and Rx
+                * buffers can share the SRAM equally.
+                */
+               a->write_bcr(ioaddr, 25, 0x17);
+               a->write_bcr(ioaddr, 26, 0xc);
+               /* And finally enable the NOUFLO bit */
+               a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11));
+       }
+
        dev = alloc_etherdev(sizeof(*lp));
        if (!dev) {
                ret = -ENOMEM;
index bef750a090276a8dd1131e0e5696129d2b996053..996e215fc3246c4fba6f1714ddceb69b88f179be 100644 (file)
@@ -12769,7 +12769,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
                NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
                NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO |
                NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
-       if (!CHIP_IS_E1x(bp)) {
+       if (!chip_is_e1x) {
                dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
                                    NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
                dev->hw_enc_features =
index 853c38997c822aa8ab48a6bca5e0e88ae075146d..1abdfa123c6cf8d42a4788400539b40b05ed84eb 100644 (file)
@@ -1120,7 +1120,7 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
                }
 
                /* Installed successfully, update the cached header too. */
-               memcpy(card_fw, fs_fw, sizeof(*card_fw));
+               *card_fw = *fs_fw;
                card_fw_usable = 1;
                *reset = 0;     /* already reset as part of load_fw */
        }
index 3b42556f7f8d66929f1435445df06072c65ae6aa..ed41559bae771b8d58e49f21a46f7a79d9f20cac 100644 (file)
@@ -589,7 +589,7 @@ static void tulip_tx_timeout(struct net_device *dev)
                               (unsigned int)tp->rx_ring[i].buffer1,
                               (unsigned int)tp->rx_ring[i].buffer2,
                               buf[0], buf[1], buf[2]);
-                       for (j = 0; buf[j] != 0xee && j < 1600; j++)
+                       for (j = 0; ((j < 1600) && buf[j] != 0xee); j++)
                                if (j < 100)
                                        pr_cont(" %02x", buf[j]);
                        pr_cont(" j=%d\n", j);
index 27de37aa90afe12b2d564d87c9b13246160d39aa..27b9fe99a9bdfa4eddb70aaa9749eaef6bdd3518 100644 (file)
@@ -354,6 +354,7 @@ struct be_vf_cfg {
        u16 vlan_tag;
        u32 tx_rate;
        u32 plink_tracking;
+       u32 privileges;
 };
 
 enum vf_state {
@@ -423,6 +424,7 @@ struct be_adapter {
 
        u8 __iomem *csr;        /* CSR BAR used only for BE2/3 */
        u8 __iomem *db;         /* Door Bell */
+       u8 __iomem *pcicfg;     /* On SH,BEx only. Shadow of PCI config space */
 
        struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
        struct be_dma_mem mbox_mem;
index 36916cfa70f9a7d31f36b7d80135e61f854a499a..7f05f309e93596778851fb280fa4c8bd068828c3 100644 (file)
@@ -1902,15 +1902,11 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
 {
        int num_eqs, i = 0;
 
-       if (lancer_chip(adapter) && num > 8) {
-               while (num) {
-                       num_eqs = min(num, 8);
-                       __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
-                       i += num_eqs;
-                       num -= num_eqs;
-               }
-       } else {
-               __be_cmd_modify_eqd(adapter, set_eqd, num);
+       while (num) {
+               num_eqs = min(num, 8);
+               __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
+               i += num_eqs;
+               num -= num_eqs;
        }
 
        return 0;
@@ -1918,7 +1914,7 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
 
 /* Uses sycnhronous mcc */
 int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
-                      u32 num)
+                      u32 num, u32 domain)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_vlan_config *req;
@@ -1936,6 +1932,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                               OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
                               wrb, NULL);
+       req->hdr.domain = domain;
 
        req->interface_id = if_id;
        req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
index db761e8e42a3224486ced01238f9fb6b61ad3579..a7634a3f052ac02786baa7e63e764d86262720a9 100644 (file)
@@ -2256,7 +2256,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
 int be_cmd_get_fw_ver(struct be_adapter *adapter);
 int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num);
 int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
-                      u32 num);
+                      u32 num, u32 domain);
 int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
 int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc);
 int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc);
index 0a816859aca507c3e762aeebbf6d0601e3529aec..e6b790f0d9dc1ebfe6103a1549e84cf058522027 100644 (file)
@@ -1171,7 +1171,7 @@ static int be_vid_config(struct be_adapter *adapter)
        for_each_set_bit(i, adapter->vids, VLAN_N_VID)
                vids[num++] = cpu_to_le16(i);
 
-       status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num);
+       status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num, 0);
        if (status) {
                dev_err(dev, "Setting HW VLAN filtering failed\n");
                /* Set to VLAN promisc mode as setting VLAN filter failed */
@@ -1380,11 +1380,67 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
        return 0;
 }
 
+static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan)
+{
+       struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
+       u16 vids[BE_NUM_VLANS_SUPPORTED];
+       int vf_if_id = vf_cfg->if_handle;
+       int status;
+
+       /* Enable Transparent VLAN Tagging */
+       status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0);
+       if (status)
+               return status;
+
+       /* Clear pre-programmed VLAN filters on VF if any, if TVT is enabled */
+       vids[0] = 0;
+       status = be_cmd_vlan_config(adapter, vf_if_id, vids, 1, vf + 1);
+       if (!status)
+               dev_info(&adapter->pdev->dev,
+                        "Cleared guest VLANs on VF%d", vf);
+
+       /* After TVT is enabled, disallow VFs to program VLAN filters */
+       if (vf_cfg->privileges & BE_PRIV_FILTMGMT) {
+               status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges &
+                                                 ~BE_PRIV_FILTMGMT, vf + 1);
+               if (!status)
+                       vf_cfg->privileges &= ~BE_PRIV_FILTMGMT;
+       }
+       return 0;
+}
+
+static int be_clear_vf_tvt(struct be_adapter *adapter, int vf)
+{
+       struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
+       struct device *dev = &adapter->pdev->dev;
+       int status;
+
+       /* Reset Transparent VLAN Tagging. */
+       status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1,
+                                      vf_cfg->if_handle, 0);
+       if (status)
+               return status;
+
+       /* Allow VFs to program VLAN filtering */
+       if (!(vf_cfg->privileges & BE_PRIV_FILTMGMT)) {
+               status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges |
+                                                 BE_PRIV_FILTMGMT, vf + 1);
+               if (!status) {
+                       vf_cfg->privileges |= BE_PRIV_FILTMGMT;
+                       dev_info(dev, "VF%d: FILTMGMT priv enabled", vf);
+               }
+       }
+
+       dev_info(dev,
+                "Disable/re-enable i/f in VM to clear Transparent VLAN tag");
+       return 0;
+}
+
 static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
-       int status = 0;
+       int status;
 
        if (!sriov_enabled(adapter))
                return -EPERM;
@@ -1394,24 +1450,19 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
 
        if (vlan || qos) {
                vlan |= qos << VLAN_PRIO_SHIFT;
-               if (vf_cfg->vlan_tag != vlan)
-                       status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
-                                                      vf_cfg->if_handle, 0);
+               status = be_set_vf_tvt(adapter, vf, vlan);
        } else {
-               /* Reset Transparent Vlan Tagging. */
-               status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID,
-                                              vf + 1, vf_cfg->if_handle, 0);
+               status = be_clear_vf_tvt(adapter, vf);
        }
 
        if (status) {
                dev_err(&adapter->pdev->dev,
-                       "VLAN %d config on VF %d failed : %#x\n", vlan,
-                       vf, status);
+                       "VLAN %d config on VF %d failed : %#x\n", vlan, vf,
+                       status);
                return be_cmd_status(status);
        }
 
        vf_cfg->vlan_tag = vlan;
-
        return 0;
 }
 
@@ -2772,14 +2823,12 @@ void be_detect_error(struct be_adapter *adapter)
                        }
                }
        } else {
-               pci_read_config_dword(adapter->pdev,
-                                     PCICFG_UE_STATUS_LOW, &ue_lo);
-               pci_read_config_dword(adapter->pdev,
-                                     PCICFG_UE_STATUS_HIGH, &ue_hi);
-               pci_read_config_dword(adapter->pdev,
-                                     PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask);
-               pci_read_config_dword(adapter->pdev,
-                                     PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask);
+               ue_lo = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_LOW);
+               ue_hi = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_HIGH);
+               ue_lo_mask = ioread32(adapter->pcicfg +
+                                     PCICFG_UE_STATUS_LOW_MASK);
+               ue_hi_mask = ioread32(adapter->pcicfg +
+                                     PCICFG_UE_STATUS_HI_MASK);
 
                ue_lo = (ue_lo & ~ue_lo_mask);
                ue_hi = (ue_hi & ~ue_hi_mask);
@@ -3339,7 +3388,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
                        u32 cap_flags, u32 vf)
 {
        u32 en_flags;
-       int status;
 
        en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                   BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
@@ -3347,10 +3395,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
 
        en_flags &= cap_flags;
 
-       status = be_cmd_if_create(adapter, cap_flags, en_flags,
-                                 if_handle, vf);
-
-       return status;
+       return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
 }
 
 static int be_vfs_if_create(struct be_adapter *adapter)
@@ -3368,8 +3413,13 @@ static int be_vfs_if_create(struct be_adapter *adapter)
                if (!BE3_chip(adapter)) {
                        status = be_cmd_get_profile_config(adapter, &res,
                                                           vf + 1);
-                       if (!status)
+                       if (!status) {
                                cap_flags = res.if_cap_flags;
+                               /* Prevent VFs from enabling VLAN promiscuous
+                                * mode
+                                */
+                               cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+                       }
                }
 
                status = be_if_create(adapter, &vf_cfg->if_handle,
@@ -3403,7 +3453,6 @@ static int be_vf_setup(struct be_adapter *adapter)
        struct device *dev = &adapter->pdev->dev;
        struct be_vf_cfg *vf_cfg;
        int status, old_vfs, vf;
-       u32 privileges;
 
        old_vfs = pci_num_vf(adapter->pdev);
 
@@ -3433,15 +3482,18 @@ static int be_vf_setup(struct be_adapter *adapter)
 
        for_all_vfs(adapter, vf_cfg, vf) {
                /* Allow VFs to programs MAC/VLAN filters */
-               status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1);
-               if (!status && !(privileges & BE_PRIV_FILTMGMT)) {
+               status = be_cmd_get_fn_privileges(adapter, &vf_cfg->privileges,
+                                                 vf + 1);
+               if (!status && !(vf_cfg->privileges & BE_PRIV_FILTMGMT)) {
                        status = be_cmd_set_fn_privileges(adapter,
-                                                         privileges |
+                                                         vf_cfg->privileges |
                                                          BE_PRIV_FILTMGMT,
                                                          vf + 1);
-                       if (!status)
+                       if (!status) {
+                               vf_cfg->privileges |= BE_PRIV_FILTMGMT;
                                dev_info(dev, "VF%d has FILTMGMT privilege\n",
                                         vf);
+                       }
                }
 
                /* Allow full available bandwidth */
@@ -4820,24 +4872,37 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter)
 
 static int be_map_pci_bars(struct be_adapter *adapter)
 {
+       struct pci_dev *pdev = adapter->pdev;
        u8 __iomem *addr;
 
        if (BEx_chip(adapter) && be_physfn(adapter)) {
-               adapter->csr = pci_iomap(adapter->pdev, 2, 0);
+               adapter->csr = pci_iomap(pdev, 2, 0);
                if (!adapter->csr)
                        return -ENOMEM;
        }
 
-       addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
+       addr = pci_iomap(pdev, db_bar(adapter), 0);
        if (!addr)
                goto pci_map_err;
        adapter->db = addr;
 
+       if (skyhawk_chip(adapter) || BEx_chip(adapter)) {
+               if (be_physfn(adapter)) {
+                       /* PCICFG is the 2nd BAR in BE2 */
+                       addr = pci_iomap(pdev, BE2_chip(adapter) ? 1 : 0, 0);
+                       if (!addr)
+                               goto pci_map_err;
+                       adapter->pcicfg = addr;
+               } else {
+                       adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
+               }
+       }
+
        be_roce_map_pci_bars(adapter);
        return 0;
 
 pci_map_err:
-       dev_err(&adapter->pdev->dev, "Error in mapping PCI BARs\n");
+       dev_err(&pdev->dev, "Error in mapping PCI BARs\n");
        be_unmap_pci_bars(adapter);
        return -ENOMEM;
 }
index 99492b7e3713bbd04aaacffb8aa1a926b1ce9ef9..78e1ce09b1ab1deadad177472593e020a8f9d3c2 100644 (file)
@@ -1189,13 +1189,12 @@ static void
 fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 {
        struct  fec_enet_private *fep;
-       struct bufdesc *bdp, *bdp_t;
+       struct bufdesc *bdp;
        unsigned short status;
        struct  sk_buff *skb;
        struct fec_enet_priv_tx_q *txq;
        struct netdev_queue *nq;
        int     index = 0;
-       int     i, bdnum;
        int     entries_free;
 
        fep = netdev_priv(ndev);
@@ -1216,29 +1215,18 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                if (bdp == txq->cur_tx)
                        break;
 
-               bdp_t = bdp;
-               bdnum = 1;
-               index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep);
-               skb = txq->tx_skbuff[index];
-               while (!skb) {
-                       bdp_t = fec_enet_get_nextdesc(bdp_t, fep, queue_id);
-                       index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep);
-                       skb = txq->tx_skbuff[index];
-                       bdnum++;
-               }
-               if (skb_shinfo(skb)->nr_frags &&
-                   (status = bdp_t->cbd_sc) & BD_ENET_TX_READY)
-                       break;
+               index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
 
-               for (i = 0; i < bdnum; i++) {
-                       if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
-                               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-                                                bdp->cbd_datlen, DMA_TO_DEVICE);
-                       bdp->cbd_bufaddr = 0;
-                       if (i < bdnum - 1)
-                               bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
-               }
+               skb = txq->tx_skbuff[index];
                txq->tx_skbuff[index] = NULL;
+               if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
+                       dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+                                       bdp->cbd_datlen, DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
+               if (!skb) {
+                       bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+                       continue;
+               }
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1479,8 +1467,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 
                        vlan_packet_rcvd = true;
 
-                       skb_copy_to_linear_data_offset(skb, VLAN_HLEN,
-                                                      data, (2 * ETH_ALEN));
+                       memmove(skb->data + VLAN_HLEN, data, ETH_ALEN * 2);
                        skb_pull(skb, VLAN_HLEN);
                }
 
index 072426a72745a8fd984fa26dac7922a89ba189bb..cd7675ac5bf9ed8b8658996d2d27190c6b20245f 100644 (file)
@@ -1136,6 +1136,8 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
        ibmveth_replenish_task(adapter);
 
        if (frames_processed < budget) {
+               napi_complete(napi);
+
                /* We think we are done - reenable interrupts,
                 * then check once more to make sure we are done.
                 */
@@ -1144,8 +1146,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
 
                BUG_ON(lpar_rc != H_SUCCESS);
 
-               napi_complete(napi);
-
                if (ibmveth_rxq_pending_buffer(adapter) &&
                    napi_reschedule(napi)) {
                        lpar_rc = h_vio_signal(adapter->vdev->unit_address,
index 2a210c4efb895728ec6ad12eaef9ec8f9ff7fd08..ebce5bb24df98b77eec38a1fc6c720987768934b 100644 (file)
@@ -1698,8 +1698,6 @@ int mlx4_en_start_port(struct net_device *dev)
        /* Schedule multicast task to populate multicast list */
        queue_work(mdev->workqueue, &priv->rx_mode_task);
 
-       mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
-
 #ifdef CONFIG_MLX4_EN_VXLAN
        if (priv->mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
                vxlan_get_rx_port(dev);
@@ -2853,6 +2851,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                queue_delayed_work(mdev->workqueue, &priv->service_task,
                                   SERVICE_TASK_DELAY);
 
+       mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
+
        return 0;
 
 out:
index 2a8268e6be15d0b8682b8ad47bb4bb4ac071b243..ebbe244e80dde55068d924905e08d1d631821811 100644 (file)
@@ -453,7 +453,7 @@ struct mlx4_en_port_stats {
        unsigned long rx_chksum_none;
        unsigned long rx_chksum_complete;
        unsigned long tx_chksum_offload;
-#define NUM_PORT_STATS         9
+#define NUM_PORT_STATS         10
 };
 
 struct mlx4_en_perf_stats {
index 5d093dc0f5f598cf1f6b98fd336e329bf5c78922..8678e39aba08cfe0d5b3b0578348b258812ec4ec 100644 (file)
@@ -2248,10 +2248,9 @@ static int smc_drv_probe(struct platform_device *pdev)
        const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
-       struct resource *res;
+       struct resource *res, *ires;
        unsigned int __iomem *addr;
        unsigned long irq_flags = SMC_IRQ_FLAGS;
-       unsigned long irq_resflags;
        int ret;
 
        ndev = alloc_etherdev(sizeof(struct smc_local));
@@ -2343,19 +2342,16 @@ static int smc_drv_probe(struct platform_device *pdev)
                goto out_free_netdev;
        }
 
-       ndev->irq = platform_get_irq(pdev, 0);
-       if (ndev->irq <= 0) {
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!ires) {
                ret = -ENODEV;
                goto out_release_io;
        }
-       /*
-        * If this platform does not specify any special irqflags, or if
-        * the resource supplies a trigger, override the irqflags with
-        * the trigger flags from the resource.
-        */
-       irq_resflags = irqd_get_trigger_type(irq_get_irq_data(ndev->irq));
-       if (irq_flags == -1 || irq_resflags & IRQF_TRIGGER_MASK)
-               irq_flags = irq_resflags & IRQF_TRIGGER_MASK;
+
+       ndev->irq = ires->start;
+
+       if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK)
+               irq_flags = ires->flags & IRQF_TRIGGER_MASK;
 
        ret = smc_request_attrib(pdev, ndev);
        if (ret)
index a495931a66a1f217216cdb90a6b6989881039f32..0e0fbb5842b3d25e0d18ebaedfaeff60b006c1b7 100644 (file)
@@ -498,9 +498,9 @@ static int w5100_napi_poll(struct napi_struct *napi, int budget)
        }
 
        if (rx_count < budget) {
+               napi_complete(napi);
                w5100_write(priv, W5100_IMR, IR_S0);
                mmiowb();
-               napi_complete(napi);
        }
 
        return rx_count;
index 09322d9db5785ccb622a3ee3ec854442576bd537..4b310002258d0742031f4bcb36d395dd992d0a3d 100644 (file)
@@ -418,9 +418,9 @@ static int w5300_napi_poll(struct napi_struct *napi, int budget)
        }
 
        if (rx_count < budget) {
+               napi_complete(napi);
                w5300_write(priv, W5300_IMR, IR_S0);
                mmiowb();
-               napi_complete(napi);
        }
 
        return rx_count;
index 3eed708a6182e761fb79d197eadfbcbc028e5afc..1762ad3910b2e75b55db894afee887f055977b22 100644 (file)
@@ -46,8 +46,7 @@ enum cx82310_status {
 };
 
 #define CMD_PACKET_SIZE        64
-/* first command after power on can take around 8 seconds */
-#define CMD_TIMEOUT    15000
+#define CMD_TIMEOUT    100
 #define CMD_REPLY_RETRY 5
 
 #define CX82310_MTU    1514
@@ -78,8 +77,9 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
        ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
                           CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
        if (ret < 0) {
-               dev_err(&dev->udev->dev, "send command %#x: error %d\n",
-                       cmd, ret);
+               if (cmd != CMD_GET_LINK_STATUS)
+                       dev_err(&dev->udev->dev, "send command %#x: error %d\n",
+                               cmd, ret);
                goto end;
        }
 
@@ -90,8 +90,10 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
                                           buf, CMD_PACKET_SIZE, &actual_len,
                                           CMD_TIMEOUT);
                        if (ret < 0) {
-                               dev_err(&dev->udev->dev,
-                                       "reply receive error %d\n", ret);
+                               if (cmd != CMD_GET_LINK_STATUS)
+                                       dev_err(&dev->udev->dev,
+                                               "reply receive error %d\n",
+                                               ret);
                                goto end;
                        }
                        if (actual_len > 0)
@@ -134,6 +136,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        int ret;
        char buf[15];
        struct usb_device *udev = dev->udev;
+       u8 link[3];
+       int timeout = 50;
 
        /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
        if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
@@ -160,6 +164,20 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        if (!dev->partial_data)
                return -ENOMEM;
 
+       /* wait for firmware to become ready (indicated by the link being up) */
+       while (--timeout) {
+               ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
+                                 link, sizeof(link));
+               /* the command can time out during boot - it's not an error */
+               if (!ret && link[0] == 1 && link[2] == 1)
+                       break;
+               msleep(500);
+       };
+       if (!timeout) {
+               dev_err(&udev->dev, "firmware not ready in time\n");
+               return -ETIMEDOUT;
+       }
+
        /* enable ethernet mode (?) */
        ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
        if (ret) {
@@ -300,9 +318,18 @@ static const struct driver_info    cx82310_info = {
        .tx_fixup       = cx82310_tx_fixup,
 };
 
+#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+                      USB_DEVICE_ID_MATCH_DEV_INFO, \
+       .idVendor = (vend), \
+       .idProduct = (prod), \
+       .bDeviceClass = (cl), \
+       .bDeviceSubClass = (sc), \
+       .bDeviceProtocol = (pr)
+
 static const struct usb_device_id products[] = {
        {
-               USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0),
+               USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
                .driver_info = (unsigned long) &cx82310_info
        },
        { },
index f1ff3666f090d886e6b8ecc99bc6ac09d8687ef6..59b0e9754ae39cbc38812d407688f66f5e79b539 100644 (file)
@@ -1448,8 +1448,10 @@ static void virtnet_free_queues(struct virtnet_info *vi)
 {
        int i;
 
-       for (i = 0; i < vi->max_queue_pairs; i++)
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               napi_hash_del(&vi->rq[i].napi);
                netif_napi_del(&vi->rq[i].napi);
+       }
 
        kfree(vi->rq);
        kfree(vi->sq);
@@ -1948,11 +1950,8 @@ static int virtnet_freeze(struct virtio_device *vdev)
        cancel_delayed_work_sync(&vi->refill);
 
        if (netif_running(vi->dev)) {
-               for (i = 0; i < vi->max_queue_pairs; i++) {
+               for (i = 0; i < vi->max_queue_pairs; i++)
                        napi_disable(&vi->rq[i].napi);
-                       napi_hash_del(&vi->rq[i].napi);
-                       netif_napi_del(&vi->rq[i].napi);
-               }
        }
 
        remove_vq_common(vi);
index 1e0a775ea882995d88127e4d3c2a8f3f0afb8d60..f8528a4cf54f2b0bc78b78bd705a82577530bdeb 100644 (file)
@@ -1218,7 +1218,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                        goto drop;
 
                flags &= ~VXLAN_HF_RCO;
-               vni &= VXLAN_VID_MASK;
+               vni &= VXLAN_VNI_MASK;
        }
 
        /* For backwards compatibility, only allow reserved fields to be
@@ -1239,7 +1239,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                flags &= ~VXLAN_GBP_USED_BITS;
        }
 
-       if (flags || (vni & ~VXLAN_VID_MASK)) {
+       if (flags || vni & ~VXLAN_VNI_MASK) {
                /* If there are any unprocessed flags remaining treat
                 * this as a malformed packet. This behavior diverges from
                 * VXLAN RFC (RFC7348) which stipulates that bits in reserved
index ccbdb05b28cd7e2dc457afe9443e35ac2ca3fc21..75345c1e8c3487468a23611a3072d525cdc8b8ca 100644 (file)
@@ -5370,6 +5370,7 @@ static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
        case 0x432a: /* BCM4321 */
        case 0x432d: /* BCM4322 */
        case 0x4352: /* BCM43222 */
+       case 0x435a: /* BCM43228 */
        case 0x4333: /* BCM4331 */
        case 0x43a2: /* BCM4360 */
        case 0x43b3: /* BCM4352 */
index 50cdf7090198b3662b83488ff52e3868162401c5..8eff2753abadeb2704f87f88f7c5eabd75bf091b 100644 (file)
@@ -39,13 +39,22 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,
        void *dcmd_buf = NULL, *wr_pointer;
        u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
 
-       brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
-                 cmdhdr->len);
+       if (len < sizeof(*cmdhdr)) {
+               brcmf_err("vendor command too short: %d\n", len);
+               return -EINVAL;
+       }
 
        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
        ifp = vif->ifp;
 
-       len -= sizeof(struct brcmf_vndr_dcmd_hdr);
+       brcmf_dbg(TRACE, "ifidx=%d, cmd=%d\n", ifp->ifidx, cmdhdr->cmd);
+
+       if (cmdhdr->offset > len) {
+               brcmf_err("bad buffer offset %d > %d\n", cmdhdr->offset, len);
+               return -EINVAL;
+       }
+
+       len -= cmdhdr->offset;
        ret_len = cmdhdr->len;
        if (ret_len > 0 || len > 0) {
                if (len > BRCMF_DCMD_MAXLEN) {
index c3817fae16c04207136e5d45e8cc65bd3a125429..06f6cc08f451cadc7696c5b1810735288a85b1a9 100644 (file)
@@ -95,7 +95,8 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
        .nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,  \
        .base_params = &iwl1000_base_params,                    \
        .eeprom_params = &iwl1000_eeprom_params,                \
-       .led_mode = IWL_LED_BLINK
+       .led_mode = IWL_LED_BLINK,                              \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl1000_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
@@ -121,7 +122,8 @@ const struct iwl_cfg iwl1000_bg_cfg = {
        .base_params = &iwl1000_base_params,                    \
        .eeprom_params = &iwl1000_eeprom_params,                \
        .led_mode = IWL_LED_RF_STATE,                           \
-       .rx_with_siso_diversity = true
+       .rx_with_siso_diversity = true,                         \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl100_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
index 21e5d0843a62a84a0f21ff337d1b674750fa3999..890b95f497d6eca97949a5e3989926d5b4d17d38 100644 (file)
@@ -123,7 +123,9 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
        .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,          \
        .base_params = &iwl2000_base_params,                    \
        .eeprom_params = &iwl20x0_eeprom_params,                \
-       .led_mode = IWL_LED_RF_STATE
+       .led_mode = IWL_LED_RF_STATE,                           \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
+
 
 const struct iwl_cfg iwl2000_2bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
@@ -149,7 +151,8 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = {
        .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,  \
        .base_params = &iwl2030_base_params,                    \
        .eeprom_params = &iwl20x0_eeprom_params,                \
-       .led_mode = IWL_LED_RF_STATE
+       .led_mode = IWL_LED_RF_STATE,                           \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl2030_2bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
@@ -170,7 +173,8 @@ const struct iwl_cfg iwl2030_2bgn_cfg = {
        .base_params = &iwl2000_base_params,                    \
        .eeprom_params = &iwl20x0_eeprom_params,                \
        .led_mode = IWL_LED_RF_STATE,                           \
-       .rx_with_siso_diversity = true
+       .rx_with_siso_diversity = true,                         \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl105_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
@@ -197,7 +201,8 @@ const struct iwl_cfg iwl105_bgn_d_cfg = {
        .base_params = &iwl2030_base_params,                    \
        .eeprom_params = &iwl20x0_eeprom_params,                \
        .led_mode = IWL_LED_RF_STATE,                           \
-       .rx_with_siso_diversity = true
+       .rx_with_siso_diversity = true,                         \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl135_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
index 332bbede39e5b0fc6bb25b7ab30bbbd22c929b8b..724194e234141e707dac6eb8ec57563435957aae 100644 (file)
@@ -93,7 +93,8 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
        .nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION,  \
        .base_params = &iwl5000_base_params,                    \
        .eeprom_params = &iwl5000_eeprom_params,                \
-       .led_mode = IWL_LED_BLINK
+       .led_mode = IWL_LED_BLINK,                              \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl5300_agn_cfg = {
        .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
@@ -158,7 +159,8 @@ const struct iwl_cfg iwl5350_agn_cfg = {
        .base_params = &iwl5000_base_params,                    \
        .eeprom_params = &iwl5000_eeprom_params,                \
        .led_mode = IWL_LED_BLINK,                              \
-       .internal_wimax_coex = true
+       .internal_wimax_coex = true,                            \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl5150_agn_cfg = {
        .name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
index 8f2c3c8c6b843f78f346225d371ee3ad3df54f23..21b2630763dc933db72f54fd7fadba9244d6b449 100644 (file)
@@ -145,7 +145,8 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
        .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION,  \
        .base_params = &iwl6000_g2_base_params,                 \
        .eeprom_params = &iwl6000_eeprom_params,                \
-       .led_mode = IWL_LED_RF_STATE
+       .led_mode = IWL_LED_RF_STATE,                           \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6005_2agn_cfg = {
        .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
@@ -199,7 +200,8 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
        .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,  \
        .base_params = &iwl6000_g2_base_params,                 \
        .eeprom_params = &iwl6000_eeprom_params,                \
-       .led_mode = IWL_LED_RF_STATE
+       .led_mode = IWL_LED_RF_STATE,                           \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6030_2agn_cfg = {
        .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
@@ -235,7 +237,8 @@ const struct iwl_cfg iwl6030_2bg_cfg = {
        .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,  \
        .base_params = &iwl6000_g2_base_params,                 \
        .eeprom_params = &iwl6000_eeprom_params,                \
-       .led_mode = IWL_LED_RF_STATE
+       .led_mode = IWL_LED_RF_STATE,                           \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6035_2agn_cfg = {
        .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
@@ -290,7 +293,8 @@ const struct iwl_cfg iwl130_bg_cfg = {
        .nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,  \
        .base_params = &iwl6000_base_params,                    \
        .eeprom_params = &iwl6000_eeprom_params,                \
-       .led_mode = IWL_LED_BLINK
+       .led_mode = IWL_LED_BLINK,                              \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6000i_2agn_cfg = {
        .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
@@ -322,7 +326,8 @@ const struct iwl_cfg iwl6000i_2bg_cfg = {
        .base_params = &iwl6050_base_params,                    \
        .eeprom_params = &iwl6000_eeprom_params,                \
        .led_mode = IWL_LED_BLINK,                              \
-       .internal_wimax_coex = true
+       .internal_wimax_coex = true,                            \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6050_2agn_cfg = {
        .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
@@ -347,7 +352,8 @@ const struct iwl_cfg iwl6050_2abg_cfg = {
        .base_params = &iwl6050_base_params,                    \
        .eeprom_params = &iwl6000_eeprom_params,                \
        .led_mode = IWL_LED_BLINK,                              \
-       .internal_wimax_coex = true
+       .internal_wimax_coex = true,                            \
+       .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
 
 const struct iwl_cfg iwl6150_bgn_cfg = {
        .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
index 1ec4d55155f7d72fecdbe19db62dd36546bb05e0..7810c41cf9a7300e0d3b9bc16bca22a44188b463 100644 (file)
@@ -793,7 +793,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
        if (!vif->bss_conf.assoc)
                smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
-       if (IWL_COEX_IS_RRC_ON(mvm->last_bt_notif.ttc_rrc_status,
+       if (mvmvif->phy_ctxt &&
+           IWL_COEX_IS_RRC_ON(mvm->last_bt_notif.ttc_rrc_status,
                               mvmvif->phy_ctxt->id))
                smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
index d530ef3da1071e5a421db3f4c072504b3571d8e3..542ee74f290aec1a3f356b3c69718b5029c4e708 100644 (file)
@@ -832,7 +832,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
        if (!vif->bss_conf.assoc)
                smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
-       if (data->notif->rrc_enabled & BIT(mvmvif->phy_ctxt->id))
+       if (mvmvif->phy_ctxt &&
+           data->notif->rrc_enabled & BIT(mvmvif->phy_ctxt->id))
                smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
        IWL_DEBUG_COEX(data->mvm,
index 1ff7ec08532d113aa5be85cb59eed8100e3f7eed..09654e73a533f7733c2a5b1e47bf6251d6267585 100644 (file)
@@ -405,7 +405,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
 
-               if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER)
+               if ((mvm->fw->ucode_capa.capa[0] &
+                    IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
+                   (mvm->fw->ucode_capa.api[0] &
+                    IWL_UCODE_TLV_API_LQ_SS_PARAMS))
                        hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |=
                                IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
        }
@@ -2215,7 +2218,19 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
-       iwl_mvm_cancel_scan(mvm);
+       /* Due to a race condition, it's possible that mac80211 asks
+        * us to stop a hw_scan when it's already stopped.  This can
+        * happen, for instance, if we stopped the scan ourselves,
+        * called ieee80211_scan_completed() and the userspace called
+        * cancel scan scan before ieee80211_scan_work() could run.
+        * To handle that, simply return if the scan is not running.
+       */
+       /* FIXME: for now, we ignore this race for UMAC scans, since
+        * they don't set the scan_status.
+        */
+       if ((mvm->scan_status == IWL_MVM_SCAN_OS) ||
+           (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN))
+               iwl_mvm_cancel_scan(mvm);
 
        mutex_unlock(&mvm->mutex);
 }
@@ -2559,12 +2574,29 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
        int ret;
 
        mutex_lock(&mvm->mutex);
+
+       /* Due to a race condition, it's possible that mac80211 asks
+        * us to stop a sched_scan when it's already stopped.  This
+        * can happen, for instance, if we stopped the scan ourselves,
+        * called ieee80211_sched_scan_stopped() and the userspace called
+        * stop sched scan scan before ieee80211_sched_scan_stopped_work()
+        * could run.  To handle this, simply return if the scan is
+        * not running.
+       */
+       /* FIXME: for now, we ignore this race for UMAC scans, since
+        * they don't set the scan_status.
+        */
+       if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+           !(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
+               mutex_unlock(&mvm->mutex);
+               return 0;
+       }
+
        ret = iwl_mvm_scan_offload_stop(mvm, false);
        mutex_unlock(&mvm->mutex);
        iwl_mvm_wait_for_async_handlers(mvm);
 
        return ret;
-
 }
 
 static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
index 194bd1f939ca3c6a42e9c4a9d6cc7eb843c2d256..efa9688a4cf11150f6d1e92c71e0a367d90fea87 100644 (file)
@@ -134,9 +134,12 @@ enum rs_column_mode {
 #define MAX_NEXT_COLUMNS 7
 #define MAX_COLUMN_CHECKS 3
 
+struct rs_tx_column;
+
 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
                                     struct ieee80211_sta *sta,
-                                    struct iwl_scale_tbl_info *tbl);
+                                    struct iwl_scale_tbl_info *tbl,
+                                    const struct rs_tx_column *next_col);
 
 struct rs_tx_column {
        enum rs_column_mode mode;
@@ -147,13 +150,15 @@ struct rs_tx_column {
 };
 
 static bool rs_ant_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                        struct iwl_scale_tbl_info *tbl)
+                        struct iwl_scale_tbl_info *tbl,
+                        const struct rs_tx_column *next_col)
 {
-       return iwl_mvm_bt_coex_is_ant_avail(mvm, tbl->rate.ant);
+       return iwl_mvm_bt_coex_is_ant_avail(mvm, next_col->ant);
 }
 
 static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         struct iwl_scale_tbl_info *tbl)
+                         struct iwl_scale_tbl_info *tbl,
+                         const struct rs_tx_column *next_col)
 {
        if (!sta->ht_cap.ht_supported)
                return false;
@@ -171,7 +176,8 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 }
 
 static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         struct iwl_scale_tbl_info *tbl)
+                         struct iwl_scale_tbl_info *tbl,
+                         const struct rs_tx_column *next_col)
 {
        if (!sta->ht_cap.ht_supported)
                return false;
@@ -180,7 +186,8 @@ static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 }
 
 static bool rs_sgi_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                        struct iwl_scale_tbl_info *tbl)
+                        struct iwl_scale_tbl_info *tbl,
+                        const struct rs_tx_column *next_col)
 {
        struct rs_rate *rate = &tbl->rate;
        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
@@ -1590,7 +1597,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 
                for (j = 0; j < MAX_COLUMN_CHECKS; j++) {
                        allow_func = next_col->checks[j];
-                       if (allow_func && !allow_func(mvm, sta, tbl))
+                       if (allow_func && !allow_func(mvm, sta, tbl, next_col))
                                break;
                }
 
index 7e9aa3cb325401fcf4105e278294b11657a90df1..c47c8051da7770f2a2a89c9b33868151c62f0ff6 100644 (file)
@@ -1128,8 +1128,10 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
        if (mvm->scan_status == IWL_MVM_SCAN_NONE)
                return 0;
 
-       if (iwl_mvm_is_radio_killed(mvm))
+       if (iwl_mvm_is_radio_killed(mvm)) {
+               ret = 0;
                goto out;
+       }
 
        if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
            (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
@@ -1148,16 +1150,14 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
                IWL_DEBUG_SCAN(mvm, "Send stop %sscan failed %d\n",
                               sched ? "offloaded " : "", ret);
                iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
-               return ret;
+               goto out;
        }
 
        IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
                       sched ? "offloaded " : "");
 
        ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
-       if (ret)
-               return ret;
-
+out:
        /*
         * Clear the scan status so the next scan requests will succeed. This
         * also ensures the Rx handler doesn't do anything, as the scan was
@@ -1167,7 +1167,6 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
        if (mvm->scan_status == IWL_MVM_SCAN_OS)
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
 
-out:
        mvm->scan_status = IWL_MVM_SCAN_NONE;
 
        if (notify) {
@@ -1177,7 +1176,7 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
                        ieee80211_scan_completed(mvm->hw, true);
        }
 
-       return 0;
+       return ret;
 }
 
 static void iwl_mvm_unified_scan_fill_tx_cmd(struct iwl_mvm *mvm,
index 54fafbf9a711fb9bacb3149fcb9f8ce1826c4b90..f8d6f306dd76d276b82056c9fb1a74956e78ac3c 100644 (file)
@@ -750,8 +750,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
         * request
         */
        list_for_each_entry(te_data, &mvm->time_event_list, list) {
-               if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE &&
-                   te_data->running) {
+               if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
                        mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
                        is_p2p = true;
                        goto remove_te;
@@ -766,10 +765,8 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
         * request
         */
        list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
-               if (te_data->running) {
-                       mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
-                       goto remove_te;
-               }
+               mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
+               goto remove_te;
        }
 
 remove_te:
index 1d46774607116af89f96c6e835cb84775ddaa8ca..074f716020aae4e28d3e8340da846514065a94db 100644 (file)
@@ -1386,8 +1386,11 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                }
 
                return true;
-       } else if (0x86DD == ether_type) {
-               return true;
+       } else if (ETH_P_IPV6 == ether_type) {
+               /* TODO: Handle any IPv6 cases that need special handling.
+                * For now, always return false
+                */
+               goto end;
        }
 
 end:
index cab9f5257f577ffd03c3eb2b7e57398907ee3498..997cf0901ac2dc50d92f26ea2c5c4e51511b8362 100644 (file)
@@ -96,6 +96,7 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
 static void make_tx_response(struct xenvif_queue *queue,
                             struct xen_netif_tx_request *txp,
                             s8       st);
+static void push_tx_responses(struct xenvif_queue *queue);
 
 static inline int tx_work_todo(struct xenvif_queue *queue);
 
@@ -655,15 +656,10 @@ static void xenvif_tx_err(struct xenvif_queue *queue,
        unsigned long flags;
 
        do {
-               int notify;
-
                spin_lock_irqsave(&queue->response_lock, flags);
                make_tx_response(queue, txp, XEN_NETIF_RSP_ERROR);
-               RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
+               push_tx_responses(queue);
                spin_unlock_irqrestore(&queue->response_lock, flags);
-               if (notify)
-                       notify_remote_via_irq(queue->tx_irq);
-
                if (cons == end)
                        break;
                txp = RING_GET_REQUEST(&queue->tx, cons++);
@@ -1657,7 +1653,6 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
 {
        struct pending_tx_info *pending_tx_info;
        pending_ring_idx_t index;
-       int notify;
        unsigned long flags;
 
        pending_tx_info = &queue->pending_tx_info[pending_idx];
@@ -1673,12 +1668,9 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
        index = pending_index(queue->pending_prod++);
        queue->pending_ring[index] = pending_idx;
 
-       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
+       push_tx_responses(queue);
 
        spin_unlock_irqrestore(&queue->response_lock, flags);
-
-       if (notify)
-               notify_remote_via_irq(queue->tx_irq);
 }
 
 
@@ -1699,6 +1691,15 @@ static void make_tx_response(struct xenvif_queue *queue,
        queue->tx.rsp_prod_pvt = ++i;
 }
 
+static void push_tx_responses(struct xenvif_queue *queue)
+{
+       int notify;
+
+       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
+       if (notify)
+               notify_remote_via_irq(queue->tx_irq);
+}
+
 static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue,
                                             u16      id,
                                             s8       st,
index adb8764861c02893d1e965bf077c0c9706abdadb..8f165b112e03a285899655984491b000f0020e17 100644 (file)
@@ -715,13 +715,8 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent,
 {
        struct device_node *child;
        int len;
-       const char *end;
 
-       end = strchr(path, ':');
-       if (!end)
-               end = strchrnul(path, '/');
-
-       len = end - path;
+       len = strcspn(path, "/:");
        if (!len)
                return NULL;
 
@@ -1893,10 +1888,8 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
                        name = of_get_property(of_chosen, "linux,stdout-path", NULL);
                if (IS_ENABLED(CONFIG_PPC) && !name)
                        name = of_get_property(of_aliases, "stdout", NULL);
-               if (name) {
+               if (name)
                        of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
-                       add_preferred_console("stdout-path", 0, NULL);
-               }
        }
 
        if (!of_aliases)
index 0d7765807f4940c1aa892665a78e0b32c4128528..1a7980692f254c6917371dec5a11f77f448723cf 100644 (file)
@@ -290,7 +290,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
        struct device_node *p;
        const __be32 *intspec, *tmp, *addr;
        u32 intsize, intlen;
-       int i, res = -EINVAL;
+       int i, res;
 
        pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
 
@@ -323,15 +323,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
 
        /* Get size of interrupt specifier */
        tmp = of_get_property(p, "#interrupt-cells", NULL);
-       if (tmp == NULL)
+       if (tmp == NULL) {
+               res = -EINVAL;
                goto out;
+       }
        intsize = be32_to_cpu(*tmp);
 
        pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
 
        /* Check index */
-       if ((index + 1) * intsize > intlen)
+       if ((index + 1) * intsize > intlen) {
+               res = -EINVAL;
                goto out;
+       }
 
        /* Copy intspec into irq structure */
        intspec += index * intsize;
index aba8946cac46dddd171aed6ddf6e35f58be152b7..52c45c7df07ff6623c7fb7656961f8bdcf804da3 100644 (file)
@@ -97,6 +97,11 @@ static void __init of_selftest_find_node_by_name(void)
                 "option path test, subcase #1 failed\n");
        of_node_put(np);
 
+       np = of_find_node_opts_by_path("/testcase-data/testcase-device1:test/option", &options);
+       selftest(np && !strcmp("test/option", options),
+                "option path test, subcase #2 failed\n");
+       of_node_put(np);
+
        np = of_find_node_opts_by_path("/testcase-data:testoption", NULL);
        selftest(np, "NULL option path test failed\n");
        of_node_put(np);
index 3bb49252a098b0b3d4c72b0895044c538d2af17d..45f67c63d38539a091fde716bb0c5aa8a18b2b8b 100644 (file)
@@ -69,8 +69,7 @@ config YENTA
        tristate "CardBus yenta-compatible bridge support"
        depends on PCI
        select CARDBUS if !EXPERT
-       select PCCARD_NONSTATIC if PCMCIA != n && ISA
-       select PCCARD_PCI if PCMCIA !=n && !ISA
+       select PCCARD_NONSTATIC if PCMCIA != n
        ---help---
          This option enables support for CardBus host bridges.  Virtually
          all modern PCMCIA bridges are CardBus compatible.  A "bridge" is
@@ -110,8 +109,7 @@ config YENTA_TOSHIBA
 config PD6729
        tristate "Cirrus PD6729 compatible bridge support"
        depends on PCMCIA && PCI
-       select PCCARD_NONSTATIC if PCMCIA != n && ISA
-       select PCCARD_PCI if PCMCIA !=n && !ISA
+       select PCCARD_NONSTATIC
        help
          This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
          device, found in some older laptops and PCMCIA card readers.
@@ -119,8 +117,7 @@ config PD6729
 config I82092
        tristate "i82092 compatible bridge support"
        depends on PCMCIA && PCI
-       select PCCARD_NONSTATIC if PCMCIA != n && ISA
-       select PCCARD_PCI if PCMCIA !=n && !ISA
+       select PCCARD_NONSTATIC
        help
          This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
          found in some older laptops and more commonly in evaluation boards for the
@@ -291,9 +288,6 @@ config ELECTRA_CF
          Say Y here to support the CompactFlash controller on the
          PA Semi Electra eval board.
 
-config PCCARD_PCI
-       bool
-
 config PCCARD_NONSTATIC
        bool
 
index f1a7ca04d89e9b743fc3f82e545c52521fedef81..27e94b30cf9625b8da99d67b74308651b8077dc6 100644 (file)
@@ -12,7 +12,6 @@ obj-$(CONFIG_PCMCIA)                          += pcmcia.o
 pcmcia_rsrc-y                                  += rsrc_mgr.o
 pcmcia_rsrc-$(CONFIG_PCCARD_NONSTATIC)         += rsrc_nonstatic.o
 pcmcia_rsrc-$(CONFIG_PCCARD_IODYN)             += rsrc_iodyn.o
-pcmcia_rsrc-$(CONFIG_PCCARD_PCI)               += rsrc_pci.o
 obj-$(CONFIG_PCCARD)                           += pcmcia_rsrc.o
 
 
diff --git a/drivers/pcmcia/rsrc_pci.c b/drivers/pcmcia/rsrc_pci.c
deleted file mode 100644 (file)
index 1f67b3b..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <pcmcia/ss.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-
-struct pcmcia_align_data {
-       unsigned long   mask;
-       unsigned long   offset;
-};
-
-static resource_size_t pcmcia_align(void *align_data,
-                               const struct resource *res,
-                               resource_size_t size, resource_size_t align)
-{
-       struct pcmcia_align_data *data = align_data;
-       resource_size_t start;
-
-       start = (res->start & ~data->mask) + data->offset;
-       if (start < res->start)
-               start += data->mask + 1;
-       return start;
-}
-
-static struct resource *find_io_region(struct pcmcia_socket *s,
-                                       unsigned long base, int num,
-                                       unsigned long align)
-{
-       struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
-                                               dev_name(&s->dev));
-       struct pcmcia_align_data data;
-       int ret;
-
-       data.mask = align - 1;
-       data.offset = base & data.mask;
-
-       ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
-                                            base, 0, pcmcia_align, &data);
-       if (ret != 0) {
-               kfree(res);
-               res = NULL;
-       }
-       return res;
-}
-
-static int res_pci_find_io(struct pcmcia_socket *s, unsigned int attr,
-                       unsigned int *base, unsigned int num,
-                       unsigned int align, struct resource **parent)
-{
-       int i, ret = 0;
-
-       /* Check for an already-allocated window that must conflict with
-        * what was asked for.  It is a hack because it does not catch all
-        * potential conflicts, just the most obvious ones.
-        */
-       for (i = 0; i < MAX_IO_WIN; i++) {
-               if (!s->io[i].res)
-                       continue;
-
-               if (!*base)
-                       continue;
-
-               if ((s->io[i].res->start & (align-1)) == *base)
-                       return -EBUSY;
-       }
-
-       for (i = 0; i < MAX_IO_WIN; i++) {
-               struct resource *res = s->io[i].res;
-               unsigned int try;
-
-               if (res && (res->flags & IORESOURCE_BITS) !=
-                       (attr & IORESOURCE_BITS))
-                       continue;
-
-               if (!res) {
-                       if (align == 0)
-                               align = 0x10000;
-
-                       res = s->io[i].res = find_io_region(s, *base, num,
-                                                               align);
-                       if (!res)
-                               return -EINVAL;
-
-                       *base = res->start;
-                       s->io[i].res->flags =
-                               ((res->flags & ~IORESOURCE_BITS) |
-                                       (attr & IORESOURCE_BITS));
-                       s->io[i].InUse = num;
-                       *parent = res;
-                       return 0;
-               }
-
-               /* Try to extend top of window */
-               try = res->end + 1;
-               if ((*base == 0) || (*base == try)) {
-                       ret = adjust_resource(s->io[i].res, res->start,
-                                             resource_size(res) + num);
-                       if (ret)
-                               continue;
-                       *base = try;
-                       s->io[i].InUse += num;
-                       *parent = res;
-                       return 0;
-               }
-
-               /* Try to extend bottom of window */
-               try = res->start - num;
-               if ((*base == 0) || (*base == try)) {
-                       ret = adjust_resource(s->io[i].res,
-                                             res->start - num,
-                                             resource_size(res) + num);
-                       if (ret)
-                               continue;
-                       *base = try;
-                       s->io[i].InUse += num;
-                       *parent = res;
-                       return 0;
-               }
-       }
-       return -EINVAL;
-}
-
-static struct resource *res_pci_find_mem(u_long base, u_long num,
-               u_long align, int low, struct pcmcia_socket *s)
-{
-       struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
-                                               dev_name(&s->dev));
-       struct pcmcia_align_data data;
-       unsigned long min;
-       int ret;
-
-       if (align < 0x20000)
-               align = 0x20000;
-       data.mask = align - 1;
-       data.offset = base & data.mask;
-
-       min = 0;
-       if (!low)
-               min = 0x100000UL;
-
-       ret = pci_bus_alloc_resource(s->cb_dev->bus,
-                       res, num, 1, min, 0,
-                       pcmcia_align, &data);
-
-       if (ret != 0) {
-               kfree(res);
-               res = NULL;
-       }
-       return res;
-}
-
-
-static int res_pci_init(struct pcmcia_socket *s)
-{
-       if (!s->cb_dev || !(s->features & SS_CAP_PAGE_REGS)) {
-               dev_err(&s->dev, "not supported by res_pci\n");
-               return -EOPNOTSUPP;
-       }
-       return 0;
-}
-
-struct pccard_resource_ops pccard_nonstatic_ops = {
-       .validate_mem = NULL,
-       .find_io = res_pci_find_io,
-       .find_mem = res_pci_find_mem,
-       .init = res_pci_init,
-       .exit = NULL,
-};
-EXPORT_SYMBOL(pccard_nonstatic_ops);
index 7c99ca256f059f79d4b288140da3feef5e0a67f8..8ccc3952c13dca6287b04a6b62fe50d1ceb076d6 100644 (file)
@@ -37,7 +37,7 @@ static int armada375_usb_phy_init(struct phy *phy)
        struct armada375_cluster_phy *cluster_phy;
        u32 reg;
 
-       cluster_phy = dev_get_drvdata(phy->dev.parent);
+       cluster_phy = phy_get_drvdata(phy);
        if (!cluster_phy)
                return -ENODEV;
 
@@ -131,6 +131,7 @@ static int armada375_usb_phy_probe(struct platform_device *pdev)
        cluster_phy->reg = usb_cluster_base;
 
        dev_set_drvdata(dev, cluster_phy);
+       phy_set_drvdata(phy, cluster_phy);
 
        phy_provider = devm_of_phy_provider_register(&pdev->dev,
                                                     armada375_usb_phy_xlate);
index a12d35338313bd4f4a67117f3c5c3f76030e53fd..3791838f4bd4b14e145dd5718a3030c4b89d9f3b 100644 (file)
@@ -52,7 +52,9 @@ static void devm_phy_consume(struct device *dev, void *res)
 
 static int devm_phy_match(struct device *dev, void *res, void *match_data)
 {
-       return res == match_data;
+       struct phy **phy = res;
+
+       return *phy == match_data;
 }
 
 /**
@@ -223,6 +225,7 @@ int phy_init(struct phy *phy)
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
+       ret = 0; /* Override possible ret == -ENOTSUPP */
 
        mutex_lock(&phy->mutex);
        if (phy->init_count == 0 && phy->ops->init) {
@@ -231,8 +234,6 @@ int phy_init(struct phy *phy)
                        dev_err(&phy->dev, "phy init failed --> %d\n", ret);
                        goto out;
                }
-       } else {
-               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->init_count;
 
@@ -253,6 +254,7 @@ int phy_exit(struct phy *phy)
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
+       ret = 0; /* Override possible ret == -ENOTSUPP */
 
        mutex_lock(&phy->mutex);
        if (phy->init_count == 1 && phy->ops->exit) {
@@ -287,6 +289,7 @@ int phy_power_on(struct phy *phy)
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
+       ret = 0; /* Override possible ret == -ENOTSUPP */
 
        mutex_lock(&phy->mutex);
        if (phy->power_count == 0 && phy->ops->power_on) {
@@ -295,8 +298,6 @@ int phy_power_on(struct phy *phy)
                        dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
                        goto out;
                }
-       } else {
-               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->power_count;
        mutex_unlock(&phy->mutex);
index f86cbe68ddaf30fd1a5a377c2f7d9dfb1c259c8f..179cbf9451aacf1aca440e46eb05493f41037e48 100644 (file)
@@ -30,28 +30,13 @@ struct exynos_dp_video_phy {
        const struct exynos_dp_video_phy_drvdata *drvdata;
 };
 
-static void exynos_dp_video_phy_pwr_isol(struct exynos_dp_video_phy *state,
-                                                       unsigned int on)
-{
-       unsigned int val;
-
-       if (IS_ERR(state->regs))
-               return;
-
-       val = on ? 0 : EXYNOS5_PHY_ENABLE;
-
-       regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
-                          EXYNOS5_PHY_ENABLE, val);
-}
-
 static int exynos_dp_video_phy_power_on(struct phy *phy)
 {
        struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
 
        /* Disable power isolation on DP-PHY */
-       exynos_dp_video_phy_pwr_isol(state, 0);
-
-       return 0;
+       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
+                                 EXYNOS5_PHY_ENABLE, EXYNOS5_PHY_ENABLE);
 }
 
 static int exynos_dp_video_phy_power_off(struct phy *phy)
@@ -59,9 +44,8 @@ static int exynos_dp_video_phy_power_off(struct phy *phy)
        struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
 
        /* Enable power isolation on DP-PHY */
-       exynos_dp_video_phy_pwr_isol(state, 1);
-
-       return 0;
+       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
+                                 EXYNOS5_PHY_ENABLE, 0);
 }
 
 static struct phy_ops exynos_dp_video_phy_ops = {
index f017b2f2a54ecb18c8aa7b0fed3c375f790e48d4..df7519a39ba0b15fd9181a3c3c9bcba17fcd34e9 100644 (file)
@@ -43,7 +43,6 @@ struct exynos_mipi_video_phy {
        } phys[EXYNOS_MIPI_PHYS_NUM];
        spinlock_t slock;
        void __iomem *regs;
-       struct mutex mutex;
        struct regmap *regmap;
 };
 
@@ -59,8 +58,9 @@ static int __set_phy_state(struct exynos_mipi_video_phy *state,
        else
                reset = EXYNOS4_MIPI_PHY_SRESETN;
 
-       if (state->regmap) {
-               mutex_lock(&state->mutex);
+       spin_lock(&state->slock);
+
+       if (!IS_ERR(state->regmap)) {
                regmap_read(state->regmap, offset, &val);
                if (on)
                        val |= reset;
@@ -72,11 +72,9 @@ static int __set_phy_state(struct exynos_mipi_video_phy *state,
                else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
                        val &= ~EXYNOS4_MIPI_PHY_ENABLE;
                regmap_write(state->regmap, offset, val);
-               mutex_unlock(&state->mutex);
        } else {
                addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
 
-               spin_lock(&state->slock);
                val = readl(addr);
                if (on)
                        val |= reset;
@@ -90,9 +88,9 @@ static int __set_phy_state(struct exynos_mipi_video_phy *state,
                        val &= ~EXYNOS4_MIPI_PHY_ENABLE;
 
                writel(val, addr);
-               spin_unlock(&state->slock);
        }
 
+       spin_unlock(&state->slock);
        return 0;
 }
 
@@ -158,7 +156,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 
        dev_set_drvdata(dev, state);
        spin_lock_init(&state->slock);
-       mutex_init(&state->mutex);
 
        for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
                struct phy *phy = devm_phy_create(dev, NULL,
index 236a52ad94eb705a6be6ea9813838ded256f76e1..f30bbb0fb3b2652e897c1922a7f51e48b3dc270f 100644 (file)
@@ -250,7 +250,6 @@ static const struct samsung_usb2_common_phy exynos4210_phys[] = {
                .power_on       = exynos4210_power_on,
                .power_off      = exynos4210_power_off,
        },
-       {},
 };
 
 const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
index 0b9de88579b13264a0eae49c4e159bad70aac3b1..765da90a536f057f9e3ccfc4bfe24868a388a63f 100644 (file)
@@ -361,7 +361,6 @@ static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
                .power_on       = exynos4x12_power_on,
                .power_off      = exynos4x12_power_off,
        },
-       {},
 };
 
 const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
index 04374018425f9ab488dea49dd797f68aa5b339c1..e2a0be750ad962d82e2666e5005a8b8daf97f381 100644 (file)
@@ -531,7 +531,7 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
 {
        struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
 
-       if (WARN_ON(args->args[0] > EXYNOS5_DRDPHYS_NUM))
+       if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
                return ERR_PTR(-ENODEV);
 
        return phy_drd->phys[args->args[0]].phy;
index 1c139aa0d074324e74a5f95bb06e83cea2818abf..2ed1735a076a1f8a50898de3d3de28bc7dfa235d 100644 (file)
@@ -391,7 +391,6 @@ static const struct samsung_usb2_common_phy exynos5250_phys[] = {
                .power_on       = exynos5250_power_on,
                .power_off      = exynos5250_power_off,
        },
-       {},
 };
 
 const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
index 34915b4202f18c5249a059dd42aa914fee2e7f2d..d6b22659cac11cfb4187cf9347ac86774f79de5e 100644 (file)
@@ -147,6 +147,9 @@ static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
        priv->base = devm_ioremap(dev, res->start, resource_size(res));
        if (!priv->base)
                return -ENOMEM;
index 9b2848e6115d44d050d7858ac75d01df60f71da3..933435214acce1db8895b95cc739138288b3de4b 100644 (file)
@@ -228,6 +228,7 @@ struct miphy28lp_dev {
        struct regmap *regmap;
        struct mutex miphy_mutex;
        struct miphy28lp_phy **phys;
+       int nphys;
 };
 
 struct miphy_initval {
@@ -1116,7 +1117,7 @@ static struct phy *miphy28lp_xlate(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       for (index = 0; index < of_get_child_count(dev->of_node); index++)
+       for (index = 0; index < miphy_dev->nphys; index++)
                if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
                        miphy_phy = miphy_dev->phys[index];
                        break;
@@ -1138,6 +1139,7 @@ static struct phy *miphy28lp_xlate(struct device *dev,
 
 static struct phy_ops miphy28lp_ops = {
        .init = miphy28lp_init,
+       .owner = THIS_MODULE,
 };
 
 static int miphy28lp_probe_resets(struct device_node *node,
@@ -1200,16 +1202,15 @@ static int miphy28lp_probe(struct platform_device *pdev)
        struct miphy28lp_dev *miphy_dev;
        struct phy_provider *provider;
        struct phy *phy;
-       int chancount, port = 0;
-       int ret;
+       int ret, port = 0;
 
        miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
        if (!miphy_dev)
                return -ENOMEM;
 
-       chancount = of_get_child_count(np);
-       miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
-                                      GFP_KERNEL);
+       miphy_dev->nphys = of_get_child_count(np);
+       miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,
+                                      sizeof(*miphy_dev->phys), GFP_KERNEL);
        if (!miphy_dev->phys)
                return -ENOMEM;
 
index 6c80154e8bffb23253e03d546edd68a11ad3e0b0..51b459db9137417bb26fa971df92e6d8e86121ed 100644 (file)
@@ -150,6 +150,7 @@ struct miphy365x_dev {
        struct regmap *regmap;
        struct mutex miphy_mutex;
        struct miphy365x_phy **phys;
+       int nphys;
 };
 
 /*
@@ -485,7 +486,7 @@ static struct phy *miphy365x_xlate(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       for (index = 0; index < of_get_child_count(dev->of_node); index++)
+       for (index = 0; index < miphy_dev->nphys; index++)
                if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
                        miphy_phy = miphy_dev->phys[index];
                        break;
@@ -541,16 +542,15 @@ static int miphy365x_probe(struct platform_device *pdev)
        struct miphy365x_dev *miphy_dev;
        struct phy_provider *provider;
        struct phy *phy;
-       int chancount, port = 0;
-       int ret;
+       int ret, port = 0;
 
        miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
        if (!miphy_dev)
                return -ENOMEM;
 
-       chancount = of_get_child_count(np);
-       miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
-                                      GFP_KERNEL);
+       miphy_dev->nphys = of_get_child_count(np);
+       miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,
+                                      sizeof(*miphy_dev->phys), GFP_KERNEL);
        if (!miphy_dev->phys)
                return -ENOMEM;
 
index efe724f97e02fbf9eba84c215628993fa3ea1274..93252e053a31ca752fe54bd0fc71760d318f2579 100644 (file)
@@ -360,7 +360,7 @@ static void __exit omap_control_phy_exit(void)
 }
 module_exit(omap_control_phy_exit);
 
-MODULE_ALIAS("platform: omap_control_phy");
+MODULE_ALIAS("platform:omap_control_phy");
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("OMAP Control Module PHY Driver");
 MODULE_LICENSE("GPL v2");
index 6f4aef3db2481de0dc03df70521242a9be5d7fa5..4757e765696a232d1926ece274ef35111188cdc1 100644 (file)
@@ -296,10 +296,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
                        dev_warn(&pdev->dev,
                                 "found usb_otg_ss_refclk960m, please fix DTS\n");
                }
-       } else {
-               clk_prepare(phy->optclk);
        }
 
+       if (!IS_ERR(phy->optclk))
+               clk_prepare(phy->optclk);
+
        usb_add_phy_dev(&phy->phy);
 
        return 0;
@@ -383,7 +384,7 @@ static struct platform_driver omap_usb2_driver = {
 
 module_platform_driver(omap_usb2_driver);
 
-MODULE_ALIAS("platform: omap_usb2");
+MODULE_ALIAS("platform:omap_usb2");
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("OMAP USB2 phy driver");
 MODULE_LICENSE("GPL v2");
index 22011c3b6a4bbdc3a3734a3ca27c665fcf099de8..7d4c33643768808780f71455900bc7dd51329103 100644 (file)
@@ -61,8 +61,6 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
                return ret;
 
        clk_disable_unprepare(phy->clk);
-       if (ret)
-               return ret;
 
        return 0;
 }
@@ -78,8 +76,10 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
 
        /* Power up usb phy analog blocks by set siddq 0 */
        ret = rockchip_usb_phy_power(phy, 0);
-       if (ret)
+       if (ret) {
+               clk_disable_unprepare(phy->clk);
                return ret;
+       }
 
        return 0;
 }
index 95c88f929f27f7d4113961e90215f3e769fe75f5..2ba610b72ca202842df7f6b43b18c7da17af1d1c 100644 (file)
@@ -165,15 +165,11 @@ static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
                cpu_relax();
                val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
                if (val & PLL_LOCK)
-                       break;
+                       return 0;
        } while (!time_after(jiffies, timeout));
 
-       if (!(val & PLL_LOCK)) {
-               dev_err(phy->dev, "DPLL failed to lock\n");
-               return -EBUSY;
-       }
-
-       return 0;
+       dev_err(phy->dev, "DPLL failed to lock\n");
+       return -EBUSY;
 }
 
 static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
@@ -608,7 +604,7 @@ static struct platform_driver ti_pipe3_driver = {
 
 module_platform_driver(ti_pipe3_driver);
 
-MODULE_ALIAS("platform: ti_pipe3");
+MODULE_ALIAS("platform:ti_pipe3");
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("TI PIPE3 phy driver");
 MODULE_LICENSE("GPL v2");
index 8e87f54671f32de11915a7921824fc4a8929ab84..bc42d6a8939f4efd85fb1e10ea6d12faa1b76e97 100644 (file)
@@ -666,7 +666,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        twl->dev                = &pdev->dev;
        twl->irq                = platform_get_irq(pdev, 0);
        twl->vbus_supplied      = false;
-       twl->linkstat           = -EINVAL;
        twl->linkstat           = OMAP_MUSB_UNKNOWN;
 
        twl->phy.dev            = twl->dev;
index 29214a36ea28ef0c13ab972693f23e004fa77612..2263cd01003211e6d81a39fcb7a48538ba08e2c1 100644 (file)
@@ -1704,7 +1704,6 @@ static int xgene_phy_probe(struct platform_device *pdev)
        for (i = 0; i < MAX_LANE; i++)
                ctx->sata_param.speed[i] = 2; /* Default to Gen3 */
 
-       ctx->dev = &pdev->dev;
        platform_set_drvdata(pdev, ctx);
 
        ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
index 5afe03e28b911223c8909229d513a7c0e99fef4e..2062c224e32fbe7ee73da7b283205040fbd7164c 100644 (file)
 #define BYT_DIR_MASK           (BIT(1) | BIT(2))
 #define BYT_TRIG_MASK          (BIT(26) | BIT(25) | BIT(24))
 
+#define BYT_CONF0_RESTORE_MASK (BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
+                                BYT_PIN_MUX)
+#define BYT_VAL_RESTORE_MASK   (BYT_DIR_MASK | BYT_LEVEL)
+
 #define BYT_NGPIO_SCORE                102
 #define BYT_NGPIO_NCORE                28
 #define BYT_NGPIO_SUS          44
@@ -134,12 +138,18 @@ static struct pinctrl_gpio_range byt_ranges[] = {
        },
 };
 
+struct byt_gpio_pin_context {
+       u32 conf0;
+       u32 val;
+};
+
 struct byt_gpio {
        struct gpio_chip                chip;
        struct platform_device          *pdev;
        spinlock_t                      lock;
        void __iomem                    *reg_base;
        struct pinctrl_gpio_range       *range;
+       struct byt_gpio_pin_context     *saved_context;
 };
 
 #define to_byt_gpio(c) container_of(c, struct byt_gpio, chip)
@@ -158,40 +168,62 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
        return vg->reg_base + reg_offset + reg;
 }
 
-static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
+static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
+{
+       void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg);
+       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+       writel(value, reg);
+       spin_unlock_irqrestore(&vg->lock, flags);
+}
+
+static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
 {
        /* SCORE pin 92-93 */
        if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
                offset >= 92 && offset <= 93)
-               return true;
+               return 1;
 
        /* SUS pin 11-21 */
        if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
                offset >= 11 && offset <= 21)
-               return true;
+               return 1;
 
-       return false;
+       return 0;
 }
 
 static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
        struct byt_gpio *vg = to_byt_gpio(chip);
        void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
-       u32 value;
-       bool special;
+       u32 value, gpio_mux;
 
        /*
         * In most cases, func pin mux 000 means GPIO function.
         * But, some pins may have func pin mux 001 represents
-        * GPIO function. Only allow user to export pin with
-        * func pin mux preset as GPIO function by BIOS/FW.
+        * GPIO function.
+        *
+        * Because there are devices out there where some pins were not
+        * configured correctly we allow changing the mux value from
+        * request (but print out warning about that).
         */
        value = readl(reg) & BYT_PIN_MUX;
-       special = is_special_pin(vg, offset);
-       if ((special && value != 1) || (!special && value)) {
-               dev_err(&vg->pdev->dev,
-                       "pin %u cannot be used as GPIO.\n", offset);
-               return -EINVAL;
+       gpio_mux = byt_get_gpio_mux(vg, offset);
+       if (WARN_ON(gpio_mux != value)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&vg->lock, flags);
+               value = readl(reg) & ~BYT_PIN_MUX;
+               value |= gpio_mux;
+               writel(value, reg);
+               spin_unlock_irqrestore(&vg->lock, flags);
+
+               dev_warn(&vg->pdev->dev,
+                        "pin %u forcibly re-configured as GPIO\n", offset);
        }
 
        pm_runtime_get(&vg->pdev->dev);
@@ -202,14 +234,8 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
        struct byt_gpio *vg = to_byt_gpio(chip);
-       void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
-       u32 value;
-
-       /* clear interrupt triggering */
-       value = readl(reg);
-       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
-       writel(value, reg);
 
+       byt_gpio_clear_triggering(vg, offset);
        pm_runtime_put(&vg->pdev->dev);
 }
 
@@ -236,23 +262,13 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
        value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
                   BYT_TRIG_LVL);
 
-       switch (type) {
-       case IRQ_TYPE_LEVEL_HIGH:
-               value |= BYT_TRIG_LVL;
-       case IRQ_TYPE_EDGE_RISING:
-               value |= BYT_TRIG_POS;
-               break;
-       case IRQ_TYPE_LEVEL_LOW:
-               value |= BYT_TRIG_LVL;
-       case IRQ_TYPE_EDGE_FALLING:
-               value |= BYT_TRIG_NEG;
-               break;
-       case IRQ_TYPE_EDGE_BOTH:
-               value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
-               break;
-       }
        writel(value, reg);
 
+       if (type & IRQ_TYPE_EDGE_BOTH)
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+       else if (type & IRQ_TYPE_LEVEL_MASK)
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+
        spin_unlock_irqrestore(&vg->lock, flags);
 
        return 0;
@@ -410,58 +426,80 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
        struct irq_chip *chip = irq_data_get_irq_chip(data);
-       u32 base, pin, mask;
+       u32 base, pin;
        void __iomem *reg;
-       u32 pending;
+       unsigned long pending;
        unsigned virq;
-       int looplimit = 0;
 
        /* check from GPIO controller which pin triggered the interrupt */
        for (base = 0; base < vg->chip.ngpio; base += 32) {
-
                reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
-
-               while ((pending = readl(reg))) {
-                       pin = __ffs(pending);
-                       mask = BIT(pin);
-                       /* Clear before handling so we can't lose an edge */
-                       writel(mask, reg);
-
+               pending = readl(reg);
+               for_each_set_bit(pin, &pending, 32) {
                        virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
                        generic_handle_irq(virq);
-
-                       /* In case bios or user sets triggering incorretly a pin
-                        * might remain in "interrupt triggered" state.
-                        */
-                       if (looplimit++ > 32) {
-                               dev_err(&vg->pdev->dev,
-                                       "Gpio %d interrupt flood, disabling\n",
-                                       base + pin);
-
-                               reg = byt_gpio_reg(&vg->chip, base + pin,
-                                                  BYT_CONF0_REG);
-                               mask = readl(reg);
-                               mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
-                                         BYT_TRIG_LVL);
-                               writel(mask, reg);
-                               mask = readl(reg); /* flush */
-                               break;
-                       }
                }
        }
        chip->irq_eoi(data);
 }
 
+static void byt_irq_ack(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct byt_gpio *vg = to_byt_gpio(gc);
+       unsigned offset = irqd_to_hwirq(d);
+       void __iomem *reg;
+
+       reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
+       writel(BIT(offset % 32), reg);
+}
+
 static void byt_irq_unmask(struct irq_data *d)
 {
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct byt_gpio *vg = to_byt_gpio(gc);
+       unsigned offset = irqd_to_hwirq(d);
+       unsigned long flags;
+       void __iomem *reg;
+       u32 value;
+
+       spin_lock_irqsave(&vg->lock, flags);
+
+       reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+       value = readl(reg);
+
+       switch (irqd_get_trigger_type(d)) {
+       case IRQ_TYPE_LEVEL_HIGH:
+               value |= BYT_TRIG_LVL;
+       case IRQ_TYPE_EDGE_RISING:
+               value |= BYT_TRIG_POS;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               value |= BYT_TRIG_LVL;
+       case IRQ_TYPE_EDGE_FALLING:
+               value |= BYT_TRIG_NEG;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
+               break;
+       }
+
+       writel(value, reg);
+
+       spin_unlock_irqrestore(&vg->lock, flags);
 }
 
 static void byt_irq_mask(struct irq_data *d)
 {
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct byt_gpio *vg = to_byt_gpio(gc);
+
+       byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
 }
 
 static struct irq_chip byt_irqchip = {
        .name = "BYT-GPIO",
+       .irq_ack = byt_irq_ack,
        .irq_mask = byt_irq_mask,
        .irq_unmask = byt_irq_unmask,
        .irq_set_type = byt_irq_type,
@@ -472,6 +510,21 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 {
        void __iomem *reg;
        u32 base, value;
+       int i;
+
+       /*
+        * Clear interrupt triggers for all pins that are GPIOs and
+        * do not use direct IRQ mode. This will prevent spurious
+        * interrupts from misconfigured pins.
+        */
+       for (i = 0; i < vg->chip.ngpio; i++) {
+               value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG));
+               if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
+                   !(value & BYT_DIRECT_IRQ_EN)) {
+                       byt_gpio_clear_triggering(vg, i);
+                       dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
+               }
+       }
 
        /* clear interrupt status trigger registers */
        for (base = 0; base < vg->chip.ngpio; base += 32) {
@@ -541,6 +594,11 @@ static int byt_gpio_probe(struct platform_device *pdev)
        gc->can_sleep = false;
        gc->dev = dev;
 
+#ifdef CONFIG_PM_SLEEP
+       vg->saved_context = devm_kcalloc(&pdev->dev, gc->ngpio,
+                                      sizeof(*vg->saved_context), GFP_KERNEL);
+#endif
+
        ret = gpiochip_add(gc);
        if (ret) {
                dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
@@ -569,6 +627,69 @@ static int byt_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int byt_gpio_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < vg->chip.ngpio; i++) {
+               void __iomem *reg;
+               u32 value;
+
+               reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
+               value = readl(reg) & BYT_CONF0_RESTORE_MASK;
+               vg->saved_context[i].conf0 = value;
+
+               reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
+               value = readl(reg) & BYT_VAL_RESTORE_MASK;
+               vg->saved_context[i].val = value;
+       }
+
+       return 0;
+}
+
+static int byt_gpio_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < vg->chip.ngpio; i++) {
+               void __iomem *reg;
+               u32 value;
+
+               reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
+               value = readl(reg);
+               if ((value & BYT_CONF0_RESTORE_MASK) !=
+                    vg->saved_context[i].conf0) {
+                       value &= ~BYT_CONF0_RESTORE_MASK;
+                       value |= vg->saved_context[i].conf0;
+                       writel(value, reg);
+                       dev_info(dev, "restored pin %d conf0 %#08x", i, value);
+               }
+
+               reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
+               value = readl(reg);
+               if ((value & BYT_VAL_RESTORE_MASK) !=
+                    vg->saved_context[i].val) {
+                       u32 v;
+
+                       v = value & ~BYT_VAL_RESTORE_MASK;
+                       v |= vg->saved_context[i].val;
+                       if (v != value) {
+                               writel(v, reg);
+                               dev_dbg(dev, "restored pin %d val %#08x\n",
+                                       i, v);
+                       }
+               }
+       }
+
+       return 0;
+}
+#endif
+
 static int byt_gpio_runtime_suspend(struct device *dev)
 {
        return 0;
@@ -580,8 +701,9 @@ static int byt_gpio_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops byt_gpio_pm_ops = {
-       .runtime_suspend = byt_gpio_runtime_suspend,
-       .runtime_resume = byt_gpio_runtime_resume,
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
+       SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume,
+                          NULL)
 };
 
 static const struct acpi_device_id byt_gpio_acpi_match[] = {
index 3034fd03bced3ff7587f8bfd248c7bb212a0c16c..82f691eeeec4d82cd5e75b7a96be719befbcd57f 100644 (file)
@@ -1226,6 +1226,7 @@ static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
                                     int value)
 {
+       chv_gpio_set(chip, offset, value);
        return pinctrl_gpio_direction_output(chip->base + offset);
 }
 
index f4cd0b9b2438b3548fafa4746b6c6a6cf8874bb4..a4814066ea0876d7f52063f5ba2cfb5ca5a6f6d3 100644 (file)
@@ -1477,28 +1477,25 @@ static void gpio_irq_ack(struct irq_data *d)
        /* the interrupt is already cleared before by reading ISR */
 }
 
-static unsigned int gpio_irq_startup(struct irq_data *d)
+static int gpio_irq_request_res(struct irq_data *d)
 {
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
        unsigned        pin = d->hwirq;
        int ret;
 
        ret = gpiochip_lock_as_irq(&at91_gpio->chip, pin);
-       if (ret) {
+       if (ret)
                dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
                        d->hwirq);
-               return ret;
-       }
-       gpio_irq_unmask(d);
-       return 0;
+
+       return ret;
 }
 
-static void gpio_irq_shutdown(struct irq_data *d)
+static void gpio_irq_release_res(struct irq_data *d)
 {
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
        unsigned        pin = d->hwirq;
 
-       gpio_irq_mask(d);
        gpiochip_unlock_as_irq(&at91_gpio->chip, pin);
 }
 
@@ -1577,8 +1574,8 @@ void at91_pinctrl_gpio_resume(void)
 static struct irq_chip gpio_irqchip = {
        .name           = "GPIO",
        .irq_ack        = gpio_irq_ack,
-       .irq_startup    = gpio_irq_startup,
-       .irq_shutdown   = gpio_irq_shutdown,
+       .irq_request_resources = gpio_irq_request_res,
+       .irq_release_resources = gpio_irq_release_res,
        .irq_disable    = gpio_irq_mask,
        .irq_mask       = gpio_irq_mask,
        .irq_unmask     = gpio_irq_unmask,
index 24c5d88f943f7809910507727ff50d4a43532530..3c68a8e5e0dd4d4bbb8d6fae4166a6bf92e521a2 100644 (file)
@@ -1011,6 +1011,7 @@ static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
        .pins = sun4i_a10_pins,
        .npins = ARRAY_SIZE(sun4i_a10_pins),
        .irq_banks = 1,
+       .irq_read_needs_mux = true,
 };
 
 static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
index 3d07443377362f0b84f59d971dcf73ecdf1d236c..f8e171b7669380d3d1f018124e04488fd4682f8f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 
 #include "../core.h"
+#include "../../gpio/gpiolib.h"
 #include "pinctrl-sunxi.h"
 
 static struct irq_chip sunxi_pinctrl_edge_irq_chip;
@@ -464,10 +465,19 @@ static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
 static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
-
        u32 reg = sunxi_data_reg(offset);
        u8 index = sunxi_data_offset(offset);
-       u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
+       u32 set_mux = pctl->desc->irq_read_needs_mux &&
+                       test_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
+       u32 val;
+
+       if (set_mux)
+               sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_INPUT);
+
+       val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
+
+       if (set_mux)
+               sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_IRQ);
 
        return val;
 }
index 5a51523a34599daba95571cb0d8b2597fdf4f45c..e248e81a0f9e0f8446cbd634040c93632b5e1268 100644 (file)
@@ -77,6 +77,9 @@
 #define IRQ_LEVEL_LOW          0x03
 #define IRQ_EDGE_BOTH          0x04
 
+#define SUN4I_FUNC_INPUT       0
+#define SUN4I_FUNC_IRQ         6
+
 struct sunxi_desc_function {
        const char      *name;
        u8              muxval;
@@ -94,6 +97,7 @@ struct sunxi_pinctrl_desc {
        int                             npins;
        unsigned                        pin_base;
        unsigned                        irq_banks;
+       bool                            irq_read_needs_mux;
 };
 
 struct sunxi_pinctrl_function {
index 97b5e4ee1ca40ae4bc5b50ab7e413833de693af7..63d4033eb683868738dedca38e838fe7e4b56cea 100644 (file)
@@ -73,7 +73,7 @@
 
 #define TIME_WINDOW_MAX_MSEC 40000
 #define TIME_WINDOW_MIN_MSEC 250
-
+#define ENERGY_UNIT_SCALE    1000 /* scale from driver unit to powercap unit */
 enum unit_type {
        ARBITRARY_UNIT, /* no translation */
        POWER_UNIT,
@@ -158,6 +158,7 @@ struct rapl_domain {
        struct rapl_power_limit rpl[NR_POWER_LIMITS];
        u64 attr_map; /* track capabilities */
        unsigned int state;
+       unsigned int domain_energy_unit;
        int package_id;
 };
 #define power_zone_to_rapl_domain(_zone) \
@@ -190,6 +191,7 @@ struct rapl_defaults {
        void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
        u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
                                bool to_raw);
+       unsigned int dram_domain_energy_unit;
 };
 static struct rapl_defaults *rapl_defaults;
 
@@ -227,7 +229,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
 static int rapl_write_data_raw(struct rapl_domain *rd,
                        enum rapl_primitives prim,
                        unsigned long long value);
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+                       enum unit_type type, u64 value,
                        int to_raw);
 static void package_power_limit_irq_save(int package_id);
 
@@ -305,7 +308,9 @@ static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw)
 
 static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
 {
-       *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+       struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
+
+       *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
        return 0;
 }
 
@@ -639,6 +644,11 @@ static void rapl_init_domains(struct rapl_package *rp)
                        rd->msrs[4] = MSR_DRAM_POWER_INFO;
                        rd->rpl[0].prim_id = PL1_ENABLE;
                        rd->rpl[0].name = pl1_name;
+                       rd->domain_energy_unit =
+                               rapl_defaults->dram_domain_energy_unit;
+                       if (rd->domain_energy_unit)
+                               pr_info("DRAM domain energy unit %dpj\n",
+                                       rd->domain_energy_unit);
                        break;
                }
                if (mask) {
@@ -648,11 +658,13 @@ static void rapl_init_domains(struct rapl_package *rp)
        }
 }
 
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+                       enum unit_type type, u64 value,
                        int to_raw)
 {
        u64 units = 1;
        struct rapl_package *rp;
+       u64 scale = 1;
 
        rp = find_package_by_id(package);
        if (!rp)
@@ -663,7 +675,12 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
                units = rp->power_unit;
                break;
        case ENERGY_UNIT:
-               units = rp->energy_unit;
+               scale = ENERGY_UNIT_SCALE;
+               /* per domain unit takes precedence */
+               if (rd && rd->domain_energy_unit)
+                       units = rd->domain_energy_unit;
+               else
+                       units = rp->energy_unit;
                break;
        case TIME_UNIT:
                return rapl_defaults->compute_time_window(rp, value, to_raw);
@@ -673,11 +690,11 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
        };
 
        if (to_raw)
-               return div64_u64(value, units);
+               return div64_u64(value, units) * scale;
 
        value *= units;
 
-       return value;
+       return div64_u64(value, scale);
 }
 
 /* in the order of enum rapl_primitives */
@@ -773,7 +790,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
        final = value & rp->mask;
        final = final >> rp->shift;
        if (xlate)
-               *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0);
+               *data = rapl_unit_xlate(rd, rd->package_id, rp->unit, final, 0);
        else
                *data = final;
 
@@ -799,7 +816,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
                        "failed to read msr 0x%x on cpu %d\n", msr, cpu);
                return -EIO;
        }
-       value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1);
+       value = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1);
        msr_val &= ~rp->mask;
        msr_val |= value << rp->shift;
        if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
@@ -818,7 +835,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
  * calculate units differ on different CPUs.
  * We convert the units to below format based on CPUs.
  * i.e.
- * energy unit: microJoules : Represented in microJoules by default
+ * energy unit: picoJoules  : Represented in picoJoules by default
  * power unit : microWatts  : Represented in milliWatts by default
  * time unit  : microseconds: Represented in seconds by default
  */
@@ -834,7 +851,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
        }
 
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit = 1000000 / (1 << value);
+       rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit = 1000000 / (1 << value);
@@ -842,7 +859,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Core CPU package %d energy=%duJ, time=%dus, power=%duW\n",
+       pr_debug("Core CPU package %d energy=%dpJ, time=%dus, power=%duW\n",
                rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
@@ -859,7 +876,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
                return -ENODEV;
        }
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit = 1 << value;
+       rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit = (1 << value) * 1000;
@@ -867,7 +884,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Atom package %d energy=%duJ, time=%dus, power=%duW\n",
+       pr_debug("Atom package %d energy=%dpJ, time=%dus, power=%duW\n",
                rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
@@ -1017,6 +1034,13 @@ static const struct rapl_defaults rapl_defaults_core = {
        .compute_time_window = rapl_compute_time_window_core,
 };
 
+static const struct rapl_defaults rapl_defaults_hsw_server = {
+       .check_unit = rapl_check_unit_core,
+       .set_floor_freq = set_floor_freq_default,
+       .compute_time_window = rapl_compute_time_window_core,
+       .dram_domain_energy_unit = 15300,
+};
+
 static const struct rapl_defaults rapl_defaults_atom = {
        .check_unit = rapl_check_unit_atom,
        .set_floor_freq = set_floor_freq_atom,
@@ -1037,7 +1061,7 @@ static const struct x86_cpu_id rapl_ids[] = {
        RAPL_CPU(0x3a, rapl_defaults_core),/* Ivy Bridge */
        RAPL_CPU(0x3c, rapl_defaults_core),/* Haswell */
        RAPL_CPU(0x3d, rapl_defaults_core),/* Broadwell */
-       RAPL_CPU(0x3f, rapl_defaults_core),/* Haswell */
+       RAPL_CPU(0x3f, rapl_defaults_hsw_server),/* Haswell servers */
        RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */
        RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */
        RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */
index 1245dca7900901f5b44d2576df9f503d2bc63b76..a4a8a6dc60c470bf6911632a8b14f790cc415ef4 100644 (file)
@@ -1839,10 +1839,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
        }
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, true);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 1;
+               if (!rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, true);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 1;
+               }
        } else if (rdev->desc->ops->enable) {
                ret = rdev->desc->ops->enable(rdev);
                if (ret < 0)
@@ -1939,10 +1941,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
        trace_regulator_disable(rdev_get_name(rdev));
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, false);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 0;
+               if (rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, false);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 0;
+               }
 
        } else if (rdev->desc->ops->disable) {
                ret = rdev->desc->ops->disable(rdev);
@@ -3626,12 +3630,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
                                 config->ena_gpio, ret);
                        goto wash;
                }
-
-               if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
-                       rdev->ena_gpio_state = 1;
-
-               if (config->ena_gpio_invert)
-                       rdev->ena_gpio_state = !rdev->ena_gpio_state;
        }
 
        /* set regulator constraints */
@@ -3800,9 +3798,11 @@ int regulator_suspend_finish(void)
        list_for_each_entry(rdev, &regulator_list, list) {
                mutex_lock(&rdev->mutex);
                if (rdev->use_count > 0  || rdev->constraints->always_on) {
-                       error = _regulator_do_enable(rdev);
-                       if (error)
-                               ret = error;
+                       if (!_regulator_is_enabled(rdev)) {
+                               error = _regulator_do_enable(rdev);
+                               if (error)
+                                       ret = error;
+                       }
                } else {
                        if (!have_full_constraints())
                                goto unlock;
index 9205f433573cc124bd84701f6ee6324969b093e9..18198316b6cf15c406c6f9eb243bc39601b97979 100644 (file)
@@ -1572,6 +1572,10 @@ static int palmas_regulators_probe(struct platform_device *pdev)
        if (!pmic)
                return -ENOMEM;
 
+       if (of_device_is_compatible(node, "ti,tps659038-pmic"))
+               palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
+                                                       TPS659038_REGEN2_CTRL;
+
        pmic->dev = &pdev->dev;
        pmic->palmas = palmas;
        palmas->pmic = pmic;
index e2cffe01b8072263330b28164130cf2fd23953b5..fb991ec764235d55443a9f99414efc3511cad7a2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
index 92f6af6da6991f0f15400b07572b4338458ff8ca..73354ee278771ac0be6fc9fcaa40b96f9964bc9b 100644 (file)
@@ -951,6 +951,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
        void *bufs_va;
        int err = 0, i;
        size_t total_buf_space;
+       bool notify;
 
        vrp = kzalloc(sizeof(*vrp), GFP_KERNEL);
        if (!vrp)
@@ -1030,8 +1031,22 @@ static int rpmsg_probe(struct virtio_device *vdev)
                }
        }
 
+       /*
+        * Prepare to kick but don't notify yet - we can't do this before
+        * device is ready.
+        */
+       notify = virtqueue_kick_prepare(vrp->rvq);
+
+       /* From this point on, we can notify and get callbacks. */
+       virtio_device_ready(vdev);
+
        /* tell the remote processor it can start sending messages */
-       virtqueue_kick(vrp->rvq);
+       /*
+        * this might be concurrent with callbacks, but we are only
+        * doing notify, not a full kick here, so that's ok.
+        */
+       if (notify)
+               virtqueue_notify(vrp->rvq);
 
        dev_info(&vdev->dev, "rpmsg host is online\n");
 
index b4f7744f67510b87be03400d270c7328e6c77912..b283a1a573b30549cb101f763ed430e258a29124 100644 (file)
@@ -324,7 +324,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
 
                ret = IRQ_HANDLED;
        }
-       spin_lock(&suspended_lock);
+       spin_unlock(&suspended_lock);
 
        return ret;
 }
index 9219953ee949a9dfaf1ff0f044e41a3e5c13adc7..d9afc51af7d3dbc7df2e38865596ba3473a1f708 100644 (file)
@@ -6815,7 +6815,8 @@ static struct ata_port_operations ipr_sata_ops = {
 };
 
 static struct ata_port_info sata_port_info = {
-       .flags          = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
+       .flags          = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
+                         ATA_FLAG_SAS_HOST,
        .pio_mask       = ATA_PIO4_ONLY,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA6,
index 932d9cc98d2fc807c4ef0e7715fe922803bbc29c..9c706d8c144174dae8cf87c1aa62a95a98f961e4 100644 (file)
@@ -547,7 +547,8 @@ static struct ata_port_operations sas_sata_ops = {
 };
 
 static struct ata_port_info sata_port_info = {
-       .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ,
+       .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ |
+                ATA_FLAG_SAS_HOST,
        .pio_mask = ATA_PIO4,
        .mwdma_mask = ATA_MWDMA2,
        .udma_mask = ATA_UDMA6,
index 99f43b7fc9ab74256d6f22f17e3c6d75c6e5fcdb..ab4879e12ea7fd0b2745327400b2166451519483 100644 (file)
@@ -1596,7 +1596,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        /*
         * Finally register the new FC Nexus with TCM
         */
-       __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess);
+       transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess);
 
        return 0;
 }
index 3ce39d10fafbc270d47a17107b7cc5ce257dca94..4f8c798e0633a81483c3b05af46805b1848ba386 100644 (file)
@@ -108,7 +108,8 @@ static void dw_spi_dma_tx_done(void *arg)
 {
        struct dw_spi *dws = arg;
 
-       if (test_and_clear_bit(TX_BUSY, &dws->dma_chan_busy) & BIT(RX_BUSY))
+       clear_bit(TX_BUSY, &dws->dma_chan_busy);
+       if (test_bit(RX_BUSY, &dws->dma_chan_busy))
                return;
        dw_spi_xfer_done(dws);
 }
@@ -156,7 +157,8 @@ static void dw_spi_dma_rx_done(void *arg)
 {
        struct dw_spi *dws = arg;
 
-       if (test_and_clear_bit(RX_BUSY, &dws->dma_chan_busy) & BIT(TX_BUSY))
+       clear_bit(RX_BUSY, &dws->dma_chan_busy);
+       if (test_bit(TX_BUSY, &dws->dma_chan_busy))
                return;
        dw_spi_xfer_done(dws);
 }
index ff9cdbdb6672371df54b6c59ce54579a46758602..2b2c359f5a501da32a38af38cfe0c0956b0e23c9 100644 (file)
@@ -498,7 +498,7 @@ static int spi_qup_probe(struct platform_device *pdev)
        struct resource *res;
        struct device *dev;
        void __iomem *base;
-       u32 max_freq, iomode;
+       u32 max_freq, iomode, num_cs;
        int ret, irq, size;
 
        dev = &pdev->dev;
@@ -550,10 +550,11 @@ static int spi_qup_probe(struct platform_device *pdev)
        }
 
        /* use num-cs unless not present or out of range */
-       if (of_property_read_u16(dev->of_node, "num-cs",
-                       &master->num_chipselect) ||
-                       (master->num_chipselect > SPI_NUM_CHIPSELECTS))
+       if (of_property_read_u32(dev->of_node, "num-cs", &num_cs) ||
+           num_cs > SPI_NUM_CHIPSELECTS)
                master->num_chipselect = SPI_NUM_CHIPSELECTS;
+       else
+               master->num_chipselect = num_cs;
 
        master->bus_num = pdev->id;
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
index c64a3e59fce30a7f9658afcca246a6d6872627da..57a195041dc72e019a02b3c7c4b6f4c2a6fac59b 100644 (file)
@@ -1105,13 +1105,14 @@ void spi_finalize_current_message(struct spi_master *master)
                                "failed to unprepare message: %d\n", ret);
                }
        }
+
+       trace_spi_message_done(mesg);
+
        master->cur_msg_prepared = false;
 
        mesg->state = NULL;
        if (mesg->complete)
                mesg->complete(mesg->context);
-
-       trace_spi_message_done(mesg);
 }
 EXPORT_SYMBOL_GPL(spi_finalize_current_message);
 
index 4324282afe499bc83f32318873a6cd484875df1b..03b2a90b9ac0b6f73109686b66623c61f0cd5ccb 100644 (file)
@@ -330,16 +330,6 @@ static void device_init_registers(struct vnt_private *pDevice)
        /* zonetype initial */
        pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 
-       /* Get RFType */
-       pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
-
-       /* force change RevID for VT3253 emu */
-       if ((pDevice->byRFType & RF_EMU) != 0)
-                       pDevice->byRevId = 0x80;
-
-       pDevice->byRFType &= RF_MASK;
-       pr_debug("pDevice->byRFType = %x\n", pDevice->byRFType);
-
        if (!pDevice->bZoneRegExist)
                pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
 
@@ -1187,12 +1177,14 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        PSTxDesc head_td;
-       u32 dma_idx = TYPE_AC0DMA;
+       u32 dma_idx;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (ieee80211_is_data(hdr->frame_control))
+               dma_idx = TYPE_AC0DMA;
+       else
                dma_idx = TYPE_TXDMA0;
 
        if (AVAIL_TD(priv, dma_idx) < 1) {
@@ -1206,6 +1198,9 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 
        head_td->pTDInfo->skb = skb;
 
+       if (dma_idx == TYPE_AC0DMA)
+               head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
+
        priv->iTDUsed[dma_idx]++;
 
        /* Take ownership */
@@ -1234,13 +1229,10 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 
        head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);
 
-       if (dma_idx == TYPE_AC0DMA) {
-               head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
-
+       if (head_td->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
                MACvTransmitAC0(priv->PortOffset);
-       } else {
+       else
                MACvTransmit0(priv->PortOffset);
-       }
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -1778,6 +1770,12 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
        MACvInitialize(priv->PortOffset);
        MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr);
 
+       /* Get RFType */
+       priv->byRFType = SROMbyReadEmbedded(priv->PortOffset, EEP_OFS_RFTYPE);
+       priv->byRFType &= RF_MASK;
+
+       dev_dbg(&pcid->dev, "RF Type = %x\n", priv->byRFType);
+
        device_get_options(priv);
        device_set_options(priv);
        /* Mask out the options cannot be set to the chip */
index 941b2adca95a9d8fbb01bf2afe8a4c99cd1b04fb..7626f635f160799f581b50d3e1e50bbcc7fd8da0 100644 (file)
@@ -794,6 +794,7 @@ bool RFbSetPower(
                break;
        case RATE_6M:
        case RATE_9M:
+       case RATE_12M:
        case RATE_18M:
                byPwr = priv->abyOFDMPwrTbl[uCH];
                if (priv->byRFType == RF_UW2452)
index c42cde59f598efe27f8bff760ce94ca20692a177..c4286ccac32034558966cc52b7fac8501ecc5daa 100644 (file)
@@ -640,6 +640,7 @@ int vnt_rf_setpower(struct vnt_private *priv, u32 rate, u32 channel)
                break;
        case RATE_6M:
        case RATE_9M:
+       case RATE_12M:
        case RATE_18M:
        case RATE_24M:
        case RATE_36M:
index 50bad55a0c42e3bd9eef6925520cb1e9bddf2209..2accb6e47beb35c1eff10256f7a85d749fe6d590 100644 (file)
@@ -4256,11 +4256,17 @@ int iscsit_close_connection(
        pr_debug("Closing iSCSI connection CID %hu on SID:"
                " %u\n", conn->cid, sess->sid);
        /*
-        * Always up conn_logout_comp just in case the RX Thread is sleeping
-        * and the logout response never got sent because the connection
-        * failed.
+        * Always up conn_logout_comp for the traditional TCP case just in case
+        * the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout
+        * response never got sent because the connection failed.
+        *
+        * However for iser-target, isert_wait4logout() is using conn_logout_comp
+        * to signal logout response TX interrupt completion.  Go ahead and skip
+        * this for iser since isert_rx_opcode() does not wait on logout failure,
+        * and to avoid iscsi_conn pointer dereference in iser-target code.
         */
-       complete(&conn->conn_logout_comp);
+       if (conn->conn_transport->transport_type == ISCSI_TCP)
+               complete(&conn->conn_logout_comp);
 
        iscsi_release_thread_set(conn);
 
index 1c197bad6132be98cd267b6ea666fc24e41e00a9..bdd8731a4daa677083d829333fc651591ebca046 100644 (file)
@@ -22,7 +22,6 @@
 #include <target/target_core_fabric.h>
 
 #include <target/iscsi/iscsi_target_core.h>
-#include <target/iscsi/iscsi_transport.h>
 #include "iscsi_target_seq_pdu_list.h"
 #include "iscsi_target_tq.h"
 #include "iscsi_target_erl0.h"
@@ -940,8 +939,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
 
        if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
                spin_unlock_bh(&conn->state_lock);
-               if (conn->conn_transport->transport_type == ISCSI_TCP)
-                       iscsit_close_connection(conn);
+               iscsit_close_connection(conn);
                return;
        }
 
index 6b3c329546895ab1095beb5c048ef24c6e1cea19..c36bd7c29136aba1ea42afbc28cae34c6c7ad6a8 100644 (file)
@@ -953,11 +953,8 @@ static int tcm_loop_make_nexus(
                transport_free_session(tl_nexus->se_sess);
                goto out;
        }
-       /*
-        * Now, register the SAS I_T Nexus as active with the call to
-        * transport_register_session()
-        */
-       __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
+       /* Now, register the SAS I_T Nexus as active. */
+       transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
                        tl_nexus->se_sess, tl_nexus);
        tl_tpg->tl_nexus = tl_nexus;
        pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
index 58f49ff69b1424bf5feb33ed64eba495d8826851..79b4ec3ca2db12416a692fba785a09b462e3169f 100644 (file)
@@ -650,6 +650,18 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
        return aligned_max_sectors;
 }
 
+bool se_dev_check_wce(struct se_device *dev)
+{
+       bool wce = false;
+
+       if (dev->transport->get_write_cache)
+               wce = dev->transport->get_write_cache(dev);
+       else if (dev->dev_attrib.emulate_write_cache > 0)
+               wce = true;
+
+       return wce;
+}
+
 int se_dev_set_max_unmap_lba_count(
        struct se_device *dev,
        u32 max_unmap_lba_count)
@@ -767,6 +779,16 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
                pr_err("Illegal value %d\n", flag);
                return -EINVAL;
        }
+       if (flag &&
+           dev->transport->get_write_cache) {
+               pr_err("emulate_fua_write not supported for this device\n");
+               return -EINVAL;
+       }
+       if (dev->export_count) {
+               pr_err("emulate_fua_write cannot be changed with active"
+                      " exports: %d\n", dev->export_count);
+               return -EINVAL;
+       }
        dev->dev_attrib.emulate_fua_write = flag;
        pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n",
                        dev, dev->dev_attrib.emulate_fua_write);
@@ -801,7 +823,11 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
                pr_err("emulate_write_cache not supported for this device\n");
                return -EINVAL;
        }
-
+       if (dev->export_count) {
+               pr_err("emulate_write_cache cannot be changed with active"
+                      " exports: %d\n", dev->export_count);
+               return -EINVAL;
+       }
        dev->dev_attrib.emulate_write_cache = flag;
        pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n",
                        dev, dev->dev_attrib.emulate_write_cache);
@@ -1534,8 +1560,6 @@ int target_configure_device(struct se_device *dev)
        ret = dev->transport->configure_device(dev);
        if (ret)
                goto out;
-       dev->dev_flags |= DF_CONFIGURED;
-
        /*
         * XXX: there is not much point to have two different values here..
         */
@@ -1597,6 +1621,8 @@ int target_configure_device(struct se_device *dev)
        list_add_tail(&dev->g_dev_node, &g_device_list);
        mutex_unlock(&g_device_mutex);
 
+       dev->dev_flags |= DF_CONFIGURED;
+
        return 0;
 
 out_free_alua:
index 1045dcd7bf651b679ee355a19401065d559976b1..f6c954c4635f5dab27ac24ea117dd284561c836a 100644 (file)
@@ -1121,7 +1121,7 @@ static u32 pscsi_get_device_type(struct se_device *dev)
        struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
        struct scsi_device *sd = pdv->pdv_sd;
 
-       return sd->type;
+       return (sd) ? sd->type : TYPE_NO_LUN;
 }
 
 static sector_t pscsi_get_blocks(struct se_device *dev)
index 9a2f9d3a6e70514ad9351ab6e144709e8b95f91d..3e729741111075cf4828a46ac2f434414e70faf1 100644 (file)
@@ -708,8 +708,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
                }
        }
        if (cdb[1] & 0x8) {
-               if (!dev->dev_attrib.emulate_fua_write ||
-                   !dev->dev_attrib.emulate_write_cache) {
+               if (!dev->dev_attrib.emulate_fua_write || !se_dev_check_wce(dev)) {
                        pr_err("Got CDB: 0x%02x with FUA bit set, but device"
                               " does not advertise support for FUA write\n",
                               cdb[0]);
index 460e9310947399661ce1fbd6ab4ed3e86b4a47e1..6c8bd6bc175ca48fb9d33063dc3f3b8185d19876 100644 (file)
@@ -454,19 +454,6 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 }
 EXPORT_SYMBOL(spc_emulate_evpd_83);
 
-static bool
-spc_check_dev_wce(struct se_device *dev)
-{
-       bool wce = false;
-
-       if (dev->transport->get_write_cache)
-               wce = dev->transport->get_write_cache(dev);
-       else if (dev->dev_attrib.emulate_write_cache > 0)
-               wce = true;
-
-       return wce;
-}
-
 /* Extended INQUIRY Data VPD Page */
 static sense_reason_t
 spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
@@ -490,7 +477,7 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
        buf[5] = 0x07;
 
        /* If WriteCache emulation is enabled, set V_SUP */
-       if (spc_check_dev_wce(dev))
+       if (se_dev_check_wce(dev))
                buf[6] = 0x01;
        /* If an LBA map is present set R_SUP */
        spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
@@ -897,7 +884,7 @@ static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p)
        if (pc == 1)
                goto out;
 
-       if (spc_check_dev_wce(dev))
+       if (se_dev_check_wce(dev))
                p[2] = 0x04; /* Write Cache Enable */
        p[12] = 0x20; /* Disabled Read Ahead */
 
@@ -1009,7 +996,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
             (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
                spc_modesense_write_protect(&buf[length], type);
 
-       if ((spc_check_dev_wce(dev)) &&
+       if ((se_dev_check_wce(dev)) &&
            (dev->dev_attrib.emulate_fua_write > 0))
                spc_modesense_dpofua(&buf[length], type);
 
index 0adc0f6502134eb3292a7a2cab66ac75be4d6406..ac3cbabdbdf0243ecbfd91c01e331ee3e0013a1a 100644 (file)
@@ -2389,6 +2389,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
        list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
 out:
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
+       if (ret && ack_kref)
+               target_put_sess_cmd(se_sess, se_cmd);
+
        return ret;
 }
 EXPORT_SYMBOL(target_get_sess_cmd);
index 97b486c3dda136a21824d02ea0f70c828b214d46..583e755d809177d59953b991a9c8dd9068649205 100644 (file)
@@ -359,7 +359,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd)
                ep = fc_seq_exch(seq);
                if (ep) {
                        lport = ep->lp;
-                       if (lport && (ep->xid <= lport->lro_xid))
+                       if (lport && (ep->xid <= lport->lro_xid)) {
                                /*
                                 * "ddp_done" trigger invalidation of HW
                                 * specific DDP context
@@ -374,6 +374,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd)
                                 * identified using ep->xid)
                                 */
                                cmd->was_ddp_setup = 0;
+                       }
                }
        }
 }
index 2ab229ddee389ee20fa7923f93e43ddda944bbf0..6ae5b8560e4d764cafb8143a8a4654a81bf21f83 100644 (file)
@@ -119,7 +119,10 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 
@@ -163,7 +166,10 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
                        __raw_writeq(value & 0xff,
                                     p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 #endif /* CONFIG_64BIT */
@@ -187,7 +193,10 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 
index ff451048c1aca26d14cd23a40b344810134695cf..4bfb7ac0239f9b4bac46ec3246ff99f29e4dcc2a 100644 (file)
@@ -929,6 +929,13 @@ __acquires(hwep->lock)
        return retval;
 }
 
+static int otg_a_alt_hnp_support(struct ci_hdrc *ci)
+{
+       dev_warn(&ci->gadget.dev,
+               "connect the device to an alternate port if you want HNP\n");
+       return isr_setup_status_phase(ci);
+}
+
 /**
  * isr_setup_packet_handler: setup packet handler
  * @ci: UDC descriptor
@@ -1061,6 +1068,10 @@ __acquires(ci->lock)
                                                        ci);
                                }
                                break;
+                       case USB_DEVICE_A_ALT_HNP_SUPPORT:
+                               if (ci_otg_is_fsm_mode(ci))
+                                       err = otg_a_alt_hnp_support(ci);
+                               break;
                        default:
                                goto delegate;
                        }
index c6b35b77dab73a173eb08d2522d4d961bebc7163..61d538aa23466b62ddf37eec8567460ecf0cd363 100644 (file)
@@ -150,9 +150,9 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
                break;
        case OTG_STATE_B_PERIPHERAL:
                otg_chrg_vbus(fsm, 0);
-               otg_loc_conn(fsm, 1);
                otg_loc_sof(fsm, 0);
                otg_set_protocol(fsm, PROTO_GADGET);
+               otg_loc_conn(fsm, 1);
                break;
        case OTG_STATE_B_WAIT_ACON:
                otg_chrg_vbus(fsm, 0);
@@ -213,10 +213,10 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 
                break;
        case OTG_STATE_A_PERIPHERAL:
-               otg_loc_conn(fsm, 1);
                otg_loc_sof(fsm, 0);
                otg_set_protocol(fsm, PROTO_GADGET);
                otg_drv_vbus(fsm, 1);
+               otg_loc_conn(fsm, 1);
                otg_add_timer(fsm, A_BIDL_ADIS);
                break;
        case OTG_STATE_A_WAIT_VFALL:
index 02e3e2d4ea5658c0ddd6de8b1cb1729425a3c0ab..6cf047878dbae1812d19c27b13d5d5a1ce71536a 100644 (file)
@@ -377,6 +377,9 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
                dwc2_is_host_mode(hsotg) ? "Host" : "Device",
                dwc2_op_state_str(hsotg));
 
+       if (hsotg->op_state == OTG_STATE_A_HOST)
+               dwc2_hcd_disconnect(hsotg);
+
        /* Change to L3 (OFF) state */
        hsotg->lx_state = DWC2_L3;
 
index 298b46112b1a354eaa2965edc548b10b628ac577..39f49f1ad22f287e58df631077a9a1506381707b 100644 (file)
@@ -289,8 +289,7 @@ static void disable_loopback(struct f_loopback *loop)
        struct usb_composite_dev        *cdev;
 
        cdev = loop->function.config->cdev;
-       disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL, NULL,
-                       NULL);
+       disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
        VDBG(cdev, "%s disabled\n", loop->function.name);
 }
 
index e3dae47baef3d3bfcf8d7dc5124cc22bbcc8a272..3a5ae9900b1ee585881aa8233065ef9772de8da7 100644 (file)
 #include "gadget_chips.h"
 #include "u_f.h"
 
-#define USB_MS_TO_SS_INTERVAL(x) USB_MS_TO_HS_INTERVAL(x)
-
-enum eptype {
-       EP_CONTROL = 0,
-       EP_BULK,
-       EP_ISOC,
-       EP_INTERRUPT,
-};
-
 /*
  * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
  * controller drivers.
@@ -64,8 +55,6 @@ struct f_sourcesink {
        struct usb_ep           *out_ep;
        struct usb_ep           *iso_in_ep;
        struct usb_ep           *iso_out_ep;
-       struct usb_ep           *int_in_ep;
-       struct usb_ep           *int_out_ep;
        int                     cur_alt;
 };
 
@@ -79,10 +68,6 @@ static unsigned isoc_interval;
 static unsigned isoc_maxpacket;
 static unsigned isoc_mult;
 static unsigned isoc_maxburst;
-static unsigned int_interval; /* In ms */
-static unsigned int_maxpacket;
-static unsigned int_mult;
-static unsigned int_maxburst;
 static unsigned buflen;
 
 /*-------------------------------------------------------------------------*/
@@ -107,16 +92,6 @@ static struct usb_interface_descriptor source_sink_intf_alt1 = {
        /* .iInterface          = DYNAMIC */
 };
 
-static struct usb_interface_descriptor source_sink_intf_alt2 = {
-       .bLength =              USB_DT_INTERFACE_SIZE,
-       .bDescriptorType =      USB_DT_INTERFACE,
-
-       .bAlternateSetting =    2,
-       .bNumEndpoints =        2,
-       .bInterfaceClass =      USB_CLASS_VENDOR_SPEC,
-       /* .iInterface          = DYNAMIC */
-};
-
 /* full speed support: */
 
 static struct usb_endpoint_descriptor fs_source_desc = {
@@ -155,26 +130,6 @@ static struct usb_endpoint_descriptor fs_iso_sink_desc = {
        .bInterval =            4,
 };
 
-static struct usb_endpoint_descriptor fs_int_source_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bEndpointAddress =     USB_DIR_IN,
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(64),
-       .bInterval =            GZERO_INT_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor fs_int_sink_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bEndpointAddress =     USB_DIR_OUT,
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(64),
-       .bInterval =            GZERO_INT_INTERVAL,
-};
-
 static struct usb_descriptor_header *fs_source_sink_descs[] = {
        (struct usb_descriptor_header *) &source_sink_intf_alt0,
        (struct usb_descriptor_header *) &fs_sink_desc,
@@ -185,10 +140,6 @@ static struct usb_descriptor_header *fs_source_sink_descs[] = {
        (struct usb_descriptor_header *) &fs_source_desc,
        (struct usb_descriptor_header *) &fs_iso_sink_desc,
        (struct usb_descriptor_header *) &fs_iso_source_desc,
-       (struct usb_descriptor_header *) &source_sink_intf_alt2,
-#define FS_ALT_IFC_2_OFFSET    8
-       (struct usb_descriptor_header *) &fs_int_sink_desc,
-       (struct usb_descriptor_header *) &fs_int_source_desc,
        NULL,
 };
 
@@ -228,24 +179,6 @@ static struct usb_endpoint_descriptor hs_iso_sink_desc = {
        .bInterval =            4,
 };
 
-static struct usb_endpoint_descriptor hs_int_source_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-       .bInterval =            USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL),
-};
-
-static struct usb_endpoint_descriptor hs_int_sink_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-       .bInterval =            USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL),
-};
-
 static struct usb_descriptor_header *hs_source_sink_descs[] = {
        (struct usb_descriptor_header *) &source_sink_intf_alt0,
        (struct usb_descriptor_header *) &hs_source_desc,
@@ -256,10 +189,6 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = {
        (struct usb_descriptor_header *) &hs_sink_desc,
        (struct usb_descriptor_header *) &hs_iso_source_desc,
        (struct usb_descriptor_header *) &hs_iso_sink_desc,
-       (struct usb_descriptor_header *) &source_sink_intf_alt2,
-#define HS_ALT_IFC_2_OFFSET    8
-       (struct usb_descriptor_header *) &hs_int_source_desc,
-       (struct usb_descriptor_header *) &hs_int_sink_desc,
        NULL,
 };
 
@@ -335,42 +264,6 @@ static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
        .wBytesPerInterval =    cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor ss_int_source_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-       .bInterval =            USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL),
-};
-
-static struct usb_ss_ep_comp_descriptor ss_int_source_comp_desc = {
-       .bLength =              USB_DT_SS_EP_COMP_SIZE,
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-
-       .bMaxBurst =            0,
-       .bmAttributes =         0,
-       .wBytesPerInterval =    cpu_to_le16(1024),
-};
-
-static struct usb_endpoint_descriptor ss_int_sink_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-       .bInterval =            USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL),
-};
-
-static struct usb_ss_ep_comp_descriptor ss_int_sink_comp_desc = {
-       .bLength =              USB_DT_SS_EP_COMP_SIZE,
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-
-       .bMaxBurst =            0,
-       .bmAttributes =         0,
-       .wBytesPerInterval =    cpu_to_le16(1024),
-};
-
 static struct usb_descriptor_header *ss_source_sink_descs[] = {
        (struct usb_descriptor_header *) &source_sink_intf_alt0,
        (struct usb_descriptor_header *) &ss_source_desc,
@@ -387,12 +280,6 @@ static struct usb_descriptor_header *ss_source_sink_descs[] = {
        (struct usb_descriptor_header *) &ss_iso_source_comp_desc,
        (struct usb_descriptor_header *) &ss_iso_sink_desc,
        (struct usb_descriptor_header *) &ss_iso_sink_comp_desc,
-       (struct usb_descriptor_header *) &source_sink_intf_alt2,
-#define SS_ALT_IFC_2_OFFSET    14
-       (struct usb_descriptor_header *) &ss_int_source_desc,
-       (struct usb_descriptor_header *) &ss_int_source_comp_desc,
-       (struct usb_descriptor_header *) &ss_int_sink_desc,
-       (struct usb_descriptor_header *) &ss_int_sink_comp_desc,
        NULL,
 };
 
@@ -414,21 +301,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
 };
 
 /*-------------------------------------------------------------------------*/
-static const char *get_ep_string(enum eptype ep_type)
-{
-       switch (ep_type) {
-       case EP_ISOC:
-               return "ISOC-";
-       case EP_INTERRUPT:
-               return "INTERRUPT-";
-       case EP_CONTROL:
-               return "CTRL-";
-       case EP_BULK:
-               return "BULK-";
-       default:
-               return "UNKNOWN-";
-       }
-}
 
 static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
 {
@@ -456,8 +328,7 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 
 void disable_endpoints(struct usb_composite_dev *cdev,
                struct usb_ep *in, struct usb_ep *out,
-               struct usb_ep *iso_in, struct usb_ep *iso_out,
-               struct usb_ep *int_in, struct usb_ep *int_out)
+               struct usb_ep *iso_in, struct usb_ep *iso_out)
 {
        disable_ep(cdev, in);
        disable_ep(cdev, out);
@@ -465,10 +336,6 @@ void disable_endpoints(struct usb_composite_dev *cdev,
                disable_ep(cdev, iso_in);
        if (iso_out)
                disable_ep(cdev, iso_out);
-       if (int_in)
-               disable_ep(cdev, int_in);
-       if (int_out)
-               disable_ep(cdev, int_out);
 }
 
 static int
@@ -485,7 +352,6 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
                return id;
        source_sink_intf_alt0.bInterfaceNumber = id;
        source_sink_intf_alt1.bInterfaceNumber = id;
-       source_sink_intf_alt2.bInterfaceNumber = id;
 
        /* allocate bulk endpoints */
        ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
@@ -546,55 +412,14 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
        if (isoc_maxpacket > 1024)
                isoc_maxpacket = 1024;
 
-       /* sanity check the interrupt module parameters */
-       if (int_interval < 1)
-               int_interval = 1;
-       if (int_interval > 4096)
-               int_interval = 4096;
-       if (int_mult > 2)
-               int_mult = 2;
-       if (int_maxburst > 15)
-               int_maxburst = 15;
-
-       /* fill in the FS interrupt descriptors from the module parameters */
-       fs_int_source_desc.wMaxPacketSize = int_maxpacket > 64 ?
-                                               64 : int_maxpacket;
-       fs_int_source_desc.bInterval = int_interval > 255 ?
-                                               255 : int_interval;
-       fs_int_sink_desc.wMaxPacketSize = int_maxpacket > 64 ?
-                                               64 : int_maxpacket;
-       fs_int_sink_desc.bInterval = int_interval > 255 ?
-                                               255 : int_interval;
-
-       /* allocate int endpoints */
-       ss->int_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_source_desc);
-       if (!ss->int_in_ep)
-               goto no_int;
-       ss->int_in_ep->driver_data = cdev;      /* claim */
-
-       ss->int_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_sink_desc);
-       if (ss->int_out_ep) {
-               ss->int_out_ep->driver_data = cdev;     /* claim */
-       } else {
-               ss->int_in_ep->driver_data = NULL;
-               ss->int_in_ep = NULL;
-no_int:
-               fs_source_sink_descs[FS_ALT_IFC_2_OFFSET] = NULL;
-               hs_source_sink_descs[HS_ALT_IFC_2_OFFSET] = NULL;
-               ss_source_sink_descs[SS_ALT_IFC_2_OFFSET] = NULL;
-       }
-
-       if (int_maxpacket > 1024)
-               int_maxpacket = 1024;
-
        /* support high speed hardware */
        hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
        hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 
        /*
-        * Fill in the HS isoc and interrupt descriptors from the module
-        * parameters. We assume that the user knows what they are doing and
-        * won't give parameters that their UDC doesn't support.
+        * Fill in the HS isoc descriptors from the module parameters.
+        * We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
         */
        hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
        hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
@@ -607,17 +432,6 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
        hs_iso_sink_desc.bInterval = isoc_interval;
        hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
-       hs_int_source_desc.wMaxPacketSize = int_maxpacket;
-       hs_int_source_desc.wMaxPacketSize |= int_mult << 11;
-       hs_int_source_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval);
-       hs_int_source_desc.bEndpointAddress =
-               fs_int_source_desc.bEndpointAddress;
-
-       hs_int_sink_desc.wMaxPacketSize = int_maxpacket;
-       hs_int_sink_desc.wMaxPacketSize |= int_mult << 11;
-       hs_int_sink_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval);
-       hs_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress;
-
        /* support super speed hardware */
        ss_source_desc.bEndpointAddress =
                fs_source_desc.bEndpointAddress;
@@ -625,9 +439,9 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
                fs_sink_desc.bEndpointAddress;
 
        /*
-        * Fill in the SS isoc and interrupt descriptors from the module
-        * parameters. We assume that the user knows what they are doing and
-        * won't give parameters that their UDC doesn't support.
+        * Fill in the SS isoc descriptors from the module parameters.
+        * We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
         */
        ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
        ss_iso_source_desc.bInterval = isoc_interval;
@@ -646,37 +460,17 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
                isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
        ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
-       ss_int_source_desc.wMaxPacketSize = int_maxpacket;
-       ss_int_source_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval);
-       ss_int_source_comp_desc.bmAttributes = int_mult;
-       ss_int_source_comp_desc.bMaxBurst = int_maxburst;
-       ss_int_source_comp_desc.wBytesPerInterval =
-               int_maxpacket * (int_mult + 1) * (int_maxburst + 1);
-       ss_int_source_desc.bEndpointAddress =
-               fs_int_source_desc.bEndpointAddress;
-
-       ss_int_sink_desc.wMaxPacketSize = int_maxpacket;
-       ss_int_sink_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval);
-       ss_int_sink_comp_desc.bmAttributes = int_mult;
-       ss_int_sink_comp_desc.bMaxBurst = int_maxburst;
-       ss_int_sink_comp_desc.wBytesPerInterval =
-               int_maxpacket * (int_mult + 1) * (int_maxburst + 1);
-       ss_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress;
-
        ret = usb_assign_descriptors(f, fs_source_sink_descs,
                        hs_source_sink_descs, ss_source_sink_descs);
        if (ret)
                return ret;
 
-       DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s, "
-                       "INT-IN/%s, INT-OUT/%s\n",
+       DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
            (gadget_is_superspeed(c->cdev->gadget) ? "super" :
             (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
                        f->name, ss->in_ep->name, ss->out_ep->name,
                        ss->iso_in_ep ? ss->iso_in_ep->name : "<none>",
-                       ss->iso_out_ep ? ss->iso_out_ep->name : "<none>",
-                       ss->int_in_ep ? ss->int_in_ep->name : "<none>",
-                       ss->int_out_ep ? ss->int_out_ep->name : "<none>");
+                       ss->iso_out_ep ? ss->iso_out_ep->name : "<none>");
        return 0;
 }
 
@@ -807,15 +601,14 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
 }
 
 static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
-               enum eptype ep_type, int speed)
+               bool is_iso, int speed)
 {
        struct usb_ep           *ep;
        struct usb_request      *req;
        int                     i, size, status;
 
        for (i = 0; i < 8; i++) {
-               switch (ep_type) {
-               case EP_ISOC:
+               if (is_iso) {
                        switch (speed) {
                        case USB_SPEED_SUPER:
                                size = isoc_maxpacket * (isoc_mult + 1) *
@@ -831,28 +624,9 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
                        }
                        ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
                        req = ss_alloc_ep_req(ep, size);
-                       break;
-               case EP_INTERRUPT:
-                       switch (speed) {
-                       case USB_SPEED_SUPER:
-                               size = int_maxpacket * (int_mult + 1) *
-                                               (int_maxburst + 1);
-                               break;
-                       case USB_SPEED_HIGH:
-                               size = int_maxpacket * (int_mult + 1);
-                               break;
-                       default:
-                               size = int_maxpacket > 1023 ?
-                                               1023 : int_maxpacket;
-                               break;
-                       }
-                       ep = is_in ? ss->int_in_ep : ss->int_out_ep;
-                       req = ss_alloc_ep_req(ep, size);
-                       break;
-               default:
+               } else {
                        ep = is_in ? ss->in_ep : ss->out_ep;
                        req = ss_alloc_ep_req(ep, 0);
-                       break;
                }
 
                if (!req)
@@ -870,12 +644,12 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
 
                        cdev = ss->function.config->cdev;
                        ERROR(cdev, "start %s%s %s --> %d\n",
-                               get_ep_string(ep_type), is_in ? "IN" : "OUT",
-                               ep->name, status);
+                             is_iso ? "ISO-" : "", is_in ? "IN" : "OUT",
+                             ep->name, status);
                        free_ep_req(ep, req);
                }
 
-               if (!(ep_type == EP_ISOC))
+               if (!is_iso)
                        break;
        }
 
@@ -888,7 +662,7 @@ static void disable_source_sink(struct f_sourcesink *ss)
 
        cdev = ss->function.config->cdev;
        disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep,
-                       ss->iso_out_ep, ss->int_in_ep, ss->int_out_ep);
+                       ss->iso_out_ep);
        VDBG(cdev, "%s disabled\n", ss->function.name);
 }
 
@@ -900,62 +674,6 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
        int                                     speed = cdev->gadget->speed;
        struct usb_ep                           *ep;
 
-       if (alt == 2) {
-               /* Configure for periodic interrupt endpoint */
-               ep = ss->int_in_ep;
-               if (ep) {
-                       result = config_ep_by_speed(cdev->gadget,
-                                       &(ss->function), ep);
-                       if (result)
-                               return result;
-
-                       result = usb_ep_enable(ep);
-                       if (result < 0)
-                               return result;
-
-                       ep->driver_data = ss;
-                       result = source_sink_start_ep(ss, true, EP_INTERRUPT,
-                                       speed);
-                       if (result < 0) {
-fail1:
-                               ep = ss->int_in_ep;
-                               if (ep) {
-                                       usb_ep_disable(ep);
-                                       ep->driver_data = NULL;
-                               }
-                               return result;
-                       }
-               }
-
-               /*
-                * one interrupt endpoint reads (sinks) anything OUT (from the
-                * host)
-                */
-               ep = ss->int_out_ep;
-               if (ep) {
-                       result = config_ep_by_speed(cdev->gadget,
-                                       &(ss->function), ep);
-                       if (result)
-                               goto fail1;
-
-                       result = usb_ep_enable(ep);
-                       if (result < 0)
-                               goto fail1;
-
-                       ep->driver_data = ss;
-                       result = source_sink_start_ep(ss, false, EP_INTERRUPT,
-                                       speed);
-                       if (result < 0) {
-                               ep = ss->int_out_ep;
-                               usb_ep_disable(ep);
-                               ep->driver_data = NULL;
-                               goto fail1;
-                       }
-               }
-
-               goto out;
-       }
-
        /* one bulk endpoint writes (sources) zeroes IN (to the host) */
        ep = ss->in_ep;
        result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
@@ -966,7 +684,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
                return result;
        ep->driver_data = ss;
 
-       result = source_sink_start_ep(ss, true, EP_BULK, speed);
+       result = source_sink_start_ep(ss, true, false, speed);
        if (result < 0) {
 fail:
                ep = ss->in_ep;
@@ -985,7 +703,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
                goto fail;
        ep->driver_data = ss;
 
-       result = source_sink_start_ep(ss, false, EP_BULK, speed);
+       result = source_sink_start_ep(ss, false, false, speed);
        if (result < 0) {
 fail2:
                ep = ss->out_ep;
@@ -1008,7 +726,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
                        goto fail2;
                ep->driver_data = ss;
 
-               result = source_sink_start_ep(ss, true, EP_ISOC, speed);
+               result = source_sink_start_ep(ss, true, true, speed);
                if (result < 0) {
 fail3:
                        ep = ss->iso_in_ep;
@@ -1031,14 +749,13 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
                        goto fail3;
                ep->driver_data = ss;
 
-               result = source_sink_start_ep(ss, false, EP_ISOC, speed);
+               result = source_sink_start_ep(ss, false, true, speed);
                if (result < 0) {
                        usb_ep_disable(ep);
                        ep->driver_data = NULL;
                        goto fail3;
                }
        }
-
 out:
        ss->cur_alt = alt;
 
@@ -1054,8 +771,6 @@ static int sourcesink_set_alt(struct usb_function *f,
 
        if (ss->in_ep->driver_data)
                disable_source_sink(ss);
-       else if (alt == 2 && ss->int_in_ep->driver_data)
-               disable_source_sink(ss);
        return enable_source_sink(cdev, ss, alt);
 }
 
@@ -1168,10 +883,6 @@ static struct usb_function *source_sink_alloc_func(
        isoc_maxpacket = ss_opts->isoc_maxpacket;
        isoc_mult = ss_opts->isoc_mult;
        isoc_maxburst = ss_opts->isoc_maxburst;
-       int_interval = ss_opts->int_interval;
-       int_maxpacket = ss_opts->int_maxpacket;
-       int_mult = ss_opts->int_mult;
-       int_maxburst = ss_opts->int_maxburst;
        buflen = ss_opts->bulk_buflen;
 
        ss->function.name = "source/sink";
@@ -1468,182 +1179,6 @@ static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
                        f_ss_opts_bulk_buflen_show,
                        f_ss_opts_bulk_buflen_store);
 
-static ssize_t f_ss_opts_int_interval_show(struct f_ss_opts *opts, char *page)
-{
-       int result;
-
-       mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->int_interval);
-       mutex_unlock(&opts->lock);
-
-       return result;
-}
-
-static ssize_t f_ss_opts_int_interval_store(struct f_ss_opts *opts,
-                                      const char *page, size_t len)
-{
-       int ret;
-       u32 num;
-
-       mutex_lock(&opts->lock);
-       if (opts->refcnt) {
-               ret = -EBUSY;
-               goto end;
-       }
-
-       ret = kstrtou32(page, 0, &num);
-       if (ret)
-               goto end;
-
-       if (num > 4096) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       opts->int_interval = num;
-       ret = len;
-end:
-       mutex_unlock(&opts->lock);
-       return ret;
-}
-
-static struct f_ss_opts_attribute f_ss_opts_int_interval =
-       __CONFIGFS_ATTR(int_interval, S_IRUGO | S_IWUSR,
-                       f_ss_opts_int_interval_show,
-                       f_ss_opts_int_interval_store);
-
-static ssize_t f_ss_opts_int_maxpacket_show(struct f_ss_opts *opts, char *page)
-{
-       int result;
-
-       mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->int_maxpacket);
-       mutex_unlock(&opts->lock);
-
-       return result;
-}
-
-static ssize_t f_ss_opts_int_maxpacket_store(struct f_ss_opts *opts,
-                                      const char *page, size_t len)
-{
-       int ret;
-       u16 num;
-
-       mutex_lock(&opts->lock);
-       if (opts->refcnt) {
-               ret = -EBUSY;
-               goto end;
-       }
-
-       ret = kstrtou16(page, 0, &num);
-       if (ret)
-               goto end;
-
-       if (num > 1024) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       opts->int_maxpacket = num;
-       ret = len;
-end:
-       mutex_unlock(&opts->lock);
-       return ret;
-}
-
-static struct f_ss_opts_attribute f_ss_opts_int_maxpacket =
-       __CONFIGFS_ATTR(int_maxpacket, S_IRUGO | S_IWUSR,
-                       f_ss_opts_int_maxpacket_show,
-                       f_ss_opts_int_maxpacket_store);
-
-static ssize_t f_ss_opts_int_mult_show(struct f_ss_opts *opts, char *page)
-{
-       int result;
-
-       mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->int_mult);
-       mutex_unlock(&opts->lock);
-
-       return result;
-}
-
-static ssize_t f_ss_opts_int_mult_store(struct f_ss_opts *opts,
-                                      const char *page, size_t len)
-{
-       int ret;
-       u8 num;
-
-       mutex_lock(&opts->lock);
-       if (opts->refcnt) {
-               ret = -EBUSY;
-               goto end;
-       }
-
-       ret = kstrtou8(page, 0, &num);
-       if (ret)
-               goto end;
-
-       if (num > 2) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       opts->int_mult = num;
-       ret = len;
-end:
-       mutex_unlock(&opts->lock);
-       return ret;
-}
-
-static struct f_ss_opts_attribute f_ss_opts_int_mult =
-       __CONFIGFS_ATTR(int_mult, S_IRUGO | S_IWUSR,
-                       f_ss_opts_int_mult_show,
-                       f_ss_opts_int_mult_store);
-
-static ssize_t f_ss_opts_int_maxburst_show(struct f_ss_opts *opts, char *page)
-{
-       int result;
-
-       mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->int_maxburst);
-       mutex_unlock(&opts->lock);
-
-       return result;
-}
-
-static ssize_t f_ss_opts_int_maxburst_store(struct f_ss_opts *opts,
-                                      const char *page, size_t len)
-{
-       int ret;
-       u8 num;
-
-       mutex_lock(&opts->lock);
-       if (opts->refcnt) {
-               ret = -EBUSY;
-               goto end;
-       }
-
-       ret = kstrtou8(page, 0, &num);
-       if (ret)
-               goto end;
-
-       if (num > 15) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       opts->int_maxburst = num;
-       ret = len;
-end:
-       mutex_unlock(&opts->lock);
-       return ret;
-}
-
-static struct f_ss_opts_attribute f_ss_opts_int_maxburst =
-       __CONFIGFS_ATTR(int_maxburst, S_IRUGO | S_IWUSR,
-                       f_ss_opts_int_maxburst_show,
-                       f_ss_opts_int_maxburst_store);
-
 static struct configfs_attribute *ss_attrs[] = {
        &f_ss_opts_pattern.attr,
        &f_ss_opts_isoc_interval.attr,
@@ -1651,10 +1186,6 @@ static struct configfs_attribute *ss_attrs[] = {
        &f_ss_opts_isoc_mult.attr,
        &f_ss_opts_isoc_maxburst.attr,
        &f_ss_opts_bulk_buflen.attr,
-       &f_ss_opts_int_interval.attr,
-       &f_ss_opts_int_maxpacket.attr,
-       &f_ss_opts_int_mult.attr,
-       &f_ss_opts_int_maxburst.attr,
        NULL,
 };
 
@@ -1684,8 +1215,6 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
        ss_opts->isoc_interval = GZERO_ISOC_INTERVAL;
        ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET;
        ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
-       ss_opts->int_interval = GZERO_INT_INTERVAL;
-       ss_opts->int_maxpacket = GZERO_INT_MAXPACKET;
 
        config_group_init_type_name(&ss_opts->func_inst.group, "",
                                    &ss_func_type);
index 2ce28b9d97cc81a519cff3adb6e07fa89aeb9e2a..15f180904f8a3980e2845c38bf327e5174b8df30 100644 (file)
@@ -10,8 +10,6 @@
 #define GZERO_QLEN             32
 #define GZERO_ISOC_INTERVAL    4
 #define GZERO_ISOC_MAXPACKET   1024
-#define GZERO_INT_INTERVAL     1 /* Default interrupt interval = 1 ms */
-#define GZERO_INT_MAXPACKET    1024
 
 struct usb_zero_options {
        unsigned pattern;
@@ -19,10 +17,6 @@ struct usb_zero_options {
        unsigned isoc_maxpacket;
        unsigned isoc_mult;
        unsigned isoc_maxburst;
-       unsigned int_interval; /* In ms */
-       unsigned int_maxpacket;
-       unsigned int_mult;
-       unsigned int_maxburst;
        unsigned bulk_buflen;
        unsigned qlen;
 };
@@ -34,10 +28,6 @@ struct f_ss_opts {
        unsigned isoc_maxpacket;
        unsigned isoc_mult;
        unsigned isoc_maxburst;
-       unsigned int_interval; /* In ms */
-       unsigned int_maxpacket;
-       unsigned int_mult;
-       unsigned int_maxburst;
        unsigned bulk_buflen;
 
        /*
@@ -72,7 +62,6 @@ int lb_modinit(void);
 void free_ep_req(struct usb_ep *ep, struct usb_request *req);
 void disable_endpoints(struct usb_composite_dev *cdev,
                struct usb_ep *in, struct usb_ep *out,
-               struct usb_ep *iso_in, struct usb_ep *iso_out,
-               struct usb_ep *int_in, struct usb_ep *int_out);
+               struct usb_ep *iso_in, struct usb_ep *iso_out);
 
 #endif /* __G_ZERO_H */
index 3a494168661e40c9f20e812bc1473620711aebb5..6e0a019aad54ae7a209f03355ae50d7c1e0cdb29 100644 (file)
@@ -1740,10 +1740,9 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
                goto err_session;
        }
        /*
-        * Now register the TCM vHost virtual I_T Nexus as active with the
-        * call to __transport_register_session()
+        * Now register the TCM vHost virtual I_T Nexus as active.
         */
-       __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
+       transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
                        tv_nexus->tvn_se_sess, tv_nexus);
        tpg->tpg_nexus = tv_nexus;
        mutex_unlock(&tpg->tpg_mutex);
index ff97ac93ac03d0add447f3e3ed49301403386b53..5ee95152493c2b6b0be74257cc437bdb560f250b 100644 (file)
@@ -68,8 +68,6 @@ static struct usb_zero_options gzero_options = {
        .isoc_maxpacket = GZERO_ISOC_MAXPACKET,
        .bulk_buflen = GZERO_BULK_BUFLEN,
        .qlen = GZERO_QLEN,
-       .int_interval = GZERO_INT_INTERVAL,
-       .int_maxpacket = GZERO_INT_MAXPACKET,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -268,21 +266,6 @@ module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint,
                S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
 
-module_param_named(int_interval, gzero_options.int_interval, uint,
-               S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(int_interval, "1 - 16");
-
-module_param_named(int_maxpacket, gzero_options.int_maxpacket, uint,
-               S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(int_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
-
-module_param_named(int_mult, gzero_options.int_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(int_mult, "0 - 2 (hs/ss only)");
-
-module_param_named(int_maxburst, gzero_options.int_maxburst, uint,
-               S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(int_maxburst, "0 - 15 (ss only)");
-
 static struct usb_function *func_lb;
 static struct usb_function_instance *func_inst_lb;
 
@@ -318,10 +301,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
        ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
        ss_opts->isoc_mult = gzero_options.isoc_mult;
        ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;
-       ss_opts->int_interval = gzero_options.int_interval;
-       ss_opts->int_maxpacket = gzero_options.int_maxpacket;
-       ss_opts->int_mult = gzero_options.int_mult;
-       ss_opts->int_maxburst = gzero_options.int_maxburst;
        ss_opts->bulk_buflen = gzero_options.bulk_buflen;
 
        func_ss = usb_get_function(func_inst_ss);
index 663f7908b15c482c9f57bc921d3c976acb04bc53..be0964a801e819fd5dbf88bcee3c1f12f14fd039 100644 (file)
@@ -34,7 +34,6 @@ static const char hcd_name[] = "ehci-atmel";
 
 struct atmel_ehci_priv {
        struct clk *iclk;
-       struct clk *fclk;
        struct clk *uclk;
        bool clocked;
 };
@@ -51,12 +50,9 @@ static void atmel_start_clock(struct atmel_ehci_priv *atmel_ehci)
 {
        if (atmel_ehci->clocked)
                return;
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               clk_set_rate(atmel_ehci->uclk, 48000000);
-               clk_prepare_enable(atmel_ehci->uclk);
-       }
+
+       clk_prepare_enable(atmel_ehci->uclk);
        clk_prepare_enable(atmel_ehci->iclk);
-       clk_prepare_enable(atmel_ehci->fclk);
        atmel_ehci->clocked = true;
 }
 
@@ -64,10 +60,9 @@ static void atmel_stop_clock(struct atmel_ehci_priv *atmel_ehci)
 {
        if (!atmel_ehci->clocked)
                return;
-       clk_disable_unprepare(atmel_ehci->fclk);
+
        clk_disable_unprepare(atmel_ehci->iclk);
-       if (IS_ENABLED(CONFIG_COMMON_CLK))
-               clk_disable_unprepare(atmel_ehci->uclk);
+       clk_disable_unprepare(atmel_ehci->uclk);
        atmel_ehci->clocked = false;
 }
 
@@ -146,20 +141,13 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
                retval = -ENOENT;
                goto fail_request_resource;
        }
-       atmel_ehci->fclk = devm_clk_get(&pdev->dev, "uhpck");
-       if (IS_ERR(atmel_ehci->fclk)) {
-               dev_err(&pdev->dev, "Error getting function clock\n");
-               retval = -ENOENT;
+
+       atmel_ehci->uclk = devm_clk_get(&pdev->dev, "usb_clk");
+       if (IS_ERR(atmel_ehci->uclk)) {
+               dev_err(&pdev->dev, "failed to get uclk\n");
+               retval = PTR_ERR(atmel_ehci->uclk);
                goto fail_request_resource;
        }
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               atmel_ehci->uclk = devm_clk_get(&pdev->dev, "usb_clk");
-               if (IS_ERR(atmel_ehci->uclk)) {
-                       dev_err(&pdev->dev, "failed to get uclk\n");
-                       retval = PTR_ERR(atmel_ehci->uclk);
-                       goto fail_request_resource;
-               }
-       }
 
        ehci = hcd_to_ehci(hcd);
        /* registers start at offset 0x0 */
index 5fb66db89e05549da9cd4e94a15abbbcc3ba5a19..73485fa4372ff7d89298d4d8968fd28d5ec43265 100644 (file)
@@ -1729,7 +1729,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
        if (!command)
                return;
 
-       ep->ep_state |= EP_HALTED | EP_RECENTLY_HALTED;
+       ep->ep_state |= EP_HALTED;
        ep->stopped_stream = stream_id;
 
        xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
index b06d1a53652da3ff9446e99c870c4c56fe044e5e..ec8ac16748547a2ac87bf9aa225ed0a36c0bf7df 100644 (file)
@@ -1338,12 +1338,6 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                goto exit;
        }
 
-       /* Reject urb if endpoint is in soft reset, queue must stay empty */
-       if (xhci->devs[slot_id]->eps[ep_index].ep_state & EP_CONFIG_PENDING) {
-               xhci_warn(xhci, "Can't enqueue URB while ep is in soft reset\n");
-               ret = -EINVAL;
-       }
-
        if (usb_endpoint_xfer_isoc(&urb->ep->desc))
                size = urb->number_of_packets;
        else
@@ -2954,36 +2948,23 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
        }
 }
 
-/* Called after clearing a halted device. USB core should have sent the control
+/* Called when clearing halted device. The core should have sent the control
  * message to clear the device halt condition. The host side of the halt should
- * already be cleared with a reset endpoint command issued immediately when the
- * STALL tx event was received.
+ * already be cleared with a reset endpoint command issued when the STALL tx
+ * event was received.
+ *
+ * Context: in_interrupt
  */
 
 void xhci_endpoint_reset(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep)
 {
        struct xhci_hcd *xhci;
-       struct usb_device *udev;
-       struct xhci_virt_device *virt_dev;
-       struct xhci_virt_ep *virt_ep;
-       struct xhci_input_control_ctx *ctrl_ctx;
-       struct xhci_command *command;
-       unsigned int ep_index, ep_state;
-       unsigned long flags;
-       u32 ep_flag;
 
        xhci = hcd_to_xhci(hcd);
-       udev = (struct usb_device *) ep->hcpriv;
-       if (!ep->hcpriv)
-               return;
-       virt_dev = xhci->devs[udev->slot_id];
-       ep_index = xhci_get_endpoint_index(&ep->desc);
-       virt_ep = &virt_dev->eps[ep_index];
-       ep_state = virt_ep->ep_state;
 
        /*
-        * Implement the config ep command in xhci 4.6.8 additional note:
+        * We might need to implement the config ep cmd in xhci 4.8.1 note:
         * The Reset Endpoint Command may only be issued to endpoints in the
         * Halted state. If software wishes reset the Data Toggle or Sequence
         * Number of an endpoint that isn't in the Halted state, then software
@@ -2991,72 +2972,9 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
         * for the target endpoint. that is in the Stopped state.
         */
 
-       if (ep_state & SET_DEQ_PENDING || ep_state & EP_RECENTLY_HALTED) {
-               virt_ep->ep_state &= ~EP_RECENTLY_HALTED;
-               xhci_dbg(xhci, "ep recently halted, no toggle reset needed\n");
-               return;
-       }
-
-       /* Only interrupt and bulk ep's use Data toggle, USB2 spec 5.5.4-> */
-       if (usb_endpoint_xfer_control(&ep->desc) ||
-           usb_endpoint_xfer_isoc(&ep->desc))
-               return;
-
-       ep_flag = xhci_get_endpoint_flag(&ep->desc);
-
-       if (ep_flag == SLOT_FLAG || ep_flag == EP0_FLAG)
-               return;
-
-       command = xhci_alloc_command(xhci, true, true, GFP_NOWAIT);
-       if (!command) {
-               xhci_err(xhci, "Could not allocate xHCI command structure.\n");
-               return;
-       }
-
-       spin_lock_irqsave(&xhci->lock, flags);
-
-       /* block ringing ep doorbell */
-       virt_ep->ep_state |= EP_CONFIG_PENDING;
-
-       /*
-        * Make sure endpoint ring is empty before resetting the toggle/seq.
-        * Driver is required to synchronously cancel all transfer request.
-        *
-        * xhci 4.6.6 says we can issue a configure endpoint command on a
-        * running endpoint ring as long as it's idle (queue empty)
-        */
-
-       if (!list_empty(&virt_ep->ring->td_list)) {
-               dev_err(&udev->dev, "EP not empty, refuse reset\n");
-               spin_unlock_irqrestore(&xhci->lock, flags);
-               goto cleanup;
-       }
-
-       xhci_dbg(xhci, "Reset toggle/seq for slot %d, ep_index: %d\n",
-                udev->slot_id, ep_index);
-
-       ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
-       if (!ctrl_ctx) {
-               xhci_err(xhci, "Could not get input context, bad type. virt_dev: %p, in_ctx %p\n",
-                        virt_dev, virt_dev->in_ctx);
-               spin_unlock_irqrestore(&xhci->lock, flags);
-               goto cleanup;
-       }
-       xhci_setup_input_ctx_for_config_ep(xhci, command->in_ctx,
-                                          virt_dev->out_ctx, ctrl_ctx,
-                                          ep_flag, ep_flag);
-       xhci_endpoint_copy(xhci, command->in_ctx, virt_dev->out_ctx, ep_index);
-
-       xhci_queue_configure_endpoint(xhci, command, command->in_ctx->dma,
-                                    udev->slot_id, false);
-       xhci_ring_cmd_db(xhci);
-       spin_unlock_irqrestore(&xhci->lock, flags);
-
-       wait_for_completion(command->completion);
-
-cleanup:
-       virt_ep->ep_state &= ~EP_CONFIG_PENDING;
-       xhci_free_command(xhci, command);
+       /* For now just print debug to follow the situation */
+       xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n",
+                ep->desc.bEndpointAddress);
 }
 
 static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
index 265ab1771d24c887d1ba950f2c77f9ee38144438..8e421b89632ddaa4eaf30ee34ef60f89b7ac3e2d 100644 (file)
@@ -865,8 +865,6 @@ struct xhci_virt_ep {
 #define EP_HAS_STREAMS         (1 << 4)
 /* Transitioning the endpoint to not using streams, don't enqueue URBs */
 #define EP_GETTING_NO_STREAMS  (1 << 5)
-#define EP_RECENTLY_HALTED     (1 << 6)
-#define EP_CONFIG_PENDING      (1 << 7)
        /* ----  Related to URB cancellation ---- */
        struct list_head        cancelled_td_list;
        struct xhci_td          *stopped_td;
index b9827556455f74dad64adbb4e785f14330f3371a..bfa402cf3a2745492ea5d4fe4cb0f84fc9500ca4 100644 (file)
@@ -151,8 +151,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
        }
 
        if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && !udc_disabled) {
-               ret = isp1760_udc_register(isp, irq, irqflags | IRQF_SHARED |
-                                          IRQF_DISABLED);
+               ret = isp1760_udc_register(isp, irq, irqflags);
                if (ret < 0) {
                        isp1760_hcd_unregister(&isp->hcd);
                        return ret;
index 9612d7990565c81a75a5310742c793e85e9b8057..f32c292cc8689d81bfce947f7c587603e95c09be 100644 (file)
@@ -1191,6 +1191,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
                             struct usb_gadget_driver *driver)
 {
        struct isp1760_udc *udc = gadget_to_udc(gadget);
+       unsigned long flags;
 
        /* The hardware doesn't support low speed. */
        if (driver->max_speed < USB_SPEED_FULL) {
@@ -1198,7 +1199,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
                return -EINVAL;
        }
 
-       spin_lock(&udc->lock);
+       spin_lock_irqsave(&udc->lock, flags);
 
        if (udc->driver) {
                dev_err(udc->isp->dev, "UDC already has a gadget driver\n");
@@ -1208,7 +1209,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
 
        udc->driver = driver;
 
-       spin_unlock(&udc->lock);
+       spin_unlock_irqrestore(&udc->lock, flags);
 
        dev_dbg(udc->isp->dev, "starting UDC with driver %s\n",
                driver->function);
@@ -1232,6 +1233,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
 static int isp1760_udc_stop(struct usb_gadget *gadget)
 {
        struct isp1760_udc *udc = gadget_to_udc(gadget);
+       unsigned long flags;
 
        dev_dbg(udc->isp->dev, "%s\n", __func__);
 
@@ -1239,9 +1241,9 @@ static int isp1760_udc_stop(struct usb_gadget *gadget)
 
        isp1760_udc_write(udc, DC_MODE, 0);
 
-       spin_lock(&udc->lock);
+       spin_lock_irqsave(&udc->lock, flags);
        udc->driver = NULL;
-       spin_unlock(&udc->lock);
+       spin_unlock_irqrestore(&udc->lock, flags);
 
        return 0;
 }
@@ -1411,7 +1413,7 @@ static int isp1760_udc_init(struct isp1760_udc *udc)
                return -ENODEV;
        }
 
-       if (chipid != 0x00011582) {
+       if (chipid != 0x00011582 && chipid != 0x00158210) {
                dev_err(udc->isp->dev, "udc: invalid chip ID 0x%08x\n", chipid);
                return -ENODEV;
        }
@@ -1451,8 +1453,8 @@ int isp1760_udc_register(struct isp1760_device *isp, int irq,
 
        sprintf(udc->irqname, "%s (udc)", devname);
 
-       ret = request_irq(irq, isp1760_udc_irq, IRQF_SHARED | IRQF_DISABLED |
-                         irqflags, udc->irqname, udc);
+       ret = request_irq(irq, isp1760_udc_irq, IRQF_SHARED | irqflags,
+                         udc->irqname, udc);
        if (ret < 0)
                goto error;
 
index 14e1628483d9427a68b83f09e18bee8c735e4364..39db8b603627cae44b86bcbd2d9d028027cbe651 100644 (file)
@@ -79,7 +79,8 @@ config USB_MUSB_TUSB6010
 
 config USB_MUSB_OMAP2PLUS
        tristate "OMAP2430 and onwards"
-       depends on ARCH_OMAP2PLUS && USB && OMAP_CONTROL_PHY
+       depends on ARCH_OMAP2PLUS && USB
+       depends on OMAP_CONTROL_PHY || !OMAP_CONTROL_PHY
        select GENERIC_PHY
 
 config USB_MUSB_AM35X
index 403fab772724825b16ecfd8446ab9d95386bb1cc..7b3035ff94347a519a9d54f27c45108aaaca0e9f 100644 (file)
@@ -126,6 +126,9 @@ struct phy_control *am335x_get_phy_control(struct device *dev)
                return NULL;
 
        dev = bus_find_device(&platform_bus_type, NULL, node, match);
+       if (!dev)
+               return NULL;
+
        ctrl_usb = dev_get_drvdata(dev);
        if (!ctrl_usb)
                return NULL;
index 82570425fdfe388a5fd05ee6b13439deb676c4fc..c85ea530085f12d86ca691d82122f04e9f2166ae 100644 (file)
@@ -113,6 +113,13 @@ UNUSUAL_DEV(0x0bc2, 0xab2a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_ATA_1X),
 
+/* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
+UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
+               "Initio Corporation",
+               "",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_ATA_1X),
+
 /* Reported-by: Tom Arild Naess <tanaess@gmail.com> */
 UNUSUAL_DEV(0x152d, 0x0539, 0x0000, 0x9999,
                "JMicron",
index 8d4f3f1ff799fb1d7b4bb5a2184144b515676a2c..71df240a467a10bef98c6314ba8d6031fa8e3bf6 100644 (file)
@@ -1956,10 +1956,9 @@ static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
                goto out;
        }
        /*
-        * Now register the TCM vhost virtual I_T Nexus as active with the
-        * call to __transport_register_session()
+        * Now register the TCM vhost virtual I_T Nexus as active.
         */
-       __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
+       transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
                        tv_nexus->tvn_se_sess, tv_nexus);
        tpg->tpg_nexus = tv_nexus;
 
index 0413157f3b49c230aaa7a775564086144977803f..6a356e344f82c3d5b594abeeb47c453e868c4f9f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/balloon_compaction.h>
 #include <linux/oom.h>
+#include <linux/wait.h>
 
 /*
  * Balloon device works in 4K page units.  So each page is pointed to by
@@ -334,17 +335,25 @@ static int virtballoon_oom_notify(struct notifier_block *self,
 static int balloon(void *_vballoon)
 {
        struct virtio_balloon *vb = _vballoon;
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
        set_freezable();
        while (!kthread_should_stop()) {
                s64 diff;
 
                try_to_freeze();
-               wait_event_interruptible(vb->config_change,
-                                        (diff = towards_target(vb)) != 0
-                                        || vb->need_stats_update
-                                        || kthread_should_stop()
-                                        || freezing(current));
+
+               add_wait_queue(&vb->config_change, &wait);
+               for (;;) {
+                       if ((diff = towards_target(vb)) != 0 ||
+                           vb->need_stats_update ||
+                           kthread_should_stop() ||
+                           freezing(current))
+                               break;
+                       wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+               }
+               remove_wait_queue(&vb->config_change, &wait);
+
                if (vb->need_stats_update)
                        stats_handle_request(vb);
                if (diff > 0)
@@ -499,6 +508,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
        if (err < 0)
                goto out_oom_notify;
 
+       virtio_device_ready(vdev);
+
        vb->thread = kthread_run(balloon, vb, "vballoon");
        if (IS_ERR(vb->thread)) {
                err = PTR_ERR(vb->thread);
index cad569890908de40ba4d72edd6562fb87b6e14b5..6010d7ec0a0f899b7b7690d202e9b57c6dbc7193 100644 (file)
@@ -156,22 +156,95 @@ static void vm_get(struct virtio_device *vdev, unsigned offset,
                   void *buf, unsigned len)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
-       u8 *ptr = buf;
-       int i;
+       void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
+       u8 b;
+       __le16 w;
+       __le32 l;
 
-       for (i = 0; i < len; i++)
-               ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+       if (vm_dev->version == 1) {
+               u8 *ptr = buf;
+               int i;
+
+               for (i = 0; i < len; i++)
+                       ptr[i] = readb(base + offset + i);
+               return;
+       }
+
+       switch (len) {
+       case 1:
+               b = readb(base + offset);
+               memcpy(buf, &b, sizeof b);
+               break;
+       case 2:
+               w = cpu_to_le16(readw(base + offset));
+               memcpy(buf, &w, sizeof w);
+               break;
+       case 4:
+               l = cpu_to_le32(readl(base + offset));
+               memcpy(buf, &l, sizeof l);
+               break;
+       case 8:
+               l = cpu_to_le32(readl(base + offset));
+               memcpy(buf, &l, sizeof l);
+               l = cpu_to_le32(ioread32(base + offset + sizeof l));
+               memcpy(buf + sizeof l, &l, sizeof l);
+               break;
+       default:
+               BUG();
+       }
 }
 
 static void vm_set(struct virtio_device *vdev, unsigned offset,
                   const void *buf, unsigned len)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
-       const u8 *ptr = buf;
-       int i;
+       void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
+       u8 b;
+       __le16 w;
+       __le32 l;
 
-       for (i = 0; i < len; i++)
-               writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+       if (vm_dev->version == 1) {
+               const u8 *ptr = buf;
+               int i;
+
+               for (i = 0; i < len; i++)
+                       writeb(ptr[i], base + offset + i);
+
+               return;
+       }
+
+       switch (len) {
+       case 1:
+               memcpy(&b, buf, sizeof b);
+               writeb(b, base + offset);
+               break;
+       case 2:
+               memcpy(&w, buf, sizeof w);
+               writew(le16_to_cpu(w), base + offset);
+               break;
+       case 4:
+               memcpy(&l, buf, sizeof l);
+               writel(le32_to_cpu(l), base + offset);
+               break;
+       case 8:
+               memcpy(&l, buf, sizeof l);
+               writel(le32_to_cpu(l), base + offset);
+               memcpy(&l, buf + sizeof l, sizeof l);
+               writel(le32_to_cpu(l), base + offset + sizeof l);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static u32 vm_generation(struct virtio_device *vdev)
+{
+       struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+       if (vm_dev->version == 1)
+               return 0;
+       else
+               return readl(vm_dev->base + VIRTIO_MMIO_CONFIG_GENERATION);
 }
 
 static u8 vm_get_status(struct virtio_device *vdev)
@@ -440,6 +513,7 @@ static const char *vm_bus_name(struct virtio_device *vdev)
 static const struct virtio_config_ops virtio_mmio_config_ops = {
        .get            = vm_get,
        .set            = vm_set,
+       .generation     = vm_generation,
        .get_status     = vm_get_status,
        .set_status     = vm_set_status,
        .reset          = vm_reset,
index 9faca6a60bb01b33c311f86b01af239280934a78..42bd55a6c237209c15790876911d8aa31343b043 100644 (file)
@@ -1659,11 +1659,8 @@ static int scsiback_make_nexus(struct scsiback_tpg *tpg,
                         name);
                goto out;
        }
-       /*
-        * Now register the TCM pvscsi virtual I_T Nexus as active with the
-        * call to __transport_register_session()
-        */
-       __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
+       /* Now register the TCM pvscsi virtual I_T Nexus as active. */
+       transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
                        tv_nexus->tvn_se_sess, tv_nexus);
        tpg->tpg_nexus = tv_nexus;
 
index 84c3b00f3de8eedf47ba3bec71939a5fba1f90a0..f9c89cae39ee41fd6ae37bbc36178f8eb9093044 100644 (file)
@@ -3387,6 +3387,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                    struct btrfs_root *root);
+int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root);
 int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr);
 int btrfs_free_block_groups(struct btrfs_fs_info *info);
 int btrfs_read_block_groups(struct btrfs_root *root);
@@ -3909,6 +3911,9 @@ int btrfs_prealloc_file_range_trans(struct inode *inode,
                                    loff_t actual_len, u64 *alloc_hint);
 int btrfs_inode_check_errors(struct inode *inode);
 extern const struct dentry_operations btrfs_dentry_operations;
+#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+void btrfs_test_inode_set_ops(struct inode *inode);
+#endif
 
 /* ioctl.c */
 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
index f79f38542a737631e191e08aed6b50d4a940f964..639f2663ed3f8f40dc925451618702632e8b9109 100644 (file)
@@ -3921,7 +3921,7 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
        }
        if (btrfs_super_sys_array_size(sb) < sizeof(struct btrfs_disk_key)
                        + sizeof(struct btrfs_chunk)) {
-               printk(KERN_ERR "BTRFS: system chunk array too small %u < %lu\n",
+               printk(KERN_ERR "BTRFS: system chunk array too small %u < %zu\n",
                                btrfs_super_sys_array_size(sb),
                                sizeof(struct btrfs_disk_key)
                                + sizeof(struct btrfs_chunk));
index 6f080451fcb11181c10247a542b599412bb42f22..8b353ad02f034a9307e1da5d8923aff6b43a0dcb 100644 (file)
@@ -3325,6 +3325,32 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        return ret;
 }
 
+int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root)
+{
+       struct btrfs_block_group_cache *cache, *tmp;
+       struct btrfs_transaction *cur_trans = trans->transaction;
+       struct btrfs_path *path;
+
+       if (list_empty(&cur_trans->dirty_bgs) ||
+           !btrfs_test_opt(root, SPACE_CACHE))
+               return 0;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       /* Could add new block groups, use _safe just in case */
+       list_for_each_entry_safe(cache, tmp, &cur_trans->dirty_bgs,
+                                dirty_list) {
+               if (cache->disk_cache_state == BTRFS_DC_CLEAR)
+                       cache_save_setup(cache, trans, path);
+       }
+
+       btrfs_free_path(path);
+       return 0;
+}
+
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root)
 {
@@ -5110,7 +5136,11 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        num_bytes = ALIGN(num_bytes, root->sectorsize);
 
        spin_lock(&BTRFS_I(inode)->lock);
-       BTRFS_I(inode)->outstanding_extents++;
+       nr_extents = (unsigned)div64_u64(num_bytes +
+                                        BTRFS_MAX_EXTENT_SIZE - 1,
+                                        BTRFS_MAX_EXTENT_SIZE);
+       BTRFS_I(inode)->outstanding_extents += nr_extents;
+       nr_extents = 0;
 
        if (BTRFS_I(inode)->outstanding_extents >
            BTRFS_I(inode)->reserved_extents)
@@ -5255,6 +5285,9 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
        if (dropped > 0)
                to_free += btrfs_calc_trans_metadata_size(root, dropped);
 
+       if (btrfs_test_is_dummy_root(root))
+               return;
+
        trace_btrfs_space_reservation(root->fs_info, "delalloc",
                                      btrfs_ino(inode), to_free, 0);
        if (root->fs_info->quota_enabled) {
index c7233ff1d533b653b8b9e7f29e022e9126e5f38a..d688cfe5d4962ddf626e97a36fc8136edd7922b9 100644 (file)
@@ -4968,6 +4968,12 @@ static int release_extent_buffer(struct extent_buffer *eb)
 
                /* Should be safe to release our pages at this point */
                btrfs_release_extent_buffer_page(eb);
+#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+               if (unlikely(test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags))) {
+                       __free_extent_buffer(eb);
+                       return 1;
+               }
+#endif
                call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu);
                return 1;
        }
index da828cf5e8f885b542012dc3d23854916dc35106..d2e732d7af524640bc2c197da3e7123182b4537e 100644 (file)
@@ -108,6 +108,13 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
 
 static int btrfs_dirty_inode(struct inode *inode);
 
+#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+void btrfs_test_inode_set_ops(struct inode *inode)
+{
+       BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
+}
+#endif
+
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
                                     const struct qstr *qstr)
@@ -1542,30 +1549,17 @@ static void btrfs_split_extent_hook(struct inode *inode,
                u64 new_size;
 
                /*
-                * We need the largest size of the remaining extent to see if we
-                * need to add a new outstanding extent.  Think of the following
-                * case
-                *
-                * [MEAX_EXTENT_SIZEx2 - 4k][4k]
-                *
-                * The new_size would just be 4k and we'd think we had enough
-                * outstanding extents for this if we only took one side of the
-                * split, same goes for the other direction.  We need to see if
-                * the larger size still is the same amount of extents as the
-                * original size, because if it is we need to add a new
-                * outstanding extent.  But if we split up and the larger size
-                * is less than the original then we are good to go since we've
-                * already accounted for the extra extent in our original
-                * accounting.
+                * See the explanation in btrfs_merge_extent_hook, the same
+                * applies here, just in reverse.
                 */
                new_size = orig->end - split + 1;
-               if ((split - orig->start) > new_size)
-                       new_size = split - orig->start;
-
-               num_extents = div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1,
+               num_extents = div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
                                        BTRFS_MAX_EXTENT_SIZE);
-               if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
-                             BTRFS_MAX_EXTENT_SIZE) < num_extents)
+               new_size = split - orig->start;
+               num_extents += div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
+                                       BTRFS_MAX_EXTENT_SIZE);
+               if (div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1,
+                             BTRFS_MAX_EXTENT_SIZE) >= num_extents)
                        return;
        }
 
@@ -1591,8 +1585,10 @@ static void btrfs_merge_extent_hook(struct inode *inode,
        if (!(other->state & EXTENT_DELALLOC))
                return;
 
-       old_size = other->end - other->start + 1;
-       new_size = old_size + (new->end - new->start + 1);
+       if (new->start > other->start)
+               new_size = new->end - other->start + 1;
+       else
+               new_size = other->end - new->start + 1;
 
        /* we're not bigger than the max, unreserve the space and go */
        if (new_size <= BTRFS_MAX_EXTENT_SIZE) {
@@ -1603,13 +1599,32 @@ static void btrfs_merge_extent_hook(struct inode *inode,
        }
 
        /*
-        * If we grew by another max_extent, just return, we want to keep that
-        * reserved amount.
+        * We have to add up either side to figure out how many extents were
+        * accounted for before we merged into one big extent.  If the number of
+        * extents we accounted for is <= the amount we need for the new range
+        * then we can return, otherwise drop.  Think of it like this
+        *
+        * [ 4k][MAX_SIZE]
+        *
+        * So we've grown the extent by a MAX_SIZE extent, this would mean we
+        * need 2 outstanding extents, on one side we have 1 and the other side
+        * we have 1 so they are == and we can return.  But in this case
+        *
+        * [MAX_SIZE+4k][MAX_SIZE+4k]
+        *
+        * Each range on their own accounts for 2 extents, but merged together
+        * they are only 3 extents worth of accounting, so we need to drop in
+        * this case.
         */
+       old_size = other->end - other->start + 1;
        num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
                                BTRFS_MAX_EXTENT_SIZE);
+       old_size = new->end - new->start + 1;
+       num_extents += div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
+                                BTRFS_MAX_EXTENT_SIZE);
+
        if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
-                     BTRFS_MAX_EXTENT_SIZE) > num_extents)
+                     BTRFS_MAX_EXTENT_SIZE) >= num_extents)
                return;
 
        spin_lock(&BTRFS_I(inode)->lock);
@@ -1686,6 +1701,10 @@ static void btrfs_set_bit_hook(struct inode *inode,
                        spin_unlock(&BTRFS_I(inode)->lock);
                }
 
+               /* For sanity tests */
+               if (btrfs_test_is_dummy_root(root))
+                       return;
+
                __percpu_counter_add(&root->fs_info->delalloc_bytes, len,
                                     root->fs_info->delalloc_batch);
                spin_lock(&BTRFS_I(inode)->lock);
@@ -1741,6 +1760,10 @@ static void btrfs_clear_bit_hook(struct inode *inode,
                    root != root->fs_info->tree_root)
                        btrfs_delalloc_release_metadata(inode, len);
 
+               /* For sanity tests. */
+               if (btrfs_test_is_dummy_root(root))
+                       return;
+
                if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
                    && do_list && !(state->state & EXTENT_NORESERVE))
                        btrfs_free_reserved_data_space(inode, len);
@@ -7213,7 +7236,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
        u64 start = iblock << inode->i_blkbits;
        u64 lockstart, lockend;
        u64 len = bh_result->b_size;
-       u64 orig_len = len;
+       u64 *outstanding_extents = NULL;
        int unlock_bits = EXTENT_LOCKED;
        int ret = 0;
 
@@ -7225,6 +7248,16 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
        lockstart = start;
        lockend = start + len - 1;
 
+       if (current->journal_info) {
+               /*
+                * Need to pull our outstanding extents and set journal_info to NULL so
+                * that anything that needs to check if there's a transction doesn't get
+                * confused.
+                */
+               outstanding_extents = current->journal_info;
+               current->journal_info = NULL;
+       }
+
        /*
         * If this errors out it's because we couldn't invalidate pagecache for
         * this range and we need to fallback to buffered.
@@ -7348,11 +7381,20 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                if (start + len > i_size_read(inode))
                        i_size_write(inode, start + len);
 
-               if (len < orig_len) {
+               /*
+                * If we have an outstanding_extents count still set then we're
+                * within our reservation, otherwise we need to adjust our inode
+                * counter appropriately.
+                */
+               if (*outstanding_extents) {
+                       (*outstanding_extents)--;
+               } else {
                        spin_lock(&BTRFS_I(inode)->lock);
                        BTRFS_I(inode)->outstanding_extents++;
                        spin_unlock(&BTRFS_I(inode)->lock);
                }
+
+               current->journal_info = outstanding_extents;
                btrfs_free_reserved_data_space(inode, len);
        }
 
@@ -7376,6 +7418,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
 unlock_err:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
                         unlock_bits, 1, 0, &cached_state, GFP_NOFS);
+       if (outstanding_extents)
+               current->journal_info = outstanding_extents;
        return ret;
 }
 
@@ -8075,6 +8119,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       u64 outstanding_extents = 0;
        size_t count = 0;
        int flags = 0;
        bool wakeup = true;
@@ -8112,6 +8157,16 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                ret = btrfs_delalloc_reserve_space(inode, count);
                if (ret)
                        goto out;
+               outstanding_extents = div64_u64(count +
+                                               BTRFS_MAX_EXTENT_SIZE - 1,
+                                               BTRFS_MAX_EXTENT_SIZE);
+
+               /*
+                * We need to know how many extents we reserved so that we can
+                * do the accounting properly if we go over the number we
+                * originally calculated.  Abuse current->journal_info for this.
+                */
+               current->journal_info = &outstanding_extents;
        } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
                                     &BTRFS_I(inode)->runtime_flags)) {
                inode_dio_done(inode);
@@ -8124,6 +8179,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                        iter, offset, btrfs_get_blocks_direct, NULL,
                        btrfs_submit_direct, flags);
        if (rw & WRITE) {
+               current->journal_info = NULL;
                if (ret < 0 && ret != -EIOCBQUEUED)
                        btrfs_delalloc_release_space(inode, count);
                else if (ret >= 0 && (size_t)ret < count)
index 97159a8e91d40b24ca1a8f6367892ecf2ad8b960..058c79eecbfb96825918a370e3f78d926b49b098 100644 (file)
@@ -1259,7 +1259,7 @@ static int comp_oper(struct btrfs_qgroup_operation *oper1,
        if (oper1->seq < oper2->seq)
                return -1;
        if (oper1->seq > oper2->seq)
-               return -1;
+               return 1;
        if (oper1->ref_root < oper2->ref_root)
                return -1;
        if (oper1->ref_root > oper2->ref_root)
index a116b55ce7880a5e64837dfd6cd66f7412e27cec..054fc0d97131b239486a47a5b8ef4b3f120c2e6b 100644 (file)
@@ -911,6 +911,197 @@ static int test_hole_first(void)
        return ret;
 }
 
+static int test_extent_accounting(void)
+{
+       struct inode *inode = NULL;
+       struct btrfs_root *root = NULL;
+       int ret = -ENOMEM;
+
+       inode = btrfs_new_test_inode();
+       if (!inode) {
+               test_msg("Couldn't allocate inode\n");
+               return ret;
+       }
+
+       root = btrfs_alloc_dummy_root();
+       if (IS_ERR(root)) {
+               test_msg("Couldn't allocate root\n");
+               goto out;
+       }
+
+       root->fs_info = btrfs_alloc_dummy_fs_info();
+       if (!root->fs_info) {
+               test_msg("Couldn't allocate dummy fs info\n");
+               goto out;
+       }
+
+       BTRFS_I(inode)->root = root;
+       btrfs_test_inode_set_ops(inode);
+
+       /* [BTRFS_MAX_EXTENT_SIZE] */
+       BTRFS_I(inode)->outstanding_extents++;
+       ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1,
+                                       NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 1) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 1, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* [BTRFS_MAX_EXTENT_SIZE][4k] */
+       BTRFS_I(inode)->outstanding_extents++;
+       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE,
+                                       BTRFS_MAX_EXTENT_SIZE + 4095, NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 2) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 2, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* [BTRFS_MAX_EXTENT_SIZE/2][4K HOLE][the rest] */
+       ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
+                              BTRFS_MAX_EXTENT_SIZE >> 1,
+                              (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+                              EXTENT_DELALLOC | EXTENT_DIRTY |
+                              EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0,
+                              NULL, GFP_NOFS);
+       if (ret) {
+               test_msg("clear_extent_bit returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 2) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 2, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* [BTRFS_MAX_EXTENT_SIZE][4K] */
+       BTRFS_I(inode)->outstanding_extents++;
+       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1,
+                                       (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+                                       NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 2) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 2, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /*
+        * [BTRFS_MAX_EXTENT_SIZE+4K][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4K]
+        *
+        * I'm artificially adding 2 to outstanding_extents because in the
+        * buffered IO case we'd add things up as we go, but I don't feel like
+        * doing that here, this isn't the interesting case we want to test.
+        */
+       BTRFS_I(inode)->outstanding_extents += 2;
+       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE + 8192,
+                                       (BTRFS_MAX_EXTENT_SIZE << 1) + 12287,
+                                       NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 4) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 4, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* [BTRFS_MAX_EXTENT_SIZE+4k][4k][BTRFS_MAX_EXTENT_SIZE+4k] */
+       BTRFS_I(inode)->outstanding_extents++;
+       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096,
+                                       BTRFS_MAX_EXTENT_SIZE+8191, NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 3) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 3, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */
+       ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
+                              BTRFS_MAX_EXTENT_SIZE+4096,
+                              BTRFS_MAX_EXTENT_SIZE+8191,
+                              EXTENT_DIRTY | EXTENT_DELALLOC |
+                              EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
+                              NULL, GFP_NOFS);
+       if (ret) {
+               test_msg("clear_extent_bit returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 4) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 4, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /*
+        * Refill the hole again just for good measure, because I thought it
+        * might fail and I'd rather satisfy my paranoia at this point.
+        */
+       BTRFS_I(inode)->outstanding_extents++;
+       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096,
+                                       BTRFS_MAX_EXTENT_SIZE+8191, NULL);
+       if (ret) {
+               test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents != 3) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 3, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+
+       /* Empty */
+       ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
+                              EXTENT_DIRTY | EXTENT_DELALLOC |
+                              EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
+                              NULL, GFP_NOFS);
+       if (ret) {
+               test_msg("clear_extent_bit returned %d\n", ret);
+               goto out;
+       }
+       if (BTRFS_I(inode)->outstanding_extents) {
+               ret = -EINVAL;
+               test_msg("Miscount, wanted 0, got %u\n",
+                        BTRFS_I(inode)->outstanding_extents);
+               goto out;
+       }
+       ret = 0;
+out:
+       if (ret)
+               clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
+                                EXTENT_DIRTY | EXTENT_DELALLOC |
+                                EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
+                                NULL, GFP_NOFS);
+       iput(inode);
+       btrfs_free_dummy_root(root);
+       return ret;
+}
+
 int btrfs_test_inodes(void)
 {
        int ret;
@@ -924,5 +1115,9 @@ int btrfs_test_inodes(void)
        if (ret)
                return ret;
        test_msg("Running hole first btrfs_get_extent test\n");
-       return test_hole_first();
+       ret = test_hole_first();
+       if (ret)
+               return ret;
+       test_msg("Running outstanding_extents tests\n");
+       return test_extent_accounting();
 }
index 88e51aded6bda9744a5fffa19b0b4e701dab925e..8be4278e25e8e06e32d52b5ac412201d7b20a53c 100644 (file)
@@ -1023,17 +1023,13 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
        u64 old_root_bytenr;
        u64 old_root_used;
        struct btrfs_root *tree_root = root->fs_info->tree_root;
-       bool extent_root = (root->objectid == BTRFS_EXTENT_TREE_OBJECTID);
 
        old_root_used = btrfs_root_used(&root->root_item);
-       btrfs_write_dirty_block_groups(trans, root);
 
        while (1) {
                old_root_bytenr = btrfs_root_bytenr(&root->root_item);
                if (old_root_bytenr == root->node->start &&
-                   old_root_used == btrfs_root_used(&root->root_item) &&
-                   (!extent_root ||
-                    list_empty(&trans->transaction->dirty_bgs)))
+                   old_root_used == btrfs_root_used(&root->root_item))
                        break;
 
                btrfs_set_root_node(&root->root_item, root->node);
@@ -1044,14 +1040,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
                        return ret;
 
                old_root_used = btrfs_root_used(&root->root_item);
-               if (extent_root) {
-                       ret = btrfs_write_dirty_block_groups(trans, root);
-                       if (ret)
-                               return ret;
-               }
-               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
-               if (ret)
-                       return ret;
        }
 
        return 0;
@@ -1068,6 +1056,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
                                         struct btrfs_root *root)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
+       struct list_head *dirty_bgs = &trans->transaction->dirty_bgs;
        struct list_head *next;
        struct extent_buffer *eb;
        int ret;
@@ -1095,11 +1084,15 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
        if (ret)
                return ret;
 
+       ret = btrfs_setup_space_cache(trans, root);
+       if (ret)
+               return ret;
+
        /* run_qgroups might have added some more refs */
        ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
        if (ret)
                return ret;
-
+again:
        while (!list_empty(&fs_info->dirty_cowonly_roots)) {
                next = fs_info->dirty_cowonly_roots.next;
                list_del_init(next);
@@ -1112,8 +1105,23 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
                ret = update_cowonly_root(trans, root);
                if (ret)
                        return ret;
+               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
+               if (ret)
+                       return ret;
        }
 
+       while (!list_empty(dirty_bgs)) {
+               ret = btrfs_write_dirty_block_groups(trans, root);
+               if (ret)
+                       return ret;
+               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
+               if (ret)
+                       return ret;
+       }
+
+       if (!list_empty(&fs_info->dirty_cowonly_roots))
+               goto again;
+
        list_add_tail(&fs_info->extent_root->dirty_list,
                      &trans->transaction->switch_commits);
        btrfs_after_dev_replace_commit(fs_info);
@@ -1811,6 +1819,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
                wait_for_commit(root, cur_trans);
 
+               if (unlikely(cur_trans->aborted))
+                       ret = cur_trans->aborted;
+
                btrfs_put_transaction(cur_trans);
 
                return ret;
index ed19a7d622fa35decaa08b10e83b8bdee8712419..39706c57ad3cb157d81594065a15f154f61d7bd8 100644 (file)
@@ -890,8 +890,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 
        newpage = buf->page;
 
-       if (WARN_ON(!PageUptodate(newpage)))
-               return -EIO;
+       if (!PageUptodate(newpage))
+               SetPageUptodate(newpage);
 
        ClearPageMappedToDisk(newpage);
 
@@ -1353,6 +1353,17 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
        return err;
 }
 
+static int fuse_dev_open(struct inode *inode, struct file *file)
+{
+       /*
+        * The fuse device's file's private_data is used to hold
+        * the fuse_conn(ection) when it is mounted, and is used to
+        * keep track of whether the file has been mounted already.
+        */
+       file->private_data = NULL;
+       return 0;
+}
+
 static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
                              unsigned long nr_segs, loff_t pos)
 {
@@ -1797,6 +1808,9 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
 static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
                       unsigned int size, struct fuse_copy_state *cs)
 {
+       /* Don't try to move pages (yet) */
+       cs->move_pages = 0;
+
        switch (code) {
        case FUSE_NOTIFY_POLL:
                return fuse_notify_poll(fc, size, cs);
@@ -2217,6 +2231,7 @@ static int fuse_dev_fasync(int fd, struct file *file, int on)
 
 const struct file_operations fuse_dev_operations = {
        .owner          = THIS_MODULE,
+       .open           = fuse_dev_open,
        .llseek         = no_llseek,
        .read           = do_sync_read,
        .aio_read       = fuse_dev_read,
index b684e8a132e6255b7f294321ccd3a2f0e5097a09..2bacb99885665f3a0fae9579a569128195d86fd4 100644 (file)
@@ -207,6 +207,7 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
                goto out_free;
        }
 
+       of->event = atomic_read(&of->kn->attr.open->event);
        ops = kernfs_ops(of->kn);
        if (ops->read)
                len = ops->read(of, buf, len, *ppos);
index 3c1bfa15557116d0e78c87b191a5842bdeca9417..1028a062954357c06005dc7b0d6f61a10ea6f418 100644 (file)
@@ -587,8 +587,6 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls)
 
        rpc_ntop((struct sockaddr *)&clp->cl_addr, addr_str, sizeof(addr_str));
 
-       nfsd4_cb_layout_fail(ls);
-
        printk(KERN_WARNING
                "nfsd: client %s failed to respond to layout recall. "
                "  Fencing..\n", addr_str);
index b90952f528b1cdf7414e49b5613e439d6b89fb7a..5f0d1993e6e3952bda9352d231e8fce7dee838e8 100644 (file)
@@ -529,8 +529,7 @@ static int ovl_remount(struct super_block *sb, int *flags, char *data)
 {
        struct ovl_fs *ufs = sb->s_fs_info;
 
-       if (!(*flags & MS_RDONLY) &&
-           (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)))
+       if (!(*flags & MS_RDONLY) && !ufs->upper_mnt)
                return -EROFS;
 
        return 0;
@@ -615,9 +614,19 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
                        break;
 
                default:
+                       pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
                        return -EINVAL;
                }
        }
+
+       /* Workdir is useless in non-upper mount */
+       if (!config->upperdir && config->workdir) {
+               pr_info("overlayfs: option \"workdir=%s\" is useless in a non-upper mount, ignore\n",
+                       config->workdir);
+               kfree(config->workdir);
+               config->workdir = NULL;
+       }
+
        return 0;
 }
 
@@ -837,7 +846,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_stack_depth = 0;
        if (ufs->config.upperdir) {
-               /* FIXME: workdir is not needed for a R/O mount */
                if (!ufs->config.workdir) {
                        pr_err("overlayfs: missing 'workdir'\n");
                        goto out_free_config;
@@ -847,6 +855,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                if (err)
                        goto out_free_config;
 
+               /* Upper fs should not be r/o */
+               if (upperpath.mnt->mnt_sb->s_flags & MS_RDONLY) {
+                       pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n");
+                       err = -EINVAL;
+                       goto out_put_upperpath;
+               }
+
                err = ovl_mount_dir(ufs->config.workdir, &workpath);
                if (err)
                        goto out_put_upperpath;
@@ -869,8 +884,14 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 
        err = -EINVAL;
        stacklen = ovl_split_lowerdirs(lowertmp);
-       if (stacklen > OVL_MAX_STACK)
+       if (stacklen > OVL_MAX_STACK) {
+               pr_err("overlayfs: too many lower directries, limit is %d\n",
+                      OVL_MAX_STACK);
                goto out_free_lowertmp;
+       } else if (!ufs->config.upperdir && stacklen == 1) {
+               pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n");
+               goto out_free_lowertmp;
+       }
 
        stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL);
        if (!stack)
@@ -932,8 +953,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                ufs->numlower++;
        }
 
-       /* If the upper fs is r/o or nonexistent, we mark overlayfs r/o too */
-       if (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY))
+       /* If the upper fs is nonexistent, we mark overlayfs r/o too */
+       if (!ufs->upper_mnt)
                sb->s_flags |= MS_RDONLY;
 
        sb->s_d_op = &ovl_dentry_operations;
index 956b75d61809f06cdf433411456bb08278726eb5..6dee68d013ffa69f1f6c9d49873f17f19eb3874d 100644 (file)
@@ -1325,6 +1325,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 
 static int pagemap_open(struct inode *inode, struct file *file)
 {
+       /* do not disclose physical addresses: attack vector */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
        pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about "
                        "to stop being page-shift some time soon. See the "
                        "linux/Documentation/vm/pagemap.txt for details.\n");
index 7c55dd5dd2c9faf2202692ca5f669f064c173ed4..66203b268984ebedd72d5bd1b2f54440e56011bc 100644 (file)
@@ -114,6 +114,7 @@ struct vgic_ops {
        void    (*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
        u64     (*get_elrsr)(const struct kvm_vcpu *vcpu);
        u64     (*get_eisr)(const struct kvm_vcpu *vcpu);
+       void    (*clear_eisr)(struct kvm_vcpu *vcpu);
        u32     (*get_interrupt_status)(const struct kvm_vcpu *vcpu);
        void    (*enable_underflow)(struct kvm_vcpu *vcpu);
        void    (*disable_underflow)(struct kvm_vcpu *vcpu);
index 2646aed1d3fedad16a773eaa366edad3ab44bad5..fd23978d93fe35a91afab5f56d3611c0324d9ceb 100644 (file)
@@ -375,6 +375,7 @@ int dm_create(int minor, struct mapped_device **md);
  */
 struct mapped_device *dm_get_md(dev_t dev);
 void dm_get(struct mapped_device *md);
+int dm_hold(struct mapped_device *md);
 void dm_put(struct mapped_device *md);
 
 /*
index fc03efa64ffe58ae9aa81e77bf60e5d7b4acc6c7..6b08cc106c218dc06d60988663c4bcac3eaba5fe 100644 (file)
@@ -232,6 +232,7 @@ enum {
                                              * led */
        ATA_FLAG_NO_DIPM        = (1 << 23), /* host not happy with DIPM */
        ATA_FLAG_LOWTAG         = (1 << 24), /* host wants lowest available tag */
+       ATA_FLAG_SAS_HOST       = (1 << 25), /* SAS host */
 
        /* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
index fb0390a1a498f29df135bbe7500c1dfcc00a27d7..ee7b1ce7a6f8f42280abcc3d1411f7bcdebb6ac2 100644 (file)
@@ -2999,6 +2999,9 @@ enum usb_irq_events {
 #define PALMAS_GPADC_TRIM15                                    0x0E
 #define PALMAS_GPADC_TRIM16                                    0x0F
 
+/* TPS659038 regen2_ctrl offset iss different from palmas */
+#define TPS659038_REGEN2_CTRL                                  0x12
+
 /* TPS65917 Interrupt registers */
 
 /* Registers for function INTERRUPT */
index 42999fe2dbd0fb8ec057dbd07d4c2143d6225c65..b03485bcb82a0a4d1f6ebbbac8b30f37beb722a2 100644 (file)
@@ -344,6 +344,10 @@ struct module {
        unsigned long *ftrace_callsites;
 #endif
 
+#ifdef CONFIG_LIVEPATCH
+       bool klp_alive;
+#endif
+
 #ifdef CONFIG_MODULE_UNLOAD
        /* What modules depend on me? */
        struct list_head source_list;
index 429d1790a27e85f3a2c3de433af5c16a89129b7d..dcf6ec27739b1d8bfb98c82e8902ca0b697df5f8 100644 (file)
@@ -965,9 +965,12 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  *     Used to add FDB entries to dump requests. Implementers should add
  *     entries to skb and update idx with the number of entries.
  *
- * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
+ * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh,
+ *                          u16 flags)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
  *                          struct net_device *dev, u32 filter_mask)
+ * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,
+ *                          u16 flags);
  *
  * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier);
  *     Called to change device carrier. Soft-devices (like dummy, team, etc)
index 72c0415d6c21758d31fcd2ab80c33751e41489d5..18eccefea06e40a0ea10f77e857105c6feaf4ff9 100644 (file)
@@ -82,7 +82,7 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
 
 static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
 {
-       return ERR_PTR(-ENOSYS);
+       return NULL;
 }
 
 static inline void pinctrl_put(struct pinctrl *p)
@@ -93,7 +93,7 @@ static inline struct pinctrl_state * __must_check pinctrl_lookup_state(
                                                        struct pinctrl *p,
                                                        const char *name)
 {
-       return ERR_PTR(-ENOSYS);
+       return NULL;
 }
 
 static inline int pinctrl_select_state(struct pinctrl *p,
@@ -104,7 +104,7 @@ static inline int pinctrl_select_state(struct pinctrl *p,
 
 static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
 {
-       return ERR_PTR(-ENOSYS);
+       return NULL;
 }
 
 static inline void devm_pinctrl_put(struct pinctrl *p)
index d4ad5b5a02bb478a422b349406efba00997bab76..045f709cb89b52c5e2381635b0bea10101030120 100644 (file)
@@ -316,7 +316,7 @@ struct regulator_desc {
  * @driver_data: private regulator data
  * @of_node: OpenFirmware node to parse for device tree bindings (may be
  *           NULL).
- * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is
+ * @regmap: regmap to use for core regmap helpers if dev_get_regmap() is
  *          insufficient.
  * @ena_gpio_initialized: GPIO controlling regulator enable was properly
  *                        initialized, meaning that >= 0 is a valid gpio
index 30007afe70b3541cdb4300919c2a5cfbbc0063f2..f54d6659713ae76e96391334dba700eac8be122f 100644 (file)
@@ -948,6 +948,13 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline void skb_sender_cpu_clear(struct sk_buff *skb)
+{
+#ifdef CONFIG_XPS
+       skb->sender_cpu = 0;
+#endif
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
index a8ae4e760778d8fe49ff21951bd1e088ac3aefca..0fb99a26e97372613da1851d9ee4d9bb432aba3f 100644 (file)
@@ -481,6 +481,7 @@ void dst_init(void);
 enum {
        XFRM_LOOKUP_ICMP = 1 << 0,
        XFRM_LOOKUP_QUEUE = 1 << 1,
+       XFRM_LOOKUP_KEEP_DST_REF = 1 << 2,
 };
 
 struct flowi;
index 534e1f2ac4fc36d5baeb7b3115dc95aaebd065d9..57639fca223a69823a48cecff03078387a917084 100644 (file)
@@ -79,6 +79,16 @@ void nf_log_packet(struct net *net,
                   const struct nf_loginfo *li,
                   const char *fmt, ...);
 
+__printf(8, 9)
+void nf_log_trace(struct net *net,
+                 u_int8_t pf,
+                 unsigned int hooknum,
+                 const struct sk_buff *skb,
+                 const struct net_device *in,
+                 const struct net_device *out,
+                 const struct nf_loginfo *li,
+                 const char *fmt, ...);
+
 struct nf_log_buf;
 
 struct nf_log_buf *nf_log_buf_open(void);
index eabd3a038674dd00f69263b47828134dd3a24bf1..c73e7abbbaa50e917e65a1117e881bd78665b12a 100644 (file)
@@ -91,6 +91,7 @@ struct vxlanhdr {
 
 #define VXLAN_N_VID     (1u << 24)
 #define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
+#define VXLAN_VNI_MASK  (VXLAN_VID_MASK << 8)
 #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
 
 struct vxlan_metadata {
index db81c65b8f4857c011a025e5b54026bf7d683f7c..d61be7297b2c88c867acbacadcacfd65045e6c50 100644 (file)
@@ -111,6 +111,7 @@ void        array_free(void *array, int n);
 void   target_core_setup_sub_cits(struct se_subsystem_api *);
 
 /* attribute helpers from target_core_device.c for backend drivers */
+bool   se_dev_check_wce(struct se_device *);
 int    se_dev_set_max_unmap_lba_count(struct se_device *, u32);
 int    se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
 int    se_dev_set_unmap_granularity(struct se_device *, u32);
index 23d561512f64fe65a5165a23d4620f7d457504a4..22317d2b52abcbe194ef8e9964bf179ae7d32846 100644 (file)
@@ -7,27 +7,26 @@
 #include <linux/ktime.h>
 #include <linux/tracepoint.h>
 
-struct device;
-struct regmap;
+#include "../../../drivers/base/regmap/internal.h"
 
 /*
  * Log register events
  */
 DECLARE_EVENT_CLASS(regmap_reg,
 
-       TP_PROTO(struct device *dev, unsigned int reg,
+       TP_PROTO(struct regmap *map, unsigned int reg,
                 unsigned int val),
 
-       TP_ARGS(dev, reg, val),
+       TP_ARGS(map, reg, val),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
-               __field(        unsigned int,   reg             )
-               __field(        unsigned int,   val             )
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   reg                     )
+               __field(        unsigned int,   val                     )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
                __entry->reg = reg;
                __entry->val = val;
        ),
@@ -39,45 +38,45 @@ DECLARE_EVENT_CLASS(regmap_reg,
 
 DEFINE_EVENT(regmap_reg, regmap_reg_write,
 
-       TP_PROTO(struct device *dev, unsigned int reg,
+       TP_PROTO(struct regmap *map, unsigned int reg,
                 unsigned int val),
 
-       TP_ARGS(dev, reg, val)
+       TP_ARGS(map, reg, val)
 
 );
 
 DEFINE_EVENT(regmap_reg, regmap_reg_read,
 
-       TP_PROTO(struct device *dev, unsigned int reg,
+       TP_PROTO(struct regmap *map, unsigned int reg,
                 unsigned int val),
 
-       TP_ARGS(dev, reg, val)
+       TP_ARGS(map, reg, val)
 
 );
 
 DEFINE_EVENT(regmap_reg, regmap_reg_read_cache,
 
-       TP_PROTO(struct device *dev, unsigned int reg,
+       TP_PROTO(struct regmap *map, unsigned int reg,
                 unsigned int val),
 
-       TP_ARGS(dev, reg, val)
+       TP_ARGS(map, reg, val)
 
 );
 
 DECLARE_EVENT_CLASS(regmap_block,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count),
+       TP_ARGS(map, reg, count),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
-               __field(        unsigned int,   reg             )
-               __field(        int,            count           )
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   reg                     )
+               __field(        int,            count                   )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
                __entry->reg = reg;
                __entry->count = count;
        ),
@@ -89,48 +88,48 @@ DECLARE_EVENT_CLASS(regmap_block,
 
 DEFINE_EVENT(regmap_block, regmap_hw_read_start,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count)
+       TP_ARGS(map, reg, count)
 );
 
 DEFINE_EVENT(regmap_block, regmap_hw_read_done,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count)
+       TP_ARGS(map, reg, count)
 );
 
 DEFINE_EVENT(regmap_block, regmap_hw_write_start,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count)
+       TP_ARGS(map, reg, count)
 );
 
 DEFINE_EVENT(regmap_block, regmap_hw_write_done,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count)
+       TP_ARGS(map, reg, count)
 );
 
 TRACE_EVENT(regcache_sync,
 
-       TP_PROTO(struct device *dev, const char *type,
+       TP_PROTO(struct regmap *map, const char *type,
                 const char *status),
 
-       TP_ARGS(dev, type, status),
+       TP_ARGS(map, type, status),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
-               __string(       status,         status          )
-               __string(       type,           type            )
-               __field(        int,            type            )
+               __string(       name,           regmap_name(map)        )
+               __string(       status,         status                  )
+               __string(       type,           type                    )
+               __field(        int,            type                    )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
                __assign_str(status, status);
                __assign_str(type, type);
        ),
@@ -141,17 +140,17 @@ TRACE_EVENT(regcache_sync,
 
 DECLARE_EVENT_CLASS(regmap_bool,
 
-       TP_PROTO(struct device *dev, bool flag),
+       TP_PROTO(struct regmap *map, bool flag),
 
-       TP_ARGS(dev, flag),
+       TP_ARGS(map, flag),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
-               __field(        int,            flag            )
+               __string(       name,           regmap_name(map)        )
+               __field(        int,            flag                    )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
                __entry->flag = flag;
        ),
 
@@ -161,32 +160,32 @@ DECLARE_EVENT_CLASS(regmap_bool,
 
 DEFINE_EVENT(regmap_bool, regmap_cache_only,
 
-       TP_PROTO(struct device *dev, bool flag),
+       TP_PROTO(struct regmap *map, bool flag),
 
-       TP_ARGS(dev, flag)
+       TP_ARGS(map, flag)
 
 );
 
 DEFINE_EVENT(regmap_bool, regmap_cache_bypass,
 
-       TP_PROTO(struct device *dev, bool flag),
+       TP_PROTO(struct regmap *map, bool flag),
 
-       TP_ARGS(dev, flag)
+       TP_ARGS(map, flag)
 
 );
 
 DECLARE_EVENT_CLASS(regmap_async,
 
-       TP_PROTO(struct device *dev),
+       TP_PROTO(struct regmap *map),
 
-       TP_ARGS(dev),
+       TP_ARGS(map),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
+               __string(       name,           regmap_name(map)        )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
        ),
 
        TP_printk("%s", __get_str(name))
@@ -194,50 +193,50 @@ DECLARE_EVENT_CLASS(regmap_async,
 
 DEFINE_EVENT(regmap_block, regmap_async_write_start,
 
-       TP_PROTO(struct device *dev, unsigned int reg, int count),
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
 
-       TP_ARGS(dev, reg, count)
+       TP_ARGS(map, reg, count)
 );
 
 DEFINE_EVENT(regmap_async, regmap_async_io_complete,
 
-       TP_PROTO(struct device *dev),
+       TP_PROTO(struct regmap *map),
 
-       TP_ARGS(dev)
+       TP_ARGS(map)
 
 );
 
 DEFINE_EVENT(regmap_async, regmap_async_complete_start,
 
-       TP_PROTO(struct device *dev),
+       TP_PROTO(struct regmap *map),
 
-       TP_ARGS(dev)
+       TP_ARGS(map)
 
 );
 
 DEFINE_EVENT(regmap_async, regmap_async_complete_done,
 
-       TP_PROTO(struct device *dev),
+       TP_PROTO(struct regmap *map),
 
-       TP_ARGS(dev)
+       TP_ARGS(map)
 
 );
 
 TRACE_EVENT(regcache_drop_region,
 
-       TP_PROTO(struct device *dev, unsigned int from,
+       TP_PROTO(struct regmap *map, unsigned int from,
                 unsigned int to),
 
-       TP_ARGS(dev, from, to),
+       TP_ARGS(map, from, to),
 
        TP_STRUCT__entry(
-               __string(       name,           dev_name(dev)   )
-               __field(        unsigned int,   from            )
-               __field(        unsigned int,   to              )
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   from                    )
+               __field(        unsigned int,   to                      )
        ),
 
        TP_fast_assign(
-               __assign_str(name, dev_name(dev));
+               __assign_str(name, regmap_name(map));
                __entry->from = from;
                __entry->to = to;
        ),
index 3c53eec4ae22697ecb87522bf83de79f4e7e2b0e..19c66fcbab8afb1ee5239140fab657b4fe52ed67 100644 (file)
@@ -60,7 +60,7 @@ struct virtio_blk_config {
        __u32 size_max;
        /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
        __u32 seg_max;
-       /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+       /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */
        struct virtio_blk_geometry {
                __u16 cylinders;
                __u8 heads;
@@ -119,7 +119,11 @@ struct virtio_blk_config {
 #define VIRTIO_BLK_T_BARRIER   0x80000000
 #endif /* !VIRTIO_BLK_NO_LEGACY */
 
-/* This is the first element of the read scatter-gather list. */
+/*
+ * This comes first in the read scatter-gather list.
+ * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated,
+ * this is the first element of the read scatter-gather list.
+ */
 struct virtio_blk_outhdr {
        /* VIRTIO_BLK_T* */
        __virtio32 type;
index 42b9370771b014d4b959cd4c0c67a7bcc7eee41d..cc18ef8825c0eddb493a1d1b8bc618f5d3ce74e8 100644 (file)
 
 #include <linux/virtio_types.h>
 
-#define VIRTIO_SCSI_CDB_SIZE   32
-#define VIRTIO_SCSI_SENSE_SIZE 96
+/* Default values of the CDB and sense data size configuration fields */
+#define VIRTIO_SCSI_CDB_DEFAULT_SIZE   32
+#define VIRTIO_SCSI_SENSE_DEFAULT_SIZE 96
+
+#ifndef VIRTIO_SCSI_CDB_SIZE
+#define VIRTIO_SCSI_CDB_SIZE VIRTIO_SCSI_CDB_DEFAULT_SIZE
+#endif
+#ifndef VIRTIO_SCSI_SENSE_SIZE
+#define VIRTIO_SCSI_SENSE_SIZE VIRTIO_SCSI_SENSE_DEFAULT_SIZE
+#endif
 
 /* SCSI command request, followed by data-out */
 struct virtio_scsi_cmd_req {
index f04daabfd1cffb78856e03b634b9d7c914faf4d1..453ef61311d4cf069669fb449270a0700ae0f2f9 100644 (file)
@@ -3591,7 +3591,7 @@ static void put_event(struct perf_event *event)
        ctx = perf_event_ctx_lock_nested(event, SINGLE_DEPTH_NESTING);
        WARN_ON_ONCE(ctx->parent_ctx);
        perf_remove_from_context(event, true);
-       mutex_unlock(&ctx->mutex);
+       perf_event_ctx_unlock(event, ctx);
 
        _free_event(event);
 }
index 01ca08804f5115a298cb89940e9da6ac804d00c3..3f9f1d6b4c2e5726217556a40454c46dbe368b89 100644 (file)
@@ -89,16 +89,28 @@ static bool klp_is_object_loaded(struct klp_object *obj)
 /* sets obj->mod if object is not vmlinux and module is found */
 static void klp_find_object_module(struct klp_object *obj)
 {
+       struct module *mod;
+
        if (!klp_is_module(obj))
                return;
 
        mutex_lock(&module_mutex);
        /*
-        * We don't need to take a reference on the module here because we have
-        * the klp_mutex, which is also taken by the module notifier.  This
-        * prevents any module from unloading until we release the klp_mutex.
+        * We do not want to block removal of patched modules and therefore
+        * we do not take a reference here. The patches are removed by
+        * a going module handler instead.
+        */
+       mod = find_module(obj->name);
+       /*
+        * Do not mess work of the module coming and going notifiers.
+        * Note that the patch might still be needed before the going handler
+        * is called. Module functions can be called even in the GOING state
+        * until mod->exit() finishes. This is especially important for
+        * patches that modify semantic of the functions.
         */
-       obj->mod = find_module(obj->name);
+       if (mod && mod->klp_alive)
+               obj->mod = mod;
+
        mutex_unlock(&module_mutex);
 }
 
@@ -767,6 +779,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
                return -EINVAL;
 
        obj->state = KLP_DISABLED;
+       obj->mod = NULL;
 
        klp_find_object_module(obj);
 
@@ -961,6 +974,15 @@ static int klp_module_notify(struct notifier_block *nb, unsigned long action,
 
        mutex_lock(&klp_mutex);
 
+       /*
+        * Each module has to know that the notifier has been called.
+        * We never know what module will get patched by a new patch.
+        */
+       if (action == MODULE_STATE_COMING)
+               mod->klp_alive = true;
+       else /* MODULE_STATE_GOING */
+               mod->klp_alive = false;
+
        list_for_each_entry(patch, &klp_patches, list) {
                for (obj = patch->objs; obj->funcs; obj++) {
                        if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
index 7a85967060a518a43c5da9125a03d701ab892304..f0f5c5c3de12e1a23b5aeebc7ec05da6e78d3c14 100644 (file)
@@ -139,6 +139,9 @@ static int lz4_uncompress(const char *source, char *dest, int osize)
                        /* Error: request to write beyond destination buffer */
                        if (cpy > oend)
                                goto _output_error;
+                       if ((ref + COPYLENGTH) > oend ||
+                                       (op + COPYLENGTH) > oend)
+                               goto _output_error;
                        LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
                        while (op < cpy)
                                *op++ = *ref++;
index d8e376a5f0f13d9eed735f62b81367b7bc685ebe..36a1a739ad68ff57eace5ba4bc4166faf12c485b 100644 (file)
@@ -658,14 +658,30 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
 static void p9_virtio_remove(struct virtio_device *vdev)
 {
        struct virtio_chan *chan = vdev->priv;
-
-       if (chan->inuse)
-               p9_virtio_close(chan->client);
-       vdev->config->del_vqs(vdev);
+       unsigned long warning_time;
 
        mutex_lock(&virtio_9p_lock);
+
+       /* Remove self from list so we don't get new users. */
        list_del(&chan->chan_list);
+       warning_time = jiffies;
+
+       /* Wait for existing users to close. */
+       while (chan->inuse) {
+               mutex_unlock(&virtio_9p_lock);
+               msleep(250);
+               if (time_after(jiffies, warning_time + 10 * HZ)) {
+                       dev_emerg(&vdev->dev,
+                                 "p9_virtio_remove: waiting for device in use.\n");
+                       warning_time = jiffies;
+               }
+               mutex_lock(&virtio_9p_lock);
+       }
+
        mutex_unlock(&virtio_9p_lock);
+
+       vdev->config->del_vqs(vdev);
+
        sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
        kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE);
        kfree(chan->tag);
index b087d278c6793f48f413082ff60fd8abbea49ff3..1849d96b3c91d82e20f85ca2579546857343d0f2 100644 (file)
@@ -563,6 +563,8 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
         */
        del_nbp(p);
 
+       dev_set_mtu(br->dev, br_min_mtu(br));
+
        spin_lock_bh(&br->lock);
        changed_addr = br_stp_recalculate_bridge_id(br);
        spin_unlock_bh(&br->lock);
index 769b185fefbd5f6bb6d4e68c1bcb0caeafa23d25..a6e2da0bc7184501ed5eb2bcef0e5169be2cf276 100644 (file)
@@ -281,7 +281,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
        int copylen;
 
        ret = -EOPNOTSUPP;
-       if (m->msg_flags&MSG_OOB)
+       if (flags & MSG_OOB)
                goto read_error;
 
        skb = skb_recv_datagram(sk, flags, 0 , &ret);
index 94d3d5e978832cba85b7212988f735780ceed9dd..f7bd286a82807148bed32622e5de2f975450c877 100644 (file)
@@ -49,6 +49,13 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
            __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
            __get_user(kmsg->msg_flags, &umsg->msg_flags))
                return -EFAULT;
+
+       if (!uaddr)
+               kmsg->msg_namelen = 0;
+
+       if (kmsg->msg_namelen < 0)
+               return -EINVAL;
+
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
                kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        kmsg->msg_control = compat_ptr(tmp3);
index 25b4b5d2348595d0a609733b4e4fc6d83a282c93..ee0608bb3bc087212d12bac729677bf454053560 100644 (file)
@@ -2166,28 +2166,28 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
                        }
                }
                err = rtnl_configure_link(dev, ifm);
-               if (err < 0) {
-                       if (ops->newlink) {
-                               LIST_HEAD(list_kill);
-
-                               ops->dellink(dev, &list_kill);
-                               unregister_netdevice_many(&list_kill);
-                       } else {
-                               unregister_netdevice(dev);
-                       }
-                       goto out;
-               }
-
+               if (err < 0)
+                       goto out_unregister;
                if (link_net) {
                        err = dev_change_net_namespace(dev, dest_net, ifname);
                        if (err < 0)
-                               unregister_netdevice(dev);
+                               goto out_unregister;
                }
 out:
                if (link_net)
                        put_net(link_net);
                put_net(dest_net);
                return err;
+out_unregister:
+               if (ops->newlink) {
+                       LIST_HEAD(list_kill);
+
+                       ops->dellink(dev, &list_kill);
+                       unregister_netdevice_many(&list_kill);
+               } else {
+                       unregister_netdevice(dev);
+               }
+               goto out;
        }
 }
 
index f80507823531b9000a4b8b2d8d622717ec508173..8e4ac97c84775f15c786020ff87a2ef22a8dbac8 100644 (file)
@@ -3733,9 +3733,13 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
                     struct sock *sk, int tstype)
 {
        struct sk_buff *skb;
-       bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
+       bool tsonly;
 
-       if (!sk || !skb_may_tx_timestamp(sk, tsonly))
+       if (!sk)
+               return;
+
+       tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
+       if (!skb_may_tx_timestamp(sk, tsonly))
                return;
 
        if (tsonly)
@@ -4173,7 +4177,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->ignore_df = 0;
        skb_dst_drop(skb);
        skb->mark = 0;
-       skb->sender_cpu = 0;
+       skb_sender_cpu_clear(skb);
        skb_init_secmark(skb);
        secpath_reset(skb);
        nf_reset(skb);
index 93c8b20c91e496648f7f2e5c769c062ca2dd679d..78e89eb7eb705624d3ff63324f5002ae10b51145 100644 (file)
@@ -1655,6 +1655,10 @@ void sock_rfree(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(sock_rfree);
 
+/*
+ * Buffer destructor for skbs that are not used directly in read or write
+ * path, e.g. for error handler skbs. Automatically called from kfree_skb.
+ */
 void sock_efree(struct sk_buff *skb)
 {
        sock_put(skb->sk);
index 433424804284cad8921a2efb6427a615b740ecc5..8ce351ffceb122568ae05587a0b1dc3544d476d7 100644 (file)
@@ -25,6 +25,8 @@
 static int zero = 0;
 static int one = 1;
 static int ushort_max = USHRT_MAX;
+static int min_sndbuf = SOCK_MIN_SNDBUF;
+static int min_rcvbuf = SOCK_MIN_RCVBUF;
 
 static int net_msg_warn;       /* Unused, but still a sysctl */
 
@@ -237,7 +239,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_sndbuf,
        },
        {
                .procname       = "rmem_max",
@@ -245,7 +247,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_rcvbuf,
        },
        {
                .procname       = "wmem_default",
@@ -253,7 +255,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_sndbuf,
        },
        {
                .procname       = "rmem_default",
@@ -261,7 +263,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_rcvbuf,
        },
        {
                .procname       = "dev_weight",
index 14d02ea905b6bea37240f88054f0cd42db73c4c2..3e44b9b0b78ece392a1f1b0763b5445cadfb2557 100644 (file)
@@ -268,6 +268,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
                release_sock(sk);
                if (reqsk_queue_empty(&icsk->icsk_accept_queue))
                        timeo = schedule_timeout(timeo);
+               sched_annotate_sleep();
                lock_sock(sk);
                err = 0;
                if (!reqsk_queue_empty(&icsk->icsk_accept_queue))
index 81751f12645f6224a7f076dea1da2fc0d638819a..592aff37366bb932c0aeb2bad944b5470374ec21 100644 (file)
@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler(
        mutex_unlock(&inet_diag_table_mutex);
 }
 
+static size_t inet_sk_attr_size(void)
+{
+       return    nla_total_size(sizeof(struct tcp_info))
+               + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
+               + nla_total_size(1) /* INET_DIAG_TOS */
+               + nla_total_size(1) /* INET_DIAG_TCLASS */
+               + nla_total_size(sizeof(struct inet_diag_meminfo))
+               + nla_total_size(sizeof(struct inet_diag_msg))
+               + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
+               + nla_total_size(TCP_CA_NAME_MAX)
+               + nla_total_size(sizeof(struct tcpvegas_info))
+               + 64;
+}
+
 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
                              struct user_namespace *user_ns,                   
@@ -326,9 +340,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
        if (err)
                goto out;
 
-       rep = nlmsg_new(sizeof(struct inet_diag_msg) +
-                       sizeof(struct inet_diag_meminfo) +
-                       sizeof(struct tcp_info) + 64, GFP_KERNEL);
+       rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL);
        if (!rep) {
                err = -ENOMEM;
                goto out;
index 787b3c294ce672244ce08c5426c03bbd1f71c0f3..d9bc28ac5d1b97340e79aae1eefcbac3f463251a 100644 (file)
@@ -67,6 +67,7 @@ static int ip_forward_finish(struct sk_buff *skb)
        if (unlikely(opt->optlen))
                ip_forward_options(skb);
 
+       skb_sender_cpu_clear(skb);
        return dst_output(skb);
 }
 
index 99e810f84671bbdb80e33c6915cc7be49ba0f1bb..cf5e82f39d3b87d7f8163320bffbc26af38d6f98 100644 (file)
@@ -272,9 +272,9 @@ static void trace_packet(const struct sk_buff *skb,
                    &chainname, &comment, &rulenum) != 0)
                        break;
 
-       nf_log_packet(net, AF_INET, hook, skb, in, out, &trace_loginfo,
-                     "TRACE: %s:%s:%s:%u ",
-                     tablename, chainname, comment, rulenum);
+       nf_log_trace(net, AF_INET, hook, skb, in, out, &trace_loginfo,
+                    "TRACE: %s:%s:%s:%u ",
+                    tablename, chainname, comment, rulenum);
 }
 #endif
 
index d694088214cd87fa50e413730402499610c546e6..62856e185a935e44deb26de59ff94c8bf7500579 100644 (file)
@@ -378,6 +378,12 @@ EXPORT_SYMBOL_GPL(tcp_slow_start);
  */
 void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked)
 {
+       /* If credits accumulated at a higher w, apply them gently now. */
+       if (tp->snd_cwnd_cnt >= w) {
+               tp->snd_cwnd_cnt = 0;
+               tp->snd_cwnd++;
+       }
+
        tp->snd_cwnd_cnt += acked;
        if (tp->snd_cwnd_cnt >= w) {
                u32 delta = tp->snd_cwnd_cnt / w;
index 4b276d1ed9807057986bd3b050e2e901bf1afec0..06d3d665a9fd1bfda5688907a284de83697273f6 100644 (file)
@@ -306,8 +306,10 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked)
                }
        }
 
-       if (ca->cnt == 0)                       /* cannot be zero */
-               ca->cnt = 1;
+       /* The maximum rate of cwnd increase CUBIC allows is 1 packet per
+        * 2 packets ACKed, meaning cwnd grows at 1.5x per RTT.
+        */
+       ca->cnt = max(ca->cnt, 2U);
 }
 
 static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
index a2a796c5536b032264e2a71f596f673e8307f25c..1db253e36045ac038d7449a06d312275535a8014 100644 (file)
@@ -2773,15 +2773,11 @@ void tcp_send_fin(struct sock *sk)
        } else {
                /* Socket is locked, keep trying until memory is available. */
                for (;;) {
-                       skb = alloc_skb_fclone(MAX_TCP_HEADER,
-                                              sk->sk_allocation);
+                       skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
                        if (skb)
                                break;
                        yield();
                }
-
-               /* Reserve space for headers and prepare control bits. */
-               skb_reserve(skb, MAX_TCP_HEADER);
                /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
                tcp_init_nondata_skb(skb, tp->write_seq,
                                     TCPHDR_ACK | TCPHDR_FIN);
index d5f6bd9a210ab93ed27177ecffc9499259dbe999..dab73813cb9208dafaae1277e281c2255601a771 100644 (file)
@@ -63,6 +63,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
                return err;
 
        IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
+       skb->protocol = htons(ETH_P_IP);
 
        return x->outer_mode->output2(x, skb);
 }
@@ -71,7 +72,6 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
 int xfrm4_output_finish(struct sk_buff *skb)
 {
        memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-       skb->protocol = htons(ETH_P_IP);
 
 #ifdef CONFIG_NETFILTER
        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
index b4d5e1d97c1b2576fc02a15b7a05a773197bb8e0..27ca79682efbf681a0ab6073f50f8fa73214028e 100644 (file)
@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
                                goto again;
                        flp6->saddr = saddr;
                }
+               err = rt->dst.error;
                goto out;
        }
 again:
index 0a04a37305d5ab56d0f24cc3b3f917386cb62bd8..7e80b61b51ff474db6c188218b70f12709209256 100644 (file)
@@ -318,6 +318,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
 
 static inline int ip6_forward_finish(struct sk_buff *skb)
 {
+       skb_sender_cpu_clear(skb);
        return dst_output(skb);
 }
 
index 266a264ec21273147b32d75ac7bde55afdd1b4cf..ddd94eca19b3986e4fc0b1ff684eee401032815e 100644 (file)
@@ -314,7 +314,7 @@ static int ip6_tnl_create2(struct net_device *dev)
  *   Create tunnel matching given parameters.
  *
  * Return:
- *   created tunnel or NULL
+ *   created tunnel or error pointer
  **/
 
 static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
@@ -322,7 +322,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
        struct net_device *dev;
        struct ip6_tnl *t;
        char name[IFNAMSIZ];
-       int err;
+       int err = -ENOMEM;
 
        if (p->name[0])
                strlcpy(name, p->name, IFNAMSIZ);
@@ -348,7 +348,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
 failed_free:
        ip6_dev_free(dev);
 failed:
-       return NULL;
+       return ERR_PTR(err);
 }
 
 /**
@@ -362,7 +362,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
  *   tunnel device is created and registered for use.
  *
  * Return:
- *   matching tunnel or NULL
+ *   matching tunnel or error pointer
  **/
 
 static struct ip6_tnl *ip6_tnl_locate(struct net *net,
@@ -380,13 +380,13 @@ static struct ip6_tnl *ip6_tnl_locate(struct net *net,
                if (ipv6_addr_equal(local, &t->parms.laddr) &&
                    ipv6_addr_equal(remote, &t->parms.raddr)) {
                        if (create)
-                               return NULL;
+                               return ERR_PTR(-EEXIST);
 
                        return t;
                }
        }
        if (!create)
-               return NULL;
+               return ERR_PTR(-ENODEV);
        return ip6_tnl_create(net, p);
 }
 
@@ -1420,7 +1420,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        }
                        ip6_tnl_parm_from_user(&p1, &p);
                        t = ip6_tnl_locate(net, &p1, 0);
-                       if (t == NULL)
+                       if (IS_ERR(t))
                                t = netdev_priv(dev);
                } else {
                        memset(&p, 0, sizeof(p));
@@ -1445,7 +1445,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                ip6_tnl_parm_from_user(&p1, &p);
                t = ip6_tnl_locate(net, &p1, cmd == SIOCADDTUNNEL);
                if (cmd == SIOCCHGTUNNEL) {
-                       if (t != NULL) {
+                       if (!IS_ERR(t)) {
                                if (t->dev != dev) {
                                        err = -EEXIST;
                                        break;
@@ -1457,14 +1457,15 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        else
                                err = ip6_tnl_update(t, &p1);
                }
-               if (t) {
+               if (!IS_ERR(t)) {
                        err = 0;
                        ip6_tnl_parm_to_user(&p, &t->parms);
                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
                                err = -EFAULT;
 
-               } else
-                       err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+               } else {
+                       err = PTR_ERR(t);
+               }
                break;
        case SIOCDELTUNNEL:
                err = -EPERM;
@@ -1478,7 +1479,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        err = -ENOENT;
                        ip6_tnl_parm_from_user(&p1, &p);
                        t = ip6_tnl_locate(net, &p1, 0);
-                       if (t == NULL)
+                       if (IS_ERR(t))
                                break;
                        err = -EPERM;
                        if (t->dev == ip6n->fb_tnl_dev)
@@ -1672,12 +1673,13 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
                           struct nlattr *tb[], struct nlattr *data[])
 {
        struct net *net = dev_net(dev);
-       struct ip6_tnl *nt;
+       struct ip6_tnl *nt, *t;
 
        nt = netdev_priv(dev);
        ip6_tnl_netlink_parms(data, &nt->parms);
 
-       if (ip6_tnl_locate(net, &nt->parms, 0))
+       t = ip6_tnl_locate(net, &nt->parms, 0);
+       if (!IS_ERR(t))
                return -EEXIST;
 
        return ip6_tnl_create2(dev);
@@ -1697,8 +1699,7 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
        ip6_tnl_netlink_parms(data, &p);
 
        t = ip6_tnl_locate(net, &p, 0);
-
-       if (t) {
+       if (!IS_ERR(t)) {
                if (t->dev != dev)
                        return -EEXIST;
        } else
index e080fbbbc0e5ce8d4d71014eed149e6b34250b62..bb00c6f2a8855fb72dcc6a1bc5b496e8216d683f 100644 (file)
@@ -298,9 +298,9 @@ static void trace_packet(const struct sk_buff *skb,
                    &chainname, &comment, &rulenum) != 0)
                        break;
 
-       nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo,
-                     "TRACE: %s:%s:%s:%u ",
-                     tablename, chainname, comment, rulenum);
+       nf_log_trace(net, AF_INET6, hook, skb, in, out, &trace_loginfo,
+                    "TRACE: %s:%s:%s:%u ",
+                    tablename, chainname, comment, rulenum);
 }
 #endif
 
index ab889bb16b3cb077d26ddd2837b8b2eaaf1de666..be2c0ba82c8525ca466468ae45b05df5b35f85b6 100644 (file)
@@ -112,11 +112,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
                fptr->nexthdr = nexthdr;
                fptr->reserved = 0;
-               if (skb_shinfo(skb)->ip6_frag_id)
-                       fptr->identification = skb_shinfo(skb)->ip6_frag_id;
-               else
-                       ipv6_select_ident(fptr,
-                                         (struct rt6_info *)skb_dst(skb));
+               if (!skb_shinfo(skb)->ip6_frag_id)
+                       ipv6_proxy_select_ident(skb);
+               fptr->identification = skb_shinfo(skb)->ip6_frag_id;
 
                /* Fragment the skb. ipv6 header and the remaining fields of the
                 * fragment header are updated in ipv6_gso_segment()
index ca3f29b98ae5d76b7e69c38f617362a90fd9fd04..010f8bd2d577f9767d7d44182b246e62f4a118f6 100644 (file)
@@ -114,6 +114,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
                return err;
 
        skb->ignore_df = 1;
+       skb->protocol = htons(ETH_P_IPV6);
 
        return x->outer_mode->output2(x, skb);
 }
@@ -122,7 +123,6 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
 int xfrm6_output_finish(struct sk_buff *skb)
 {
        memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
-       skb->protocol = htons(ETH_P_IPV6);
 
 #ifdef CONFIG_NETFILTER
        IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
index 48bf5a06847bd59db7834758b22aa9208d727940..8d2d01b4800a197eaaa64fb184f56c58920ad462 100644 (file)
@@ -200,6 +200,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 
 #if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPPROTO_MH:
+                       offset += ipv6_optlen(exthdr);
                        if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
                                struct ip6_mh *mh;
 
index 3afe36824703f49dcfe374e103b6372a9851b8aa..8d53d65bd2abc2d993ae5dbc7df37b707fd9ec13 100644 (file)
@@ -58,13 +58,24 @@ struct ieee80211_local;
 #define IEEE80211_UNSET_POWER_LEVEL    INT_MIN
 
 /*
- * Some APs experience problems when working with U-APSD. Decrease the
- * probability of that happening by using legacy mode for all ACs but VO.
- * The AP that caused us trouble was a Cisco 4410N. It ignores our
- * setting, and always treats non-VO ACs as legacy.
+ * Some APs experience problems when working with U-APSD. Decreasing the
+ * probability of that happening by using legacy mode for all ACs but VO isn't
+ * enough.
+ *
+ * Cisco 4410N originally forced us to enable VO by default only because it
+ * treated non-VO ACs as legacy.
+ *
+ * However some APs (notably Netgear R7000) silently reclassify packets to
+ * different ACs. Since u-APSD ACs require trigger frames for frame retrieval
+ * clients would never see some frames (e.g. ARP responses) or would fetch them
+ * accidentally after a long time.
+ *
+ * It makes little sense to enable u-APSD queues by default because it needs
+ * userspace applications to be aware of it to actually take advantage of the
+ * possible additional powersavings. Implicitly depending on driver autotrigger
+ * frame support doesn't make much sense.
  */
-#define IEEE80211_DEFAULT_UAPSD_QUEUES \
-       IEEE80211_WMM_IE_STA_QOSINFO_AC_VO
+#define IEEE80211_DEFAULT_UAPSD_QUEUES 0
 
 #define IEEE80211_DEFAULT_MAX_SP_LEN           \
        IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
@@ -453,6 +464,7 @@ struct ieee80211_if_managed {
        unsigned int flags;
 
        bool csa_waiting_bcn;
+       bool csa_ignored_same_chan;
 
        bool beacon_crc_valid;
        u32 beacon_crc;
index 10ac6324c1d014c708749748ce89ef31055561cf..142f66aece18a8789205fc12b0e1d7c7816d0863 100644 (file)
@@ -1150,6 +1150,17 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                return;
        }
 
+       if (cfg80211_chandef_identical(&csa_ie.chandef,
+                                      &sdata->vif.bss_conf.chandef)) {
+               if (ifmgd->csa_ignored_same_chan)
+                       return;
+               sdata_info(sdata,
+                          "AP %pM tries to chanswitch to same channel, ignore\n",
+                          ifmgd->associated->bssid);
+               ifmgd->csa_ignored_same_chan = true;
+               return;
+       }
+
        mutex_lock(&local->mtx);
        mutex_lock(&local->chanctx_mtx);
        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
@@ -1210,6 +1221,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        sdata->vif.csa_active = true;
        sdata->csa_chandef = csa_ie.chandef;
        sdata->csa_block_tx = csa_ie.mode;
+       ifmgd->csa_ignored_same_chan = false;
 
        if (sdata->csa_block_tx)
                ieee80211_stop_vif_queues(local, sdata,
@@ -2090,6 +2102,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        sdata->vif.csa_active = false;
        ifmgd->csa_waiting_bcn = false;
+       ifmgd->csa_ignored_same_chan = false;
        if (sdata->csa_block_tx) {
                ieee80211_wake_vif_queues(local, sdata,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -3204,7 +3217,8 @@ static const u64 care_about_ies =
        (1ULL << WLAN_EID_CHANNEL_SWITCH) |
        (1ULL << WLAN_EID_PWR_CONSTRAINT) |
        (1ULL << WLAN_EID_HT_CAPABILITY) |
-       (1ULL << WLAN_EID_HT_OPERATION);
+       (1ULL << WLAN_EID_HT_OPERATION) |
+       (1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
 
 static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                     struct ieee80211_mgmt *mgmt, size_t len,
index 1101563357eae365f1e1a1df926ecf36fdc0570b..944bdc04e913d2f599b6c5845ee2549abba20a1c 100644 (file)
@@ -2214,6 +2214,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
+       if (ieee80211_drop_unencrypted(rx, hdr->frame_control))
+               return RX_DROP_MONITOR;
+
        /* frame is in RMC, don't forward */
        if (ieee80211_is_data(hdr->frame_control) &&
            is_multicast_ether_addr(hdr->addr1) &&
index 8428f4a954795657a32a24f77a0f9c9ae6591b7e..747bdcf72e92788574ec3e2e635b5e6b96cb75f0 100644 (file)
@@ -3178,7 +3178,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                wdev_iter = &sdata_iter->wdev;
 
                if (sdata_iter == sdata ||
-                   rcu_access_pointer(sdata_iter->vif.chanctx_conf) == NULL ||
+                   !ieee80211_sdata_running(sdata_iter) ||
                    local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
                        continue;
 
index 0d8448f19dfe982f64879d9dc55ba7d746696196..675d12c69e325c70e46ca5e5522fb5f8c77b7d8b 100644 (file)
@@ -212,6 +212,30 @@ void nf_log_packet(struct net *net,
 }
 EXPORT_SYMBOL(nf_log_packet);
 
+void nf_log_trace(struct net *net,
+                 u_int8_t pf,
+                 unsigned int hooknum,
+                 const struct sk_buff *skb,
+                 const struct net_device *in,
+                 const struct net_device *out,
+                 const struct nf_loginfo *loginfo, const char *fmt, ...)
+{
+       va_list args;
+       char prefix[NF_LOG_PREFIXLEN];
+       const struct nf_logger *logger;
+
+       rcu_read_lock();
+       logger = rcu_dereference(net->nf.nf_loggers[pf]);
+       if (logger) {
+               va_start(args, fmt);
+               vsnprintf(prefix, sizeof(prefix), fmt, args);
+               va_end(args);
+               logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
+       }
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL(nf_log_trace);
+
 #define S_SIZE (1024 - (sizeof(unsigned int) + 1))
 
 struct nf_log_buf {
index 6ab777912237976ed72cdd34f18a7bea336f44ae..ac1a9528dbf2e4af0d33fec5667369d23ed179e4 100644 (file)
@@ -1225,7 +1225,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
 
        if (nla[NFTA_CHAIN_POLICY]) {
                if ((chain != NULL &&
-                   !(chain->flags & NFT_BASE_CHAIN)) ||
+                   !(chain->flags & NFT_BASE_CHAIN)))
+                       return -EOPNOTSUPP;
+
+               if (chain == NULL &&
                    nla[NFTA_CHAIN_HOOK] == NULL)
                        return -EOPNOTSUPP;
 
index 3b90eb2b2c55453e989c891a3f815be6e1da22d1..2d298dccb6dd3fc5589be16021c843d741a4c025 100644 (file)
@@ -94,10 +94,10 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
 {
        struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
 
-       nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
-                     pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
-                     chain->table->name, chain->name, comments[type],
-                     rulenum);
+       nf_log_trace(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
+                    pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
+                    chain->table->name, chain->name, comments[type],
+                    rulenum);
 }
 
 unsigned int
index a5599fc51a6f3f87db4d63ecd20073481520a238..54330fb5efaf632d39d3e00135ac3360bdfdb80d 100644 (file)
@@ -77,6 +77,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple,
        if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM])
                return -EINVAL;
 
+       /* Not all fields are initialized so first zero the tuple */
+       memset(tuple, 0, sizeof(struct nf_conntrack_tuple));
+
        tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM]));
        tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]);
 
index 213584cf04b34858164a07f99f1fc0b623c1ab44..65f3e2b6be44031448d85323ccf17cddaffd5557 100644 (file)
@@ -133,6 +133,9 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
                entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
                break;
        case AF_INET6:
+               if (proto)
+                       entry->e6.ipv6.flags |= IP6T_F_PROTO;
+
                entry->e6.ipv6.proto = proto;
                entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
                break;
@@ -344,6 +347,9 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
                entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
                break;
        case AF_INET6:
+               if (proto)
+                       entry->e6.ipv6.flags |= IP6T_F_PROTO;
+
                entry->e6.ipv6.proto = proto;
                entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
                break;
index c82df0a48fcd8a649921b3fcb6b5d1edd39c6295..37c15e6748841053df56fe092a49ced6fb06b077 100644 (file)
@@ -153,6 +153,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
                                iter->err = err;
                                goto out;
                        }
+
+                       continue;
                }
 
                if (iter->count < iter->skip)
index ef8a926752a97542f6f2f8eeb378e150958bff3d..50e1e5aaf4ce82ff7bbf1ee7171aaa51d54eefd1 100644 (file)
@@ -513,8 +513,8 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par)
 {
        const struct ip6t_ip6 *i = par->entryinfo;
 
-       if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
-           && !(i->flags & IP6T_INV_PROTO))
+       if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&
+           !(i->invflags & IP6T_INV_PROTO))
                return 0;
 
        pr_info("Can be used only in combination with "
index a817705ce2d0e9246388c2c65d77b4c486a8feba..dba8d0864f18046ee87a168d49cc159518fa2916 100644 (file)
@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool,
                        int *unpinned);
 static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr);
 
-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id)
+static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst,
+                            struct rds_iw_device **rds_iwdev,
+                            struct rdma_cm_id **cm_id)
 {
        struct rds_iw_device *iwdev;
        struct rds_iw_cm_id *i_cm_id;
@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
                                src_addr->sin_port,
                                dst_addr->sin_addr.s_addr,
                                dst_addr->sin_port,
-                               rs->rs_bound_addr,
-                               rs->rs_bound_port,
-                               rs->rs_conn_addr,
-                               rs->rs_conn_port);
+                               src->sin_addr.s_addr,
+                               src->sin_port,
+                               dst->sin_addr.s_addr,
+                               dst->sin_port);
 #ifdef WORKING_TUPLE_DETECTION
-                       if (src_addr->sin_addr.s_addr == rs->rs_bound_addr &&
-                           src_addr->sin_port == rs->rs_bound_port &&
-                           dst_addr->sin_addr.s_addr == rs->rs_conn_addr &&
-                           dst_addr->sin_port == rs->rs_conn_port) {
+                       if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr &&
+                           src_addr->sin_port == src->sin_port &&
+                           dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr &&
+                           dst_addr->sin_port == dst->sin_port) {
 #else
                        /* FIXME - needs to compare the local and remote
                         * ipaddr/port tuple, but the ipaddr is the only
@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
                         * zero'ed.  It doesn't appear to be properly populated
                         * during connection setup...
                         */
-                       if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) {
+                       if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) {
 #endif
                                spin_unlock_irq(&iwdev->spinlock);
                                *rds_iwdev = iwdev;
@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i
 {
        struct sockaddr_in *src_addr, *dst_addr;
        struct rds_iw_device *rds_iwdev_old;
-       struct rds_sock rs;
        struct rdma_cm_id *pcm_id;
        int rc;
 
        src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr;
        dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr;
 
-       rs.rs_bound_addr = src_addr->sin_addr.s_addr;
-       rs.rs_bound_port = src_addr->sin_port;
-       rs.rs_conn_addr = dst_addr->sin_addr.s_addr;
-       rs.rs_conn_port = dst_addr->sin_port;
-
-       rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id);
+       rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id);
        if (rc)
                rds_iw_remove_cm_id(rds_iwdev, cm_id);
 
@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents,
        struct rds_iw_device *rds_iwdev;
        struct rds_iw_mr *ibmr = NULL;
        struct rdma_cm_id *cm_id;
+       struct sockaddr_in src = {
+               .sin_addr.s_addr = rs->rs_bound_addr,
+               .sin_port = rs->rs_bound_port,
+       };
+       struct sockaddr_in dst = {
+               .sin_addr.s_addr = rs->rs_conn_addr,
+               .sin_port = rs->rs_conn_port,
+       };
        int ret;
 
-       ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id);
+       ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id);
        if (ret || !cm_id) {
                ret = -ENODEV;
                goto out;
index 4575485ad1b4d02796717879e09ad9078e232617..19a560626dc4f4232592e7d34381a859a04b6f4c 100644 (file)
@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
                if (!skb) {
                        /* nothing remains on the queue */
                        if (copied &&
-                           (msg->msg_flags & MSG_PEEK || timeo == 0))
+                           (flags & MSG_PEEK || timeo == 0))
                                goto out;
 
                        /* wait for a message to turn up */
index 82c5d7fc19881577d888fad3d5b0369e4698172b..5f6288fa3f1247462897cd747364dfbc9e0da843 100644 (file)
@@ -25,21 +25,41 @@ static int tcf_bpf(struct sk_buff *skb, const struct tc_action *a,
                   struct tcf_result *res)
 {
        struct tcf_bpf *b = a->priv;
-       int action;
-       int filter_res;
+       int action, filter_res;
 
        spin_lock(&b->tcf_lock);
+
        b->tcf_tm.lastuse = jiffies;
        bstats_update(&b->tcf_bstats, skb);
-       action = b->tcf_action;
 
        filter_res = BPF_PROG_RUN(b->filter, skb);
-       if (filter_res == 0) {
-               /* Return code 0 from the BPF program
-                * is being interpreted as a drop here.
-                */
-               action = TC_ACT_SHOT;
+
+       /* A BPF program may overwrite the default action opcode.
+        * Similarly as in cls_bpf, if filter_res == -1 we use the
+        * default action specified from tc.
+        *
+        * In case a different well-known TC_ACT opcode has been
+        * returned, it will overwrite the default one.
+        *
+        * For everything else that is unkown, TC_ACT_UNSPEC is
+        * returned.
+        */
+       switch (filter_res) {
+       case TC_ACT_PIPE:
+       case TC_ACT_RECLASSIFY:
+       case TC_ACT_OK:
+               action = filter_res;
+               break;
+       case TC_ACT_SHOT:
+               action = filter_res;
                b->tcf_qstats.drops++;
+               break;
+       case TC_ACT_UNSPEC:
+               action = b->tcf_action;
+               break;
+       default:
+               action = TC_ACT_UNSPEC;
+               break;
        }
 
        spin_unlock(&b->tcf_lock);
index 09487afbfd5187a312ab155df5da43548d0c326b..95fdf4e4005190704dcd405e6b9422f8f56ba796 100644 (file)
@@ -78,8 +78,11 @@ struct tc_u_hnode {
        struct tc_u_common      *tp_c;
        int                     refcnt;
        unsigned int            divisor;
-       struct tc_u_knode __rcu *ht[1];
        struct rcu_head         rcu;
+       /* The 'ht' field MUST be the last field in structure to allow for
+        * more entries allocated at end of structure.
+        */
+       struct tc_u_knode __rcu *ht[1];
 };
 
 struct tc_u_common {
index bbedbfcb42c2505fceb57fa058f262d90e1670ed..245330ca0015c2fd2548ead861d379714151c901 100644 (file)
@@ -1702,6 +1702,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
 
        if (len > INT_MAX)
                len = INT_MAX;
+       if (unlikely(!access_ok(VERIFY_READ, buff, len)))
+               return -EFAULT;
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
@@ -1760,6 +1762,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
 
        if (size > INT_MAX)
                size = INT_MAX;
+       if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size)))
+               return -EFAULT;
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
index be25015380118bbd60e0b760e956a0cd9b58d3ed..b6f84f6a2a095ef0c94891f796ef6cf7cf9af65f 100644 (file)
@@ -4400,6 +4400,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
        if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
                return -EINVAL;
 
+       /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
+        * as userspace might just pass through the capabilities from the IEs
+        * directly, rather than enforcing this restriction and returning an
+        * error in this case.
+        */
+       if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
+               params.ht_capa = NULL;
+               params.vht_capa = NULL;
+       }
+
        /* When you run into this, adjust the code below for the new flag */
        BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
 
index cee479bc655c4f317edb4e90cbcb06ec3b424b81..638af0655aaf8ec600ae5f6b201e252ca229d89d 100644 (file)
@@ -2269,11 +2269,9 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
                 * have the xfrm_state's. We need to wait for KM to
                 * negotiate new SA's or bail out with error.*/
                if (net->xfrm.sysctl_larval_drop) {
-                       dst_release(dst);
-                       xfrm_pols_put(pols, drop_pols);
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
-
-                       return ERR_PTR(-EREMOTE);
+                       err = -EREMOTE;
+                       goto error;
                }
 
                err = -EAGAIN;
@@ -2324,7 +2322,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
 error:
        dst_release(dst);
 dropdst:
-       dst_release(dst_orig);
+       if (!(flags & XFRM_LOOKUP_KEEP_DST_REF))
+               dst_release(dst_orig);
        xfrm_pols_put(pols, drop_pols);
        return ERR_PTR(err);
 }
@@ -2338,7 +2337,8 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
                                    struct sock *sk, int flags)
 {
        struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk,
-                                           flags | XFRM_LOOKUP_QUEUE);
+                                           flags | XFRM_LOOKUP_QUEUE |
+                                           XFRM_LOOKUP_KEEP_DST_REF);
 
        if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
                return make_blackhole(net, dst_orig->ops->family, dst_orig);
index fe18071bf93aab4d44e779f9b7daaca3a2815b5b..8ec5289f8e058538892aa04c402a4db9967c94c7 100644 (file)
@@ -687,13 +687,30 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
        return val;
 }
 
+/* is this a stereo widget or a stereo-to-mono mix? */
+static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
+{
+       unsigned int wcaps = get_wcaps(codec, nid);
+       hda_nid_t conn;
+
+       if (wcaps & AC_WCAP_STEREO)
+               return true;
+       if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
+               return false;
+       if (snd_hda_get_num_conns(codec, nid) != 1)
+               return false;
+       if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
+               return false;
+       return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
+}
+
 /* initialize the amp value (only at the first time) */
 static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
 {
        unsigned int caps = query_amp_caps(codec, nid, dir);
        int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
 
-       if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+       if (is_stereo_amps(codec, nid, dir))
                snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
        else
                snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
@@ -703,7 +720,7 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
 static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
                      unsigned int mask, unsigned int val)
 {
-       if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+       if (is_stereo_amps(codec, nid, dir))
                return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
                                                mask, val);
        else
index ce5a6da834199bd2acd7e6ee18fd123b4f078820..05e19f78b4cb8689ff8ac1b0b4f699bdbf5759da 100644 (file)
@@ -134,13 +134,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer,
                    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
 }
 
+/* is this a stereo widget or a stereo-to-mono mix? */
+static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
+                          int dir, unsigned int wcaps, int indices)
+{
+       hda_nid_t conn;
+
+       if (wcaps & AC_WCAP_STEREO)
+               return true;
+       /* check for a stereo-to-mono mix; it must be:
+        * only a single connection, only for input, and only a mixer widget
+        */
+       if (indices != 1 || dir != HDA_INPUT ||
+           get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
+               return false;
+
+       if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
+               return false;
+       /* the connection source is a stereo? */
+       wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
+       return !!(wcaps & AC_WCAP_STEREO);
+}
+
 static void print_amp_vals(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid,
-                          int dir, int stereo, int indices)
+                          int dir, unsigned int wcaps, int indices)
 {
        unsigned int val;
+       bool stereo;
        int i;
 
+       stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
+
        dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
        for (i = 0; i < indices; i++) {
                snd_iprintf(buffer, " [");
@@ -757,12 +782,10 @@ static void print_codec_info(struct snd_info_entry *entry,
                            (codec->single_adc_amp &&
                             wid_type == AC_WID_AUD_IN))
                                print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              1);
+                                              wid_caps, 1);
                        else
                                print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              conn_len);
+                                              wid_caps, conn_len);
                }
                if (wid_caps & AC_WCAP_OUT_AMP) {
                        snd_iprintf(buffer, "  Amp-Out caps: ");
@@ -771,11 +794,10 @@ static void print_codec_info(struct snd_info_entry *entry,
                        if (wid_type == AC_WID_PIN &&
                            codec->pin_amp_workaround)
                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              conn_len);
+                                              wid_caps, conn_len);
                        else
                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                              wid_caps & AC_WCAP_STEREO, 1);
+                                              wid_caps, 1);
                }
 
                switch (wid_type) {
index b67480f1b1aa4a7dcfb6c03b10b2ecd826875989..4373ada95648e6890f013582b97c355b45e76dd1 100644 (file)
@@ -317,7 +317,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
-       unsigned int deemph = ucontrol->value.enumerated.item[0];
+       unsigned int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
@@ -333,7 +333,7 @@ static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = adav80x->deemph;
+       ucontrol->value.integer.value[0] = adav80x->deemph;
        return 0;
 };
 
index 70861c7b1631ab577acf506f8af18f2386a0852a..81b54a270bd8f800637108d027f9edfffb464d04 100644 (file)
@@ -76,7 +76,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
@@ -92,7 +92,7 @@ static int ak4641_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = ak4641->deemph;
+       ucontrol->value.integer.value[0] = ak4641->deemph;
        return 0;
 };
 
index 632e89f793a78d2691dfb2e33b3516f0f483aeee..2a58b1dccd2f18cb41221c45ac4d026e731240c9 100644 (file)
@@ -343,25 +343,25 @@ static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route ak4671_intercon[] = {
-       {"DAC Left", "NULL", "PMPLL"},
-       {"DAC Right", "NULL", "PMPLL"},
-       {"ADC Left", "NULL", "PMPLL"},
-       {"ADC Right", "NULL", "PMPLL"},
+       {"DAC Left", NULL, "PMPLL"},
+       {"DAC Right", NULL, "PMPLL"},
+       {"ADC Left", NULL, "PMPLL"},
+       {"ADC Right", NULL, "PMPLL"},
 
        /* Outputs */
-       {"LOUT1", "NULL", "LOUT1 Mixer"},
-       {"ROUT1", "NULL", "ROUT1 Mixer"},
-       {"LOUT2", "NULL", "LOUT2 Mix Amp"},
-       {"ROUT2", "NULL", "ROUT2 Mix Amp"},
-       {"LOUT3", "NULL", "LOUT3 Mixer"},
-       {"ROUT3", "NULL", "ROUT3 Mixer"},
+       {"LOUT1", NULL, "LOUT1 Mixer"},
+       {"ROUT1", NULL, "ROUT1 Mixer"},
+       {"LOUT2", NULL, "LOUT2 Mix Amp"},
+       {"ROUT2", NULL, "ROUT2 Mix Amp"},
+       {"LOUT3", NULL, "LOUT3 Mixer"},
+       {"ROUT3", NULL, "ROUT3 Mixer"},
 
        {"LOUT1 Mixer", "DACL", "DAC Left"},
        {"ROUT1 Mixer", "DACR", "DAC Right"},
        {"LOUT2 Mixer", "DACHL", "DAC Left"},
        {"ROUT2 Mixer", "DACHR", "DAC Right"},
-       {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"},
-       {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"},
+       {"LOUT2 Mix Amp", NULL, "LOUT2 Mixer"},
+       {"ROUT2 Mix Amp", NULL, "ROUT2 Mixer"},
        {"LOUT3 Mixer", "DACSL", "DAC Left"},
        {"ROUT3 Mixer", "DACSR", "DAC Right"},
 
@@ -381,18 +381,18 @@ static const struct snd_soc_dapm_route ak4671_intercon[] = {
        {"LIN2", NULL, "Mic Bias"},
        {"RIN2", NULL, "Mic Bias"},
 
-       {"ADC Left", "NULL", "LIN MUX"},
-       {"ADC Right", "NULL", "RIN MUX"},
+       {"ADC Left", NULL, "LIN MUX"},
+       {"ADC Right", NULL, "RIN MUX"},
 
        /* Analog Loops */
-       {"LIN1 Mixing Circuit", "NULL", "LIN1"},
-       {"RIN1 Mixing Circuit", "NULL", "RIN1"},
-       {"LIN2 Mixing Circuit", "NULL", "LIN2"},
-       {"RIN2 Mixing Circuit", "NULL", "RIN2"},
-       {"LIN3 Mixing Circuit", "NULL", "LIN3"},
-       {"RIN3 Mixing Circuit", "NULL", "RIN3"},
-       {"LIN4 Mixing Circuit", "NULL", "LIN4"},
-       {"RIN4 Mixing Circuit", "NULL", "RIN4"},
+       {"LIN1 Mixing Circuit", NULL, "LIN1"},
+       {"RIN1 Mixing Circuit", NULL, "RIN1"},
+       {"LIN2 Mixing Circuit", NULL, "LIN2"},
+       {"RIN2 Mixing Circuit", NULL, "RIN2"},
+       {"LIN3 Mixing Circuit", NULL, "LIN3"},
+       {"RIN3 Mixing Circuit", NULL, "RIN3"},
+       {"LIN4 Mixing Circuit", NULL, "LIN4"},
+       {"RIN4 Mixing Circuit", NULL, "RIN4"},
 
        {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"},
        {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"},
index 79a4efcb894c192c763c649083081e4c75fbece3..7d3a6accaf9a4a583dcacbb934e275092933c026 100644 (file)
@@ -286,7 +286,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = cs4271->deemph;
+       ucontrol->value.integer.value[0] = cs4271->deemph;
        return 0;
 }
 
@@ -296,7 +296,7 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
-       cs4271->deemph = ucontrol->value.enumerated.item[0];
+       cs4271->deemph = ucontrol->value.integer.value[0];
        return cs4271_set_deemph(codec);
 }
 
index ffe96175a8a5ac62ee4721c1f17a54c305d447c7..911c26c705fc8d226e819d469c669b72f989517a 100644 (file)
@@ -876,11 +876,11 @@ static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = {
 
 static const struct snd_soc_dapm_route da732x_dapm_routes[] = {
        /* Inputs */
-       {"AUX1L PGA", "NULL", "AUX1L"},
-       {"AUX1R PGA", "NULL", "AUX1R"},
+       {"AUX1L PGA", NULL, "AUX1L"},
+       {"AUX1R PGA", NULL, "AUX1R"},
        {"MIC1 PGA", NULL, "MIC1"},
-       {"MIC2 PGA", "NULL", "MIC2"},
-       {"MIC3 PGA", "NULL", "MIC3"},
+       {"MIC2 PGA", NULL, "MIC2"},
+       {"MIC3 PGA", NULL, "MIC3"},
 
        /* Capture Path */
        {"ADC1 Left MUX", "MIC1", "MIC1 PGA"},
index f27325155acef31e1f4a7fff4ea970b9405ca8a7..c5f35a07e8e48106335df49153acd81e104f7aa9 100644 (file)
@@ -120,7 +120,7 @@ static int es8328_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = es8328->deemph;
+       ucontrol->value.integer.value[0] = es8328->deemph;
        return 0;
 }
 
@@ -129,7 +129,7 @@ static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret;
 
        if (deemph > 1)
index a722a023c26280a3c89f7a198e95c818f0c2fe6a..477e13d309713e56a5a4416d054350185fea0007 100644 (file)
@@ -118,7 +118,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = priv->deemph;
+       ucontrol->value.integer.value[0] = priv->deemph;
 
        return 0;
 }
@@ -129,7 +129,7 @@ static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       priv->deemph = ucontrol->value.enumerated.item[0];
+       priv->deemph = ucontrol->value.integer.value[0];
 
        return pcm1681_set_deemph(codec);
 }
index f374840a5a7ce376272d8f7e3290f91c099cb19f..9b541e52da8c77da4134fdf8e0c551d35a2a402b 100644 (file)
@@ -1198,7 +1198,7 @@ static struct dmi_system_id dmi_dell_dino[] = {
                .ident = "Dell Dino",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                       DMI_MATCH(DMI_BOARD_NAME, "0144P8")
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343")
                }
        },
        { }
index e182e6569bbd138713ec0047de606136254d81c4..3593a1496056d2aa7648142c67bd7952d5b589f6 100644 (file)
@@ -1151,13 +1151,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
                /* Enable VDDC charge pump */
                ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
        } else if (vddio >= 3100 && vdda >= 3100) {
-               /*
-                * if vddio and vddd > 3.1v,
-                * charge pump should be clean before set ana_pwr
-                */
-               snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
-                               SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
-
+               ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP;
                /* VDDC use VDDIO rail */
                lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
                lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
index 47b257e4180965f38be5c393cab204945f444b7f..82095d6cd07036d0ad81bf63cdc9e41746c630c3 100644 (file)
@@ -538,8 +538,8 @@ static const struct snd_soc_dapm_route sn95031_audio_map[] = {
        /* speaker map */
        { "IHFOUTL", NULL, "Speaker Rail"},
        { "IHFOUTR", NULL, "Speaker Rail"},
-       { "IHFOUTL", "NULL", "Speaker Left Playback"},
-       { "IHFOUTR", "NULL", "Speaker Right Playback"},
+       { "IHFOUTL", NULL, "Speaker Left Playback"},
+       { "IHFOUTR", NULL, "Speaker Right Playback"},
        { "Speaker Left Playback", NULL, "Speaker Left Filter"},
        { "Speaker Right Playback", NULL, "Speaker Right Filter"},
        { "Speaker Left Filter", NULL, "IHFDAC Left"},
index 249ef5c4c762795bfb19f3545ce8398868f4dba3..32942bed34b1e9bb67227adddd5c662b92aa2a9b 100644 (file)
@@ -281,7 +281,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = priv->deemph;
+       ucontrol->value.integer.value[0] = priv->deemph;
 
        return 0;
 }
@@ -292,7 +292,7 @@ static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       priv->deemph = ucontrol->value.enumerated.item[0];
+       priv->deemph = ucontrol->value.integer.value[0];
 
        return tas5086_set_deemph(codec);
 }
index 8d9de49a50524bb4e88ebd62cb580e17239b07d6..21d5402e343fbcdd7a433931bc9a78d0edac45e9 100644 (file)
@@ -610,7 +610,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       ucontrol->value.enumerated.item[0] = wm2000->anc_active;
+       ucontrol->value.integer.value[0] = wm2000->anc_active;
 
        return 0;
 }
@@ -620,7 +620,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
-       int anc_active = ucontrol->value.enumerated.item[0];
+       int anc_active = ucontrol->value.integer.value[0];
        int ret;
 
        if (anc_active > 1)
@@ -643,7 +643,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
+       ucontrol->value.integer.value[0] = wm2000->spk_ena;
 
        return 0;
 }
@@ -653,7 +653,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
-       int val = ucontrol->value.enumerated.item[0];
+       int val = ucontrol->value.integer.value[0];
        int ret;
 
        if (val > 1)
index 098c143f44d653d99c33f36e02edde9eca6600d8..c6d10533e2bde5170f8ac963333b52c62782c27f 100644 (file)
@@ -125,7 +125,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8731->deemph;
+       ucontrol->value.integer.value[0] = wm8731->deemph;
 
        return 0;
 }
@@ -135,7 +135,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
 
        if (deemph > 1)
index dde462c082be0eb6124e0f881b9a1ed936e34c77..04b04f8e147c6bdeada6decdca981a026ce57afa 100644 (file)
@@ -442,7 +442,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8903->deemph;
+       ucontrol->value.integer.value[0] = wm8903->deemph;
 
        return 0;
 }
@@ -452,7 +452,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
 
        if (deemph > 1)
index d3b3f57668ccae412f0a75d61f91f9f34f1f0fb0..215e93c1ddf0358f42dc5581fd01b1d9a3d7e1e0 100644 (file)
@@ -525,7 +525,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       ucontrol->value.integer.value[0] = wm8904->deemph;
        return 0;
 }
 
@@ -534,7 +534,7 @@ static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index 1ab2d462afadfb24a7205638a779bb0152eb702a..00bec915d6522152a5d40dcc3d2df52ef16424eb 100644 (file)
@@ -393,7 +393,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       ucontrol->value.integer.value[0] = wm8955->deemph;
        return 0;
 }
 
@@ -402,7 +402,7 @@ static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index cf8fecf97f2c7ee06fff2741bea074bd32ceb7fc..3035d98564156746bc4e814f744e1ea0f236564a 100644 (file)
@@ -184,7 +184,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       ucontrol->value.integer.value[0] = wm8960->deemph;
        return 0;
 }
 
@@ -193,7 +193,7 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index 9517571e820d9576b9505be863a73f3c02116cb8..98c9525bd751fbacb0eec07f6465869cbc3e2aa5 100644 (file)
@@ -180,7 +180,7 @@ static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
        struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
-       unsigned int val = ucontrol->value.enumerated.item[0];
+       unsigned int val = ucontrol->value.integer.value[0];
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        unsigned int mixer, mask, shift, old;
@@ -193,7 +193,7 @@ static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol,
 
        mutex_lock(&wm9712->lock);
        old = wm9712->hp_mixer[mixer];
-       if (ucontrol->value.enumerated.item[0])
+       if (ucontrol->value.integer.value[0])
                wm9712->hp_mixer[mixer] |= mask;
        else
                wm9712->hp_mixer[mixer] &= ~mask;
@@ -231,7 +231,7 @@ static int wm9712_hp_mixer_get(struct snd_kcontrol *kcontrol,
        mixer = mc->shift >> 8;
        shift = mc->shift & 0xff;
 
-       ucontrol->value.enumerated.item[0] =
+       ucontrol->value.integer.value[0] =
                (wm9712->hp_mixer[mixer] >> shift) & 1;
 
        return 0;
index 68222917b396666b975cc2aa96e13d983bf52fc2..79552953e1bdc607e4d25c95aa5ab473637be6cc 100644 (file)
@@ -255,7 +255,7 @@ static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
        struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
-       unsigned int val = ucontrol->value.enumerated.item[0];
+       unsigned int val = ucontrol->value.integer.value[0];
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        unsigned int mixer, mask, shift, old;
@@ -268,7 +268,7 @@ static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol,
 
        mutex_lock(&wm9713->lock);
        old = wm9713->hp_mixer[mixer];
-       if (ucontrol->value.enumerated.item[0])
+       if (ucontrol->value.integer.value[0])
                wm9713->hp_mixer[mixer] |= mask;
        else
                wm9713->hp_mixer[mixer] &= ~mask;
@@ -306,7 +306,7 @@ static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol,
        mixer = mc->shift >> 8;
        shift = mc->shift & 0xff;
 
-       ucontrol->value.enumerated.item[0] =
+       ucontrol->value.integer.value[0] =
                (wm9713->hp_mixer[mixer] >> shift) & 1;
 
        return 0;
index b9fabbf69db6c9830ebf0de211f62735a24297b8..6b0c8f717ec2c0781af066cfb1bc3bcce8567791 100644 (file)
@@ -603,7 +603,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
        factor = (div2 + 1) * (7 * psr + 1) * 2;
 
        for (i = 0; i < 255; i++) {
-               tmprate = freq * factor * (i + 2);
+               tmprate = freq * factor * (i + 1);
 
                if (baudclk_is_used)
                        clkrate = clk_get_rate(ssi_private->baudclk);
@@ -1227,7 +1227,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
        ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0;
        ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0;
 
-       ret = !of_property_read_u32_array(np, "dmas", dmas, 4);
+       ret = of_property_read_u32_array(np, "dmas", dmas, 4);
        if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
                ssi_private->use_dual_fifo = true;
                /* When using dual fifo mode, we need to keep watermark
index c42ffae5fe9f6acab9ebe5723862c4e3a3b4bf8d..402b728c0a06479213425c2daf88eafe4caa2877 100644 (file)
@@ -207,9 +207,6 @@ static int hsw_parse_fw_image(struct sst_fw *sst_fw)
                module = (void *)module + sizeof(*module) + module->mod_size;
        }
 
-       /* allocate scratch mem regions */
-       sst_block_alloc_scratch(dsp);
-
        return 0;
 }
 
index 394af5684c05e37403b50b67ebaa7ead69d14f1f..863a9ca34b8e37fee393930812845e672e717b8f 100644 (file)
@@ -1732,6 +1732,7 @@ static void sst_hsw_drop_all(struct sst_hsw *hsw)
 int sst_hsw_dsp_load(struct sst_hsw *hsw)
 {
        struct sst_dsp *dsp = hsw->dsp;
+       struct sst_fw *sst_fw, *t;
        int ret;
 
        dev_dbg(hsw->dev, "loading audio DSP....");
@@ -1748,12 +1749,17 @@ int sst_hsw_dsp_load(struct sst_hsw *hsw)
                return ret;
        }
 
-       ret = sst_fw_reload(hsw->sst_fw);
-       if (ret < 0) {
-               dev_err(hsw->dev, "error: SST FW reload failed\n");
-               sst_dsp_dma_put_channel(dsp);
-               return -ENOMEM;
+       list_for_each_entry_safe_reverse(sst_fw, t, &dsp->fw_list, list) {
+               ret = sst_fw_reload(sst_fw);
+               if (ret < 0) {
+                       dev_err(hsw->dev, "error: SST FW reload failed\n");
+                       sst_dsp_dma_put_channel(dsp);
+                       return -ENOMEM;
+               }
        }
+       ret = sst_block_alloc_scratch(hsw->dsp);
+       if (ret < 0)
+               return -EINVAL;
 
        sst_dsp_dma_put_channel(dsp);
        return 0;
@@ -1809,12 +1815,17 @@ int sst_hsw_dsp_runtime_suspend(struct sst_hsw *hsw)
 
 int sst_hsw_dsp_runtime_sleep(struct sst_hsw *hsw)
 {
-       sst_fw_unload(hsw->sst_fw);
-       sst_block_free_scratch(hsw->dsp);
+       struct sst_fw *sst_fw, *t;
+       struct sst_dsp *dsp = hsw->dsp;
+
+       list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) {
+               sst_fw_unload(sst_fw);
+       }
+       sst_block_free_scratch(dsp);
 
        hsw->boot_complete = false;
 
-       sst_dsp_sleep(hsw->dsp);
+       sst_dsp_sleep(dsp);
 
        return 0;
 }
@@ -1943,6 +1954,11 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
                goto fw_err;
        }
 
+       /* allocate scratch mem regions */
+       ret = sst_block_alloc_scratch(hsw->dsp);
+       if (ret < 0)
+               goto boot_err;
+
        /* wait for DSP boot completion */
        sst_dsp_boot(hsw->dsp);
        ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,
index 30579ca5bacb985c7dfa9b9ad30f58cee45d6e1a..e5c990889dcc5e6d9a1ecca2682acf4384ab5ae5 100644 (file)
@@ -347,6 +347,8 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
+       mutex_lock(&client_mutex);
+
        list_for_each_entry(codec, &codec_list, list) {
                len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
                               codec->component.name);
@@ -358,6 +360,8 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
                }
        }
 
+       mutex_unlock(&client_mutex);
+
        if (ret >= 0)
                ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
 
@@ -382,6 +386,8 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
+       mutex_lock(&client_mutex);
+
        list_for_each_entry(component, &component_list, list) {
                list_for_each_entry(dai, &component->dai_list, list) {
                        len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
@@ -395,6 +401,8 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
                }
        }
 
+       mutex_unlock(&client_mutex);
+
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
 
        kfree(buf);
@@ -418,6 +426,8 @@ static ssize_t platform_list_read_file(struct file *file,
        if (!buf)
                return -ENOMEM;
 
+       mutex_lock(&client_mutex);
+
        list_for_each_entry(platform, &platform_list, list) {
                len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
                               platform->component.name);
@@ -429,6 +439,8 @@ static ssize_t platform_list_read_file(struct file *file,
                }
        }
 
+       mutex_unlock(&client_mutex);
+
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
 
        kfree(buf);
@@ -836,6 +848,8 @@ static struct snd_soc_component *soc_find_component(
 {
        struct snd_soc_component *component;
 
+       lockdep_assert_held(&client_mutex);
+
        list_for_each_entry(component, &component_list, list) {
                if (of_node) {
                        if (component->dev->of_node == of_node)
@@ -854,6 +868,8 @@ static struct snd_soc_dai *snd_soc_find_dai(
        struct snd_soc_component *component;
        struct snd_soc_dai *dai;
 
+       lockdep_assert_held(&client_mutex);
+
        /* Find CPU DAI from registered DAIs*/
        list_for_each_entry(component, &component_list, list) {
                if (dlc->of_node && component->dev->of_node != dlc->of_node)
@@ -1508,6 +1524,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        struct snd_soc_codec *codec;
        int ret, i, order;
 
+       mutex_lock(&client_mutex);
        mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
 
        /* bind DAIs */
@@ -1662,6 +1679,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        card->instantiated = 1;
        snd_soc_dapm_sync(&card->dapm);
        mutex_unlock(&card->mutex);
+       mutex_unlock(&client_mutex);
 
        return 0;
 
@@ -1680,6 +1698,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 
 base_error:
        mutex_unlock(&card->mutex);
+       mutex_unlock(&client_mutex);
 
        return ret;
 }
@@ -2713,13 +2732,6 @@ static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
        list_del(&component->list);
 }
 
-static void snd_soc_component_del(struct snd_soc_component *component)
-{
-       mutex_lock(&client_mutex);
-       snd_soc_component_del_unlocked(component);
-       mutex_unlock(&client_mutex);
-}
-
 int snd_soc_register_component(struct device *dev,
                               const struct snd_soc_component_driver *cmpnt_drv,
                               struct snd_soc_dai_driver *dai_drv,
@@ -2767,14 +2779,17 @@ void snd_soc_unregister_component(struct device *dev)
 {
        struct snd_soc_component *cmpnt;
 
+       mutex_lock(&client_mutex);
        list_for_each_entry(cmpnt, &component_list, list) {
                if (dev == cmpnt->dev && cmpnt->registered_as_component)
                        goto found;
        }
+       mutex_unlock(&client_mutex);
        return;
 
 found:
-       snd_soc_component_del(cmpnt);
+       snd_soc_component_del_unlocked(cmpnt);
+       mutex_unlock(&client_mutex);
        snd_soc_component_cleanup(cmpnt);
        kfree(cmpnt);
 }
@@ -2882,10 +2897,14 @@ struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev)
 {
        struct snd_soc_platform *platform;
 
+       mutex_lock(&client_mutex);
        list_for_each_entry(platform, &platform_list, list) {
-               if (dev == platform->dev)
+               if (dev == platform->dev) {
+                       mutex_unlock(&client_mutex);
                        return platform;
+               }
        }
+       mutex_unlock(&client_mutex);
 
        return NULL;
 }
@@ -3090,15 +3109,15 @@ void snd_soc_unregister_codec(struct device *dev)
 {
        struct snd_soc_codec *codec;
 
+       mutex_lock(&client_mutex);
        list_for_each_entry(codec, &codec_list, list) {
                if (dev == codec->dev)
                        goto found;
        }
+       mutex_unlock(&client_mutex);
        return;
 
 found:
-
-       mutex_lock(&client_mutex);
        list_del(&codec->list);
        snd_soc_component_del_unlocked(&codec->component);
        mutex_unlock(&client_mutex);
index 61bf9128e1f28ce40d3d694ef5d9de8bb9cda1f8..9d9db3b296dd6b50ed27e581c0d78aab65dfec49 100644 (file)
@@ -30,6 +30,8 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
 
 static void ins__delete(struct ins_operands *ops)
 {
+       if (ops == NULL)
+               return;
        zfree(&ops->source.raw);
        zfree(&ops->source.name);
        zfree(&ops->target.raw);
index a0a7b5d1a0703a00f81c9421856c0fdf1b1f6aaa..f9b9c7c5137214cb56bcc0cf7455d2d712dc6848 100644 (file)
@@ -72,6 +72,8 @@ static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
 {
        if (!(lr_desc.state & LR_STATE_MASK))
                vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr |= (1ULL << lr);
+       else
+               vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr &= ~(1ULL << lr);
 }
 
 static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu)
@@ -84,6 +86,11 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
        return vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr;
 }
 
+static void vgic_v2_clear_eisr(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr = 0;
+}
+
 static u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu)
 {
        u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr;
@@ -148,6 +155,7 @@ static const struct vgic_ops vgic_v2_ops = {
        .sync_lr_elrsr          = vgic_v2_sync_lr_elrsr,
        .get_elrsr              = vgic_v2_get_elrsr,
        .get_eisr               = vgic_v2_get_eisr,
+       .clear_eisr             = vgic_v2_clear_eisr,
        .get_interrupt_status   = vgic_v2_get_interrupt_status,
        .enable_underflow       = vgic_v2_enable_underflow,
        .disable_underflow      = vgic_v2_disable_underflow,
index 3a62d8a9a2c6fce0cc2f94a6e558115785c03811..dff06021e74855a2d6cb9b8830fd30818a63c927 100644 (file)
@@ -104,6 +104,8 @@ static void vgic_v3_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
 {
        if (!(lr_desc.state & LR_STATE_MASK))
                vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr);
+       else
+               vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr &= ~(1U << lr);
 }
 
 static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu)
@@ -116,6 +118,11 @@ static u64 vgic_v3_get_eisr(const struct kvm_vcpu *vcpu)
        return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr;
 }
 
+static void vgic_v3_clear_eisr(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr = 0;
+}
+
 static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu)
 {
        u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr;
@@ -192,6 +199,7 @@ static const struct vgic_ops vgic_v3_ops = {
        .sync_lr_elrsr          = vgic_v3_sync_lr_elrsr,
        .get_elrsr              = vgic_v3_get_elrsr,
        .get_eisr               = vgic_v3_get_eisr,
+       .clear_eisr             = vgic_v3_clear_eisr,
        .get_interrupt_status   = vgic_v3_get_interrupt_status,
        .enable_underflow       = vgic_v3_enable_underflow,
        .disable_underflow      = vgic_v3_disable_underflow,
index 0cc6ab6005a07bb2e9453106a672e9efd4e237a6..c9f60f52458802f4a66a3912732d8665bc4a3e32 100644 (file)
@@ -883,6 +883,11 @@ static inline u64 vgic_get_eisr(struct kvm_vcpu *vcpu)
        return vgic_ops->get_eisr(vcpu);
 }
 
+static inline void vgic_clear_eisr(struct kvm_vcpu *vcpu)
+{
+       vgic_ops->clear_eisr(vcpu);
+}
+
 static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu)
 {
        return vgic_ops->get_interrupt_status(vcpu);
@@ -922,6 +927,7 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
        vgic_set_lr(vcpu, lr_nr, vlr);
        clear_bit(lr_nr, vgic_cpu->lr_used);
        vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
+       vgic_sync_lr_elrsr(vcpu, lr_nr, vlr);
 }
 
 /*
@@ -978,6 +984,7 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
                        BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
                        vlr.state |= LR_STATE_PENDING;
                        vgic_set_lr(vcpu, lr, vlr);
+                       vgic_sync_lr_elrsr(vcpu, lr, vlr);
                        return true;
                }
        }
@@ -999,6 +1006,7 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
                vlr.state |= LR_EOI_INT;
 
        vgic_set_lr(vcpu, lr, vlr);
+       vgic_sync_lr_elrsr(vcpu, lr, vlr);
 
        return true;
 }
@@ -1136,6 +1144,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
        if (status & INT_STATUS_UNDERFLOW)
                vgic_disable_underflow(vcpu);
 
+       /*
+        * In the next iterations of the vcpu loop, if we sync the vgic state
+        * after flushing it, but before entering the guest (this happens for
+        * pending signals and vmid rollovers), then make sure we don't pick
+        * up any old maintenance interrupts here.
+        */
+       vgic_clear_eisr(vcpu);
+
        return level_pending;
 }
 
@@ -1583,8 +1599,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
         * emulation. So check this here again. KVM_CREATE_DEVICE does
         * the proper checks already.
         */
-       if (type == KVM_DEV_TYPE_ARM_VGIC_V2 && !vgic->can_emulate_gicv2)
-               return -ENODEV;
+       if (type == KVM_DEV_TYPE_ARM_VGIC_V2 && !vgic->can_emulate_gicv2) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        /*
         * Any time a vcpu is run, vcpu_load is called which tries to grab the
index a1093700f3a41b84fc71591a7465940fdd4a017f..cc6a25d95fbff532bf5b00b0c339bec91ddc5bcf 100644 (file)
@@ -471,7 +471,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
        BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);
 
        r = -ENOMEM;
-       kvm->memslots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+       kvm->memslots = kvm_kvzalloc(sizeof(struct kvm_memslots));
        if (!kvm->memslots)
                goto out_err_no_srcu;
 
@@ -522,7 +522,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
 out_err_no_disable:
        for (i = 0; i < KVM_NR_BUSES; i++)
                kfree(kvm->buses[i]);
-       kfree(kvm->memslots);
+       kvfree(kvm->memslots);
        kvm_arch_free_vm(kvm);
        return ERR_PTR(r);
 }
@@ -578,7 +578,7 @@ static void kvm_free_physmem(struct kvm *kvm)
        kvm_for_each_memslot(memslot, slots)
                kvm_free_physmem_slot(kvm, memslot, NULL);
 
-       kfree(kvm->memslots);
+       kvfree(kvm->memslots);
 }
 
 static void kvm_destroy_devices(struct kvm *kvm)
@@ -871,10 +871,10 @@ int __kvm_set_memory_region(struct kvm *kvm,
                        goto out_free;
        }
 
-       slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
-                       GFP_KERNEL);
+       slots = kvm_kvzalloc(sizeof(struct kvm_memslots));
        if (!slots)
                goto out_free;
+       memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
 
        if ((change == KVM_MR_DELETE) || (change == KVM_MR_MOVE)) {
                slot = id_to_memslot(slots, mem->slot);
@@ -917,7 +917,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
        kvm_arch_commit_memory_region(kvm, mem, &old, change);
 
        kvm_free_physmem_slot(kvm, &old, &new);
-       kfree(old_memslots);
+       kvfree(old_memslots);
 
        /*
         * IOMMU mapping:  New slots need to be mapped.  Old slots need to be
@@ -936,7 +936,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
        return 0;
 
 out_slots:
-       kfree(slots);
+       kvfree(slots);
 out_free:
        kvm_free_physmem_slot(kvm, &new, &old);
 out:
@@ -2492,6 +2492,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
        case KVM_CAP_SIGNAL_MSI:
 #endif
 #ifdef CONFIG_HAVE_KVM_IRQFD
+       case KVM_CAP_IRQFD:
        case KVM_CAP_IRQFD_RESAMPLE:
 #endif
        case KVM_CAP_CHECK_EXTENSION_VM: