Merge tag 'Intel-CVE-2019-14615' from bundle by Akeem Abodunrin.
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Jan 2020 02:40:57 +0000 (18:40 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Jan 2020 02:40:57 +0000 (18:40 -0800)
Merge Intel Gen9 graphics fix from Akeem Abodunrin:
 "Insufficient control flow in certain data structures for some Intel
  Processors with Intel Processor Graphics may allow an unauthenticated
  user to potentially enable information disclosure via local access

  This provides mitigation for Gen9 hardware. Note that Gen8 is not
  impacted due to a previously implemented workaround.

  The mitigation involves using an existing hardware feature to forcibly
  clear down all EU state at each context switch"

* tag 'Intel-CVE-2019-14615' of emailed bundle from Akeem G Abodunrin <akeem.g.abodunrin@intel.com>:
  drm/i915/gen9: Clear residual context state on context switch

245 files changed:
Documentation/devicetree/bindings/i2c/i2c-at91.txt
Documentation/devicetree/bindings/spi/spi-controller.yaml
Documentation/networking/ip-sysctl.txt
Documentation/networking/netdev-FAQ.rst
MAINTAINERS
Makefile
arch/arc/include/asm/entry-arcv2.h
arch/arc/include/asm/hugepage.h
arch/arc/kernel/asm-offsets.c
arch/arc/plat-eznps/Kconfig
arch/arm/Kconfig
arch/arm/kernel/process.c
arch/arm64/Kconfig
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/uapi/asm/unistd.h
arch/arm64/kernel/process.c
arch/arm64/mm/fault.c
arch/parisc/Kconfig
arch/parisc/kernel/process.c
arch/riscv/Kconfig
arch/riscv/include/asm/sifive_l2_cache.h [deleted file]
arch/riscv/kernel/head.S
arch/riscv/kernel/process.c
arch/um/Kconfig
arch/um/include/asm/ptrace-generic.h
arch/um/kernel/process.c
arch/x86/um/tls_32.c
arch/x86/um/tls_64.c
arch/xtensa/Kconfig
arch/xtensa/kernel/process.c
block/bio.c
drivers/atm/eni.c
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm-dev.h
drivers/char/tpm/tpm_tis_core.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/edac/sifive_edac.c
drivers/firmware/broadcom/tee_bnxt_fw.c
drivers/gpio/Kconfig
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib-acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring_submission.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
drivers/hid/hid-asus.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-ite.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/uhid.c
drivers/hid/usbhid/hiddev.c
drivers/hid/wacom_wac.c
drivers/i2c/busses/i2c-at91-core.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/i2c-core-base.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/hfi1/iowait.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/keyboard/imx_sc_key.c
drivers/input/misc/uinput.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/iommu.c
drivers/mtd/nand/onenand/omap2.c
drivers/mtd/nand/onenand/onenand_base.c
drivers/mtd/nand/onenand/samsung_mtd.c
drivers/mtd/nand/raw/cadence-nand-controller.c
drivers/mtd/nand/raw/stm32_fmc2_nand.c
drivers/mtd/sm_ftl.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/can/m_can/tcan4x5x.c
drivers/net/can/mscan/mscan.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global1.h
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/google/gve/gve_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
drivers/net/ethernet/mellanox/mlx5/core/en/health.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/gtp.c
drivers/net/macvlan.c
drivers/net/phy/phylink.c
drivers/net/usb/lan78xx.c
drivers/net/vxlan.c
drivers/net/wan/sdla.c
drivers/nvme/host/core.c
drivers/nvme/target/admin-cmd.c
drivers/phy/motorola/phy-cpcap-usb.c
drivers/phy/motorola/phy-mapphone-mdm6600.c
drivers/phy/qualcomm/phy-qcom-qmp.c
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
drivers/pinctrl/cirrus/Kconfig
drivers/pinctrl/meson/pinctrl-meson.c
drivers/powercap/intel_rapl_common.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/bd70528-regulator.c
drivers/rtc/rtc-mc146818-lib.c
drivers/rtc/rtc-mt6397.c
drivers/rtc/rtc-sun6i.c
drivers/soc/sifive/sifive_l2_cache.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-uniphier.c
drivers/spi/spi.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/vt6656/baseband.c
drivers/staging/vt6656/card.c
drivers/staging/vt6656/device.h
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/usbpipe.c
drivers/staging/vt6656/usbpipe.h
drivers/staging/vt6656/wcmd.c
drivers/thermal/qcom/tsens.c
drivers/tty/serdev/core.c
drivers/tty/tty_port.c
drivers/usb/cdns3/gadget.c
drivers/usb/chipidea/host.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/host/ohci-da8xx.c
drivers/usb/musb/jz4740.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musbhsdma.c
drivers/usb/serial/option.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/typec/tcpm/tcpci.c
drivers/usb/typec/ucsi/ucsi.h
drivers/watchdog/Kconfig
drivers/watchdog/imx7ulp_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/rn5t618_wdt.c
drivers/watchdog/w83627hf_wdt.c
fs/buffer.c
fs/char_dev.c
fs/internal.h
fs/io_uring.c
fs/mpage.c
fs/pstore/ram.c
fs/pstore/ram_core.c
include/linux/bvec.h
include/linux/can/dev.h
include/linux/if_ether.h
include/linux/mfd/mt6397/rtc.h
include/linux/mtd/flashchip.h
include/linux/spi/spi.h
include/linux/sxgbe_platform.h
include/net/netfilter/nf_flow_table.h
include/soc/sifive/sifive_l2_cache.h [new file with mode: 0644]
include/trace/events/preemptirq.h
include/uapi/linux/input.h
kernel/bpf/cgroup.c
kernel/bpf/verifier.c
kernel/fork.c
kernel/trace/fgraph.c
kernel/trace/ftrace.c
kernel/trace/trace_events_inject.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_seq.c
kernel/trace/trace_stack.c
mm/mmap.c
net/8021q/vlan.h
net/8021q/vlan_dev.c
net/8021q/vlan_netlink.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/tcp_input.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_flow_offload.c
net/qrtr/qrtr.c
net/sched/sch_cake.c
net/sched/sch_fq.c
net/sched/sch_prio.c
net/sctp/sm_sideeffect.c
net/tipc/Makefile
net/tipc/netlink_compat.c
net/tipc/socket.c
sound/hda/hdac_regmap.c
sound/pci/hda/patch_realtek.c
sound/soc/fsl/fsl_audmix.c
sound/soc/intel/boards/cml_rt1011_rt5682.c
sound/soc/soc-core.c
sound/soc/soc-topology.c
sound/soc/sof/imx/imx8.c
sound/soc/sof/intel/hda-dai.c
sound/soc/sof/ipc.c
sound/soc/stm/stm32_spdifrx.c
sound/usb/quirks.c
tools/testing/selftests/net/forwarding/loopback.sh

index 2210f43..8347b1e 100644 (file)
@@ -18,8 +18,10 @@ Optional properties:
 - dma-names: should contain "tx" and "rx".
 - atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
   capable I2C controllers.
-- i2c-sda-hold-time-ns: TWD hold time, only available for "atmel,sama5d4-i2c"
-  and "atmel,sama5d2-i2c".
+- i2c-sda-hold-time-ns: TWD hold time, only available for:
+       "atmel,sama5d4-i2c",
+       "atmel,sama5d2-i2c",
+       "microchip,sam9x60-i2c".
 - Child nodes conforming to i2c bus binding
 
 Examples :
index 7323392..1e0ca6c 100644 (file)
@@ -111,7 +111,7 @@ patternProperties:
       spi-rx-bus-width:
         allOf:
           - $ref: /schemas/types.yaml#/definitions/uint32
-          - enum: [ 1, 2, 4 ]
+          - enum: [ 1, 2, 4, 8 ]
           - default: 1
         description:
           Bus width to the SPI bus used for MISO.
@@ -123,7 +123,7 @@ patternProperties:
       spi-tx-bus-width:
         allOf:
           - $ref: /schemas/types.yaml#/definitions/uint32
-          - enum: [ 1, 2, 4 ]
+          - enum: [ 1, 2, 4, 8 ]
           - default: 1
         description:
           Bus width to the SPI bus used for MOSI.
index fd26788..48ccb1b 100644 (file)
@@ -603,7 +603,7 @@ tcp_synack_retries - INTEGER
        with the current initial RTO of 1second. With this the final timeout
        for a passive TCP connection will happen after 63seconds.
 
-tcp_syncookies - BOOLEAN
+tcp_syncookies - INTEGER
        Only valid when the kernel was compiled with CONFIG_SYN_COOKIES
        Send out syncookies when the syn backlog queue of a socket
        overflows. This is to prevent against the common 'SYN flood attack'
index 642fa96..d5c9320 100644 (file)
@@ -34,8 +34,8 @@ the names, the ``net`` tree is for fixes to existing code already in the
 mainline tree from Linus, and ``net-next`` is where the new code goes
 for the future release.  You can find the trees here:
 
-- https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-- https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 
 Q: How often do changes from these trees make it to the mainline Linus tree?
 ----------------------------------------------------------------------------
index 8982c6e..4017e6b 100644 (file)
@@ -11460,8 +11460,8 @@ M:      "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 S:     Odd Fixes
 F:     Documentation/devicetree/bindings/net/
 F:     drivers/net/
@@ -11502,8 +11502,8 @@ M:      "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 B:     mailto:netdev@vger.kernel.org
 S:     Maintained
 F:     net/
@@ -11548,7 +11548,7 @@ M:      "David S. Miller" <davem@davemloft.net>
 M:     Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
 M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
 L:     netdev@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 S:     Maintained
 F:     net/ipv4/
 F:     net/ipv6/
@@ -13679,7 +13679,6 @@ F:      drivers/net/ethernet/qualcomm/emac/
 
 QUALCOMM ETHQOS ETHERNET DRIVER
 M:     Vinod Koul <vkoul@kernel.org>
-M:     Niklas Cassel <niklas.cassel@linaro.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -14549,8 +14548,6 @@ F:      include/linux/platform_data/spi-s3c64xx.h
 
 SAMSUNG SXGBE DRIVERS
 M:     Byungho An <bh74.an@samsung.com>
-M:     Girish K S <ks.giri@samsung.com>
-M:     Vipul Pandya <vipul.pandya@samsung.com>
 S:     Supported
 L:     netdev@vger.kernel.org
 F:     drivers/net/ethernet/samsung/sxgbe/
index e4c2d03..0a7c37d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
index 41b16f2..0b8b63d 100644 (file)
 #endif
 
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
-       ST2     r58, r59, PT_sp + 12
+       ST2     r58, r59, PT_r58
 #endif
 
 .endm
 
        LD2     gp, fp, PT_r26          ; gp (r26), fp (r27)
 
-       ld      r12, [sp, PT_sp + 4]
-       ld      r30, [sp, PT_sp + 8]
+       ld      r12, [sp, PT_r12]
+       ld      r30, [sp, PT_r30]
 
        ; Restore SP (into AUX_USER_SP) only if returning to U mode
        ;  - for K mode, it will be implicitly restored as stack is unwound
 #endif
 
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
-       LD2     r58, r59, PT_sp + 12
+       LD2     r58, r59, PT_r58
 #endif
 .endm
 
index 9a74ce7..30ac40f 100644 (file)
@@ -8,7 +8,6 @@
 #define _ASM_ARC_HUGEPAGE_H
 
 #include <linux/types.h>
-#define __ARCH_USE_5LEVEL_HACK
 #include <asm-generic/pgtable-nopmd.h>
 
 static inline pte_t pmd_pte(pmd_t pmd)
index 1f621e4..c783bcd 100644 (file)
@@ -66,7 +66,15 @@ int main(void)
 
        DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
        DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
-       DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25));
+
+#ifdef CONFIG_ISA_ARCV2
+       OFFSET(PT_r12, pt_regs, r12);
+       OFFSET(PT_r30, pt_regs, r30);
+#endif
+#ifdef CONFIG_ARC_HAS_ACCL_REGS
+       OFFSET(PT_r58, pt_regs, r58);
+       OFFSET(PT_r59, pt_regs, r59);
+#endif
 
        return 0;
 }
index a376a50..a931d0a 100644 (file)
@@ -7,7 +7,7 @@
 menuconfig ARC_PLAT_EZNPS
        bool "\"EZchip\" ARC dev platform"
        select CPU_BIG_ENDIAN
-       select CLKSRC_NPS
+       select CLKSRC_NPS if !PHYS_ADDR_T_64BIT
        select EZNPS_GIC
        select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
        help
index ba75e36..96dab76 100644 (file)
@@ -72,6 +72,7 @@ config ARM
        select HAVE_ARM_SMCCC if CPU_V7
        select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
        select HAVE_CONTEXT_TRACKING
+       select HAVE_COPY_THREAD_TLS
        select HAVE_C_RECORDMCOUNT
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS if MMU
index cea1c27..46e478f 100644 (file)
@@ -226,8 +226,8 @@ void release_thread(struct task_struct *dead_task)
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int
-copy_thread(unsigned long clone_flags, unsigned long stack_start,
-           unsigned long stk_sz, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+           unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
@@ -261,7 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        clear_ptrace_hw_breakpoint(p);
 
        if (clone_flags & CLONE_SETTLS)
-               thread->tp_value[0] = childregs->ARM_r3;
+               thread->tp_value[0] = tls;
        thread->tp_value[1] = get_tpuser();
 
        thread_notify(THREAD_NOTIFY_COPY, thread);
index b1b4476..e688dfa 100644 (file)
@@ -138,6 +138,7 @@ config ARM64
        select HAVE_CMPXCHG_DOUBLE
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CONTEXT_TRACKING
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS
index 8dc6c5c..baf52ba 100644 (file)
 #define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE)
 #define PAGE_READONLY          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_READONLY_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN)
-#define PAGE_EXECONLY          __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN)
 
 #define __P000  PAGE_NONE
 #define __P001  PAGE_READONLY
 #define __P010  PAGE_READONLY
 #define __P011  PAGE_READONLY
-#define __P100  PAGE_EXECONLY
+#define __P100  PAGE_READONLY_EXEC
 #define __P101  PAGE_READONLY_EXEC
 #define __P110  PAGE_READONLY_EXEC
 #define __P111  PAGE_READONLY_EXEC
 #define __S001  PAGE_READONLY
 #define __S010  PAGE_SHARED
 #define __S011  PAGE_SHARED
-#define __S100  PAGE_EXECONLY
+#define __S100  PAGE_READONLY_EXEC
 #define __S101  PAGE_READONLY_EXEC
 #define __S110  PAGE_SHARED_EXEC
 #define __S111  PAGE_SHARED_EXEC
index 5d15b47..cd5de0e 100644 (file)
@@ -96,12 +96,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define pte_dirty(pte)         (pte_sw_dirty(pte) || pte_hw_dirty(pte))
 
 #define pte_valid(pte)         (!!(pte_val(pte) & PTE_VALID))
-/*
- * Execute-only user mappings do not have the PTE_USER bit set. All valid
- * kernel mappings have the PTE_UXN bit set.
- */
 #define pte_valid_not_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN))
+       ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
 #define pte_valid_young(pte) \
        ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
 #define pte_valid_user(pte) \
@@ -117,8 +113,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 /*
  * p??_access_permitted() is true for valid user mappings (subject to the
- * write permission check) other than user execute-only which do not have the
- * PTE_USER bit set. PROT_NONE mappings do not have the PTE_VALID bit set.
+ * write permission check). PROT_NONE mappings do not have the PTE_VALID bit
+ * set.
  */
 #define pte_access_permitted(pte, write) \
        (pte_valid_user(pte) && (!(write) || pte_write(pte)))
index 2629a68..5af8258 100644 (file)
@@ -42,7 +42,6 @@
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
 
 #ifndef __COMPAT_SYSCALL_NR
 #include <uapi/asm/unistd.h>
index 4703d21..f83a70e 100644 (file)
@@ -19,5 +19,6 @@
 #define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
+#define __ARCH_WANT_SYS_CLONE3
 
 #include <asm-generic/unistd.h>
index 71f788c..d54586d 100644 (file)
@@ -360,8 +360,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
 asmlinkage void ret_from_fork(void) asm("ret_from_fork");
 
-int copy_thread(unsigned long clone_flags, unsigned long stack_start,
-               unsigned long stk_sz, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+               unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -394,11 +394,11 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
                }
 
                /*
-                * If a TLS pointer was passed to clone (4th argument), use it
-                * for the new thread.
+                * If a TLS pointer was passed to clone, use it for the new
+                * thread.
                 */
                if (clone_flags & CLONE_SETTLS)
-                       p->thread.uw.tp_value = childregs->regs[3];
+                       p->thread.uw.tp_value = tls;
        } else {
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->pstate = PSR_MODE_EL1h;
index 077b02a..85566d3 100644 (file)
@@ -445,7 +445,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
        const struct fault_info *inf;
        struct mm_struct *mm = current->mm;
        vm_fault_t fault, major = 0;
-       unsigned long vm_flags = VM_READ | VM_WRITE;
+       unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
        unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
        if (kprobe_page_fault(regs, esr))
index b16237c..0c29d6c 100644 (file)
@@ -62,6 +62,7 @@ config PARISC
        select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
        select HAVE_KPROBES_ON_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
+       select HAVE_COPY_THREAD_TLS
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index ecc5c27..230a642 100644 (file)
@@ -208,8 +208,8 @@ arch_initcall(parisc_idle_init);
  * Copy architecture-specific thread state
  */
 int
-copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long kthread_arg, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+           unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *cregs = &(p->thread.regs);
        void *stack = task_stack_page(p);
@@ -254,9 +254,9 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
                cregs->kpc = (unsigned long) &child_return;
 
-               /* Setup thread TLS area from the 4th parameter in clone */
+               /* Setup thread TLS area */
                if (clone_flags & CLONE_SETTLS)
-                       cregs->cr27 = cregs->gr[23];
+                       cregs->cr27 = tls;
        }
 
        return 0;
index a31169b..fa7dc03 100644 (file)
@@ -65,6 +65,7 @@ config RISCV
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select HAVE_ARCH_MMAP_RND_BITS if MMU
        select ARCH_HAS_GCOV_PROFILE_ALL
+       select HAVE_COPY_THREAD_TLS
 
 config ARCH_MMAP_RND_BITS_MIN
        default 18 if 64BIT
diff --git a/arch/riscv/include/asm/sifive_l2_cache.h b/arch/riscv/include/asm/sifive_l2_cache.h
deleted file mode 100644 (file)
index 04f6748..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * SiFive L2 Cache Controller header file
- *
- */
-
-#ifndef _ASM_RISCV_SIFIVE_L2_CACHE_H
-#define _ASM_RISCV_SIFIVE_L2_CACHE_H
-
-extern int register_sifive_l2_error_notifier(struct notifier_block *nb);
-extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
-
-#define SIFIVE_L2_ERR_TYPE_CE 0
-#define SIFIVE_L2_ERR_TYPE_UE 1
-
-#endif /* _ASM_RISCV_SIFIVE_L2_CACHE_H */
index 797802c..2227db6 100644 (file)
@@ -251,7 +251,7 @@ ENTRY(reset_regs)
 #ifdef CONFIG_FPU
        csrr    t0, CSR_MISA
        andi    t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
-       bnez    t0, .Lreset_regs_done
+       beqz    t0, .Lreset_regs_done
 
        li      t1, SR_FS
        csrs    CSR_STATUS, t1
index 95a3031..817cf7b 100644 (file)
@@ -99,8 +99,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
        return 0;
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-       unsigned long arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+       unsigned long arg, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -121,7 +121,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                if (usp) /* User fork */
                        childregs->sp = usp;
                if (clone_flags & CLONE_SETTLS)
-                       childregs->tp = childregs->a5;
+                       childregs->tp = tls;
                childregs->a0 = 0; /* Return value of fork() */
                p->thread.ra = (unsigned long)ret_from_fork;
        }
index 2a6d04f..6f0edd0 100644 (file)
@@ -14,6 +14,7 @@ config UML
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DEBUG_BUGVERBOSE
+       select HAVE_COPY_THREAD_TLS
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
index 81c647e..adf91ef 100644 (file)
@@ -36,7 +36,7 @@ extern long subarch_ptrace(struct task_struct *child, long request,
 extern unsigned long getreg(struct task_struct *child, int regno);
 extern int putreg(struct task_struct *child, int regno, unsigned long value);
 
-extern int arch_copy_tls(struct task_struct *new);
+extern int arch_set_tls(struct task_struct *new, unsigned long tls);
 extern void clear_flushed_tls(struct task_struct *task);
 extern int syscall_trace_enter(struct pt_regs *regs);
 extern void syscall_trace_leave(struct pt_regs *regs);
index 263a8f0..17045e7 100644 (file)
@@ -153,8 +153,8 @@ void fork_handler(void)
        userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long arg, struct task_struct * p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
+               unsigned long arg, struct task_struct * p, unsigned long tls)
 {
        void (*handler)(void);
        int kthread = current->flags & PF_KTHREAD;
@@ -188,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                 * Set a new TLS for the child thread?
                 */
                if (clone_flags & CLONE_SETTLS)
-                       ret = arch_copy_tls(p);
+                       ret = arch_set_tls(p, tls);
        }
 
        return ret;
index 5bd949d..ac8eee0 100644 (file)
@@ -215,14 +215,12 @@ static int set_tls_entry(struct task_struct* task, struct user_desc *info,
        return 0;
 }
 
-int arch_copy_tls(struct task_struct *new)
+int arch_set_tls(struct task_struct *new, unsigned long tls)
 {
        struct user_desc info;
        int idx, ret = -EFAULT;
 
-       if (copy_from_user(&info,
-                          (void __user *) UPT_SI(&new->thread.regs.regs),
-                          sizeof(info)))
+       if (copy_from_user(&info, (void __user *) tls, sizeof(info)))
                goto out;
 
        ret = -EINVAL;
index 3a621e0..ebd3855 100644 (file)
@@ -6,14 +6,13 @@ void clear_flushed_tls(struct task_struct *task)
 {
 }
 
-int arch_copy_tls(struct task_struct *t)
+int arch_set_tls(struct task_struct *t, unsigned long tls)
 {
        /*
         * If CLONE_SETTLS is set, we need to save the thread id
-        * (which is argument 5, child_tid, of clone) so it can be set
-        * during context switches.
+        * so it can be set during context switches.
         */
-       t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+       t->thread.arch.fs = tls;
 
        return 0;
 }
index 4a3fa29..296c532 100644 (file)
@@ -24,6 +24,7 @@ config XTENSA
        select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
        select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS
        select HAVE_EXIT_THREAD
index 9e1c491..3edecc4 100644 (file)
@@ -202,8 +202,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
-               unsigned long thread_fn_arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg, struct task_struct *p,
+               unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -266,9 +267,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
 
                childregs->syscall = regs->syscall;
 
-               /* The thread pointer is passed in the '4th argument' (= a5) */
                if (clone_flags & CLONE_SETTLS)
-                       childregs->threadptr = childregs->areg[5];
+                       childregs->threadptr = tls;
        } else {
                p->thread.ra = MAKE_RA_FOR_CALL(
                                (unsigned long)ret_from_kernel_thread, 1);
index 006bcc5..94d6972 100644 (file)
@@ -538,6 +538,16 @@ void zero_fill_bio_iter(struct bio *bio, struct bvec_iter start)
 }
 EXPORT_SYMBOL(zero_fill_bio_iter);
 
+/**
+ * bio_truncate - truncate the bio to small size of @new_size
+ * @bio:       the bio to be truncated
+ * @new_size:  new size for truncating the bio
+ *
+ * Description:
+ *   Truncate the bio to new size of @new_size. If bio_op(bio) is
+ *   REQ_OP_READ, zero the truncated part. This function should only
+ *   be used for handling corner cases, such as bio eod.
+ */
 void bio_truncate(struct bio *bio, unsigned new_size)
 {
        struct bio_vec bv;
@@ -548,7 +558,7 @@ void bio_truncate(struct bio *bio, unsigned new_size)
        if (new_size >= bio->bi_iter.bi_size)
                return;
 
-       if (bio_data_dir(bio) != READ)
+       if (bio_op(bio) != REQ_OP_READ)
                goto exit;
 
        bio_for_each_segment(bv, bio, iter) {
index b23d1e4..9d0d65e 100644 (file)
@@ -374,7 +374,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
                here = (eni_vcc->descr+skip) & (eni_vcc->words-1);
                dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci
                    << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-               j++;
+               dma[j++] = 0;
        }
        here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1);
        if (!eff) size += skip;
@@ -447,7 +447,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
        if (size != eff) {
                dma[j++] = (here << MID_DMA_COUNT_SHIFT) |
                    (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-               j++;
+               dma[j++] = 0;
        }
        if (!j || j > 2*RX_DMA_BUF) {
                printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n");
index b23b0b9..87f4493 100644 (file)
@@ -130,7 +130,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
                priv->response_read = true;
 
                ret_size = min_t(ssize_t, size, priv->response_length);
-               if (!ret_size) {
+               if (ret_size <= 0) {
                        priv->response_length = 0;
                        goto out;
                }
index 1089fc0..f3742bc 100644 (file)
@@ -14,7 +14,7 @@ struct file_priv {
        struct work_struct timeout_work;
        struct work_struct async_work;
        wait_queue_head_t async_wait;
-       size_t response_length;
+       ssize_t response_length;
        bool response_read;
        bool command_enqueued;
 
index bb0343f..27c6ca0 100644 (file)
@@ -978,13 +978,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
 
        if (wait_startup(chip, 0) != 0) {
                rc = -ENODEV;
-               goto err_start;
+               goto out_err;
        }
 
        /* Take control of the TPM's interrupt hardware and shut it off */
        rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
        if (rc < 0)
-               goto err_start;
+               goto out_err;
 
        intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
                   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
@@ -993,21 +993,21 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
 
        rc = tpm_chip_start(chip);
        if (rc)
-               goto err_start;
-
+               goto out_err;
        rc = tpm2_probe(chip);
+       tpm_chip_stop(chip);
        if (rc)
-               goto err_probe;
+               goto out_err;
 
        rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
        if (rc < 0)
-               goto err_probe;
+               goto out_err;
 
        priv->manufacturer_id = vendor;
 
        rc = tpm_tis_read8(priv, TPM_RID(0), &rid);
        if (rc < 0)
-               goto err_probe;
+               goto out_err;
 
        dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
                 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
@@ -1016,13 +1016,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
        probe = probe_itpm(chip);
        if (probe < 0) {
                rc = -ENODEV;
-               goto err_probe;
+               goto out_err;
        }
 
        /* Figure out the capabilities */
        rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
        if (rc < 0)
-               goto err_probe;
+               goto out_err;
 
        dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
                intfcaps);
@@ -1056,10 +1056,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                if (tpm_get_timeouts(chip)) {
                        dev_err(dev, "Could not get TPM timeouts and durations\n");
                        rc = -ENODEV;
-                       goto err_probe;
+                       goto out_err;
                }
 
-               chip->flags |= TPM_CHIP_FLAG_IRQ;
                if (irq) {
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
                                                 irq);
@@ -1071,18 +1070,15 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                }
        }
 
-       tpm_chip_stop(chip);
-
        rc = tpm_chip_register(chip);
        if (rc)
-               goto err_start;
-
-       return 0;
+               goto out_err;
 
-err_probe:
-       tpm_chip_stop(chip);
+       if (chip->ops->clk_enable != NULL)
+               chip->ops->clk_enable(chip, false);
 
-err_start:
+       return 0;
+out_err:
        if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
                chip->ops->clk_enable(chip, false);
 
index f1d170d..aba591d 100644 (file)
@@ -121,6 +121,8 @@ static const struct of_device_id blacklist[] __initconst = {
        { .compatible = "mediatek,mt8176", },
        { .compatible = "mediatek,mt8183", },
 
+       { .compatible = "nvidia,tegra20", },
+       { .compatible = "nvidia,tegra30", },
        { .compatible = "nvidia,tegra124", },
        { .compatible = "nvidia,tegra210", },
 
index 413cdb4..c0cc72a 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/edac.h>
 #include <linux/platform_device.h>
 #include "edac_module.h"
-#include <asm/sifive_l2_cache.h>
+#include <soc/sifive/sifive_l2_cache.h>
 
 #define DRVNAME "sifive_edac"
 
index 5b7ef89..ed10da5 100644 (file)
@@ -215,7 +215,6 @@ static int tee_bnxt_fw_probe(struct device *dev)
        fw_shm_pool = tee_shm_alloc(pvt_data.ctx, MAX_SHM_MEM_SZ,
                                    TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
        if (IS_ERR(fw_shm_pool)) {
-               tee_client_close_context(pvt_data.ctx);
                dev_err(pvt_data.dev, "tee_shm_alloc failed\n");
                err = PTR_ERR(fw_shm_pool);
                goto out_sess;
index 6ab25fe..2ed5992 100644 (file)
@@ -1148,6 +1148,7 @@ config GPIO_MADERA
 config GPIO_MAX77620
        tristate "GPIO support for PMIC MAX77620 and MAX20024"
        depends on MFD_MAX77620
+       select GPIOLIB_IRQCHIP
        help
          GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor.
          MAX77620 PMIC has 8 pins that can be configured as GPIOs. The
index c4fdc19..94b8d3a 100644 (file)
@@ -156,7 +156,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
        mutex_lock(&chip->lock);
 
        if (test_bit(FLAG_REQUESTED, &desc->flags) &&
-               !test_bit(FLAG_IS_OUT, &desc->flags)) {
+           !test_bit(FLAG_IS_OUT, &desc->flags)) {
                curr = __gpio_mockup_get(chip, offset);
                if (curr == value)
                        goto out;
@@ -165,7 +165,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
                irq_type = irq_get_trigger_type(irq);
 
                if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
-                       (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
+                   (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
                        irq_sim_fire(sim, offset);
        }
 
index 4c3f637..05ba16f 100644 (file)
@@ -684,6 +684,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
        unsigned int bank_num;
 
        for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
+               writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
+                               ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
                writel_relaxed(gpio->context.datalsw[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
@@ -693,9 +695,6 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
                writel_relaxed(gpio->context.dirm[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_DIRM_OFFSET(bank_num));
-               writel_relaxed(gpio->context.int_en[bank_num],
-                              gpio->base_addr +
-                              ZYNQ_GPIO_INTEN_OFFSET(bank_num));
                writel_relaxed(gpio->context.int_type[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
@@ -705,6 +704,9 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
                writel_relaxed(gpio->context.int_any[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+               writel_relaxed(~(gpio->context.int_en[bank_num]),
+                              gpio->base_addr +
+                              ZYNQ_GPIO_INTEN_OFFSET(bank_num));
        }
 }
 
index d30e57d..31fee5e 100644 (file)
 #include "gpiolib.h"
 #include "gpiolib-acpi.h"
 
+#define QUIRK_NO_EDGE_EVENTS_ON_BOOT           0x01l
+#define QUIRK_NO_WAKEUP                                0x02l
+
 static int run_edge_events_on_boot = -1;
 module_param(run_edge_events_on_boot, int, 0444);
 MODULE_PARM_DESC(run_edge_events_on_boot,
                 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
 
+static int honor_wakeup = -1;
+module_param(honor_wakeup, int, 0444);
+MODULE_PARM_DESC(honor_wakeup,
+                "Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto");
+
 /**
  * struct acpi_gpio_event - ACPI GPIO event handler data
  *
@@ -281,7 +289,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
        event->handle = evt_handle;
        event->handler = handler;
        event->irq = irq;
-       event->irq_is_wake = agpio->wake_capable == ACPI_WAKE_CAPABLE;
+       event->irq_is_wake = honor_wakeup && agpio->wake_capable == ACPI_WAKE_CAPABLE;
        event->pin = pin;
        event->desc = desc;
 
@@ -1309,7 +1317,7 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
 /* We must use _sync so that this runs after the first deferred_probe run */
 late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
 
-static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+static const struct dmi_system_id gpiolib_acpi_quirks[] = {
        {
                /*
                 * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
@@ -1319,7 +1327,8 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
-               }
+               },
+               .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
        },
        {
                /*
@@ -1331,20 +1340,52 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
-               }
+               },
+               .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
+       },
+       {
+               /*
+                * Various HP X2 10 Cherry Trail models use an external
+                * embedded-controller connected via I2C + an ACPI GPIO
+                * event handler. The embedded controller generates various
+                * spurious wakeup events when suspended. So disable wakeup
+                * for its handler (it uses the only ACPI GPIO event handler).
+                * This breaks wakeup when opening the lid, the user needs
+                * to press the power-button to wakeup the system. The
+                * alternative is suspend simply not working, which is worse.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
+               },
+               .driver_data = (void *)QUIRK_NO_WAKEUP,
        },
        {} /* Terminating entry */
 };
 
 static int acpi_gpio_setup_params(void)
 {
+       const struct dmi_system_id *id;
+       long quirks = 0;
+
+       id = dmi_first_match(gpiolib_acpi_quirks);
+       if (id)
+               quirks = (long)id->driver_data;
+
        if (run_edge_events_on_boot < 0) {
-               if (dmi_check_system(run_edge_events_on_boot_blacklist))
+               if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT)
                        run_edge_events_on_boot = 0;
                else
                        run_edge_events_on_boot = 1;
        }
 
+       if (honor_wakeup < 0) {
+               if (quirks & QUIRK_NO_WAKEUP)
+                       honor_wakeup = 0;
+               else
+                       honor_wakeup = 1;
+       }
+
        return 0;
 }
 
index 0ffc944..01a793a 100644 (file)
@@ -142,7 +142,7 @@ int amdgpu_async_gfx_ring = 1;
 int amdgpu_mcbp = 0;
 int amdgpu_discovery = -1;
 int amdgpu_mes = 0;
-int amdgpu_noretry = 1;
+int amdgpu_noretry;
 int amdgpu_force_asic_type = -1;
 
 struct amdgpu_mgpu_info mgpu_info = {
@@ -588,7 +588,7 @@ MODULE_PARM_DESC(mes,
 module_param_named(mes, amdgpu_mes, int, 0444);
 
 MODULE_PARM_DESC(noretry,
-       "Disable retry faults (0 = retry enabled, 1 = retry disabled (default))");
+       "Disable retry faults (0 = retry enabled (default), 1 = retry disabled)");
 module_param_named(noretry, amdgpu_noretry, int, 0644);
 
 /**
@@ -1359,7 +1359,8 @@ static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_ATOMIC |
            DRIVER_GEM |
-           DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
+           DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
+           DRIVER_SYNCOBJ_TIMELINE,
        .load = amdgpu_driver_load_kms,
        .open = amdgpu_driver_open_kms,
        .postclose = amdgpu_driver_postclose_kms,
index 7aac956..803e59d 100644 (file)
@@ -3356,27 +3356,21 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
        return color_space;
 }
 
-static void reduce_mode_colour_depth(struct dc_crtc_timing *timing_out)
-{
-       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-               return;
-
-       timing_out->display_color_depth--;
-}
-
-static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,
-                                               const struct drm_display_info *info)
+static bool adjust_colour_depth_from_display_info(
+       struct dc_crtc_timing *timing_out,
+       const struct drm_display_info *info)
 {
+       enum dc_color_depth depth = timing_out->display_color_depth;
        int normalized_clk;
-       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-               return;
        do {
                normalized_clk = timing_out->pix_clk_100hz / 10;
                /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
                if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
                        normalized_clk /= 2;
                /* Adjusting pix clock following on HDMI spec based on colour depth */
-               switch (timing_out->display_color_depth) {
+               switch (depth) {
+               case COLOR_DEPTH_888:
+                       break;
                case COLOR_DEPTH_101010:
                        normalized_clk = (normalized_clk * 30) / 24;
                        break;
@@ -3387,14 +3381,15 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
                        normalized_clk = (normalized_clk * 48) / 24;
                        break;
                default:
-                       return;
+                       /* The above depths are the only ones valid for HDMI. */
+                       return false;
                }
-               if (normalized_clk <= info->max_tmds_clock)
-                       return;
-               reduce_mode_colour_depth(timing_out);
-
-       } while (timing_out->display_color_depth > COLOR_DEPTH_888);
-
+               if (normalized_clk <= info->max_tmds_clock) {
+                       timing_out->display_color_depth = depth;
+                       return true;
+               }
+       } while (--depth > COLOR_DEPTH_666);
+       return false;
 }
 
 static void fill_stream_properties_from_drm_display_mode(
@@ -3474,8 +3469,14 @@ static void fill_stream_properties_from_drm_display_mode(
 
        stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
        stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
-       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-               adjust_colour_depth_from_display_info(timing_out, info);
+       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+               if (!adjust_colour_depth_from_display_info(timing_out, info) &&
+                   drm_mode_is_420_also(info, mode_in) &&
+                   timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) {
+                       timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+                       adjust_colour_depth_from_display_info(timing_out, info);
+               }
+       }
 }
 
 static void fill_audio_info(struct audio_info *audio_info,
index 273dd80..644c72f 100644 (file)
@@ -393,7 +393,7 @@ drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
                        memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes);
                        idx += req->u.i2c_read.transactions[i].num_bytes;
 
-                       buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5;
+                       buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 4;
                        buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf);
                        idx++;
                }
index 8ebeccd..d8e8f39 100644 (file)
@@ -1283,7 +1283,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
         * Changes struct fb_var_screeninfo are currently not pushed back
         * to KMS, hence fail if different settings are requested.
         */
-       if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
+       if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
            var->xres > fb->width || var->yres > fb->height ||
            var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
                DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
@@ -1308,6 +1308,11 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
        }
 
+       /*
+        * Likewise, bits_per_pixel should be rounded up to a supported value.
+        */
+       var->bits_per_pixel = fb->format->cpp[0] * 8;
+
        /*
         * drm fbdev emulation doesn't support changing the pixel format at all,
         * so reject all pixel format changing requests.
index 85e6b2b..3a5ac13 100644 (file)
@@ -856,7 +856,7 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
                }
 
                /* Force CDCLK to 2*BCLK as long as we need audio powered. */
-               if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (IS_GEMINILAKE(dev_priv))
                        glk_force_audio_cdclk(dev_priv, true);
 
                if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
@@ -875,7 +875,7 @@ static void i915_audio_component_put_power(struct device *kdev,
 
        /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
        if (--dev_priv->audio_power_refcount == 0)
-               if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (IS_GEMINILAKE(dev_priv))
                        glk_force_audio_cdclk(dev_priv, false);
 
        intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO, cookie);
index effc425..3018977 100644 (file)
@@ -4515,8 +4515,6 @@ static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_
 {
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       i915_reg_t reg;
-       u32 trans_ddi_func_ctl2_val;
 
        if (old_crtc_state->master_transcoder == INVALID_TRANSCODER)
                return;
@@ -4524,10 +4522,7 @@ static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_
        DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n",
                      transcoder_name(old_crtc_state->cpu_transcoder));
 
-       reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder);
-       trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE |
-                                   PORT_SYNC_MODE_MASTER_SELECT_MASK);
-       I915_WRITE(reg, trans_ddi_func_ctl2_val);
+       I915_WRITE(TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder), 0);
 }
 
 static void intel_fdi_normal_train(struct intel_crtc *crtc)
index f048578..d925a10 100644 (file)
@@ -4424,9 +4424,11 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx,
        ve->base.gt = siblings[0]->gt;
        ve->base.uncore = siblings[0]->uncore;
        ve->base.id = -1;
+
        ve->base.class = OTHER_CLASS;
        ve->base.uabi_class = I915_ENGINE_CLASS_INVALID;
        ve->base.instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
+       ve->base.uabi_instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
 
        /*
         * The decision on whether to submit a request using semaphores
index a47d5a7..9302621 100644 (file)
@@ -1413,14 +1413,6 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
        int len;
        u32 *cs;
 
-       flags |= MI_MM_SPACE_GTT;
-       if (IS_HASWELL(i915))
-               /* These flags are for resource streamer on HSW+ */
-               flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN;
-       else
-               /* We need to save the extended state for powersaving modes */
-               flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN;
-
        len = 4;
        if (IS_GEN(i915, 7))
                len += 2 + (num_engines ? 4 * num_engines + 6 : 0);
@@ -1589,22 +1581,21 @@ static int switch_context(struct i915_request *rq)
        }
 
        if (ce->state) {
-               u32 hw_flags;
+               u32 flags;
 
                GEM_BUG_ON(rq->engine->id != RCS0);
 
-               /*
-                * The kernel context(s) is treated as pure scratch and is not
-                * expected to retain any state (as we sacrifice it during
-                * suspend and on resume it may be corrupted). This is ok,
-                * as nothing actually executes using the kernel context; it
-                * is purely used for flushing user contexts.
-                */
-               hw_flags = 0;
-               if (i915_gem_context_is_kernel(rq->gem_context))
-                       hw_flags = MI_RESTORE_INHIBIT;
+               /* For resource streamer on HSW+ and power context elsewhere */
+               BUILD_BUG_ON(HSW_MI_RS_SAVE_STATE_EN != MI_SAVE_EXT_STATE_EN);
+               BUILD_BUG_ON(HSW_MI_RS_RESTORE_STATE_EN != MI_RESTORE_EXT_STATE_EN);
+
+               flags = MI_SAVE_EXT_STATE_EN | MI_MM_SPACE_GTT;
+               if (!i915_gem_context_is_kernel(rq->gem_context))
+                       flags |= MI_RESTORE_EXT_STATE_EN;
+               else
+                       flags |= MI_RESTORE_INHIBIT;
 
-               ret = mi_set_context(rq, hw_flags);
+               ret = mi_set_context(rq, flags);
                if (ret)
                        return ret;
        }
index e29bc13..21aa08f 100644 (file)
@@ -1660,8 +1660,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
        (IS_BROADWELL(dev_priv) || IS_GEN(dev_priv, 9))
 
 /* WaRsDisableCoarsePowerGating:skl,cnl */
-#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
-       (IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9))
+#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv)                   \
+       (IS_CANNONLAKE(dev_priv) ||                                     \
+        IS_SKL_GT3(dev_priv) ||                                        \
+        IS_SKL_GT4(dev_priv))
 
 #define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
 #define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \
index 4fd3d76..094011b 100644 (file)
@@ -4177,7 +4177,13 @@ enum {
 #define  CPSSUNIT_CLKGATE_DIS          REG_BIT(9)
 
 #define UNSLICE_UNIT_LEVEL_CLKGATE     _MMIO(0x9434)
-#define  VFUNIT_CLKGATE_DIS            (1 << 20)
+#define   VFUNIT_CLKGATE_DIS           REG_BIT(20)
+#define   HSUNIT_CLKGATE_DIS           REG_BIT(8)
+#define   VSUNIT_CLKGATE_DIS           REG_BIT(3)
+
+#define UNSLICE_UNIT_LEVEL_CLKGATE2    _MMIO(0x94e4)
+#define   VSUNIT_CLKGATE_DIS_TGL       REG_BIT(19)
+#define   PSDUNIT_CLKGATE_DIS          REG_BIT(5)
 
 #define INF_UNIT_LEVEL_CLKGATE         _MMIO(0x9560)
 #define   CGPSF_CLKGATE_DIS            (1 << 3)
index 75ae6f4..86379ed 100644 (file)
@@ -6565,6 +6565,17 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv)
        /* WaEnable32PlaneMode:icl */
        I915_WRITE(GEN9_CSFE_CHICKEN1_RCS,
                   _MASKED_BIT_ENABLE(GEN11_ENABLE_32_PLANE_MODE));
+
+       /*
+        * Wa_1408615072:icl,ehl  (vsunit)
+        * Wa_1407596294:icl,ehl  (hsunit)
+        */
+       intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE,
+                        0, VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS);
+
+       /* Wa_1407352427:icl,ehl */
+       intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE2,
+                        0, PSDUNIT_CLKGATE_DIS);
 }
 
 static void tgl_init_clock_gating(struct drm_i915_private *dev_priv)
index 42651d7..c81cdce 100644 (file)
@@ -489,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 
        WARN_ON(!tcon->quirks->has_channel_0);
 
-       tcon->dclk_min_div = 1;
+       tcon->dclk_min_div = tcon->quirks->dclk_min_div;
        tcon->dclk_max_div = 127;
        sun4i_tcon0_mode_set_common(tcon, mode);
 
@@ -1426,12 +1426,14 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
 static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        .set_mux                = sun4i_a10_tcon_set_mux,
 };
 
 static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        .set_mux                = sun5i_a13_tcon_set_mux,
 };
 
@@ -1440,6 +1442,7 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
        .has_channel_1          = true,
        .has_lvds_alt           = true,
        .needs_de_be_mux        = true,
+       .dclk_min_div           = 1,
        .set_mux                = sun6i_tcon_set_mux,
 };
 
@@ -1447,11 +1450,13 @@ static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
        .needs_de_be_mux        = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        /* Same display pipeline structure as A10 */
        .set_mux                = sun4i_a10_tcon_set_mux,
 };
@@ -1459,11 +1464,13 @@ static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
        .has_channel_0          = true,
        .has_lvds_alt           = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
        .supports_lvds          = true,
        .has_channel_0          = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
@@ -1477,11 +1484,13 @@ static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
 
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
        .has_channel_0          = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
-       .has_channel_0  = true,
-       .needs_edp_reset = true,
+       .has_channel_0          = true,
+       .needs_edp_reset        = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
index f9f1fe8..a62ec82 100644 (file)
@@ -224,6 +224,7 @@ struct sun4i_tcon_quirks {
        bool    needs_de_be_mux; /* sun6i needs mux to select backend */
        bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
        bool    supports_lvds;   /* Does the TCON support an LVDS output? */
+       u8      dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
        /* callback to handle tcon muxing options */
        int     (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
index 8063b1d..e6e4c84 100644 (file)
@@ -261,7 +261,8 @@ static int asus_event(struct hid_device *hdev, struct hid_field *field,
                      struct hid_usage *usage, __s32 value)
 {
        if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
-           (usage->hid & HID_USAGE) != 0x00 && !usage->type) {
+           (usage->hid & HID_USAGE) != 0x00 &&
+           (usage->hid & HID_USAGE) != 0xff && !usage->type) {
                hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
                         usage->hid & HID_USAGE);
        }
index e0b241b..851fe54 100644 (file)
@@ -288,6 +288,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
        offset = report->size;
        report->size += parser->global.report_size * parser->global.report_count;
 
+       /* Total size check: Allow for possible report index byte */
+       if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+               hid_err(parser->device, "report is too long\n");
+               return -1;
+       }
+
        if (!parser->local.usage_index) /* Ignore padding fields */
                return 0;
 
index 7e1689e..3a400ce 100644 (file)
 #define USB_VENDOR_ID_ITE               0x048d
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2  0x8350
+#define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720   0x837a
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900       0x8396
 #define USB_DEVICE_ID_ITE8595          0x8595
 
 #define USB_DEVICE_ID_LG_MULTITOUCH    0x0064
 #define USB_DEVICE_ID_LG_MELFAS_MT     0x6007
 #define I2C_DEVICE_ID_LG_8001          0x8001
+#define I2C_DEVICE_ID_LG_7010          0x7010
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
 #define USB_DEVICE_ID_SYNAPTICS_HD     0x0ac3
 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD        0x1ac3
+#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012       0x2968
 #define USB_DEVICE_ID_SYNAPTICS_TP_V103        0x5710
 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5   0x81a7
 
index 63855f2..dea9cc6 100644 (file)
@@ -1132,9 +1132,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
        }
 
 mapped:
-       if (device->driver->input_mapped && device->driver->input_mapped(device,
-                               hidinput, field, usage, &bit, &max) < 0)
-               goto ignore;
+       if (device->driver->input_mapped &&
+           device->driver->input_mapped(device, hidinput, field, usage,
+                                        &bit, &max) < 0) {
+               /*
+                * The driver indicated that no further generic handling
+                * of the usage is desired.
+                */
+               return;
+       }
 
        set_bit(usage->type, input->evbit);
 
@@ -1215,9 +1221,11 @@ mapped:
                set_bit(MSC_SCAN, input->mscbit);
        }
 
-ignore:
        return;
 
+ignore:
+       usage->type = 0;
+       usage->code = 0;
 }
 
 static void hidinput_handle_scroll(struct hid_usage *usage,
index a45f235..c436e12 100644 (file)
@@ -40,6 +40,9 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
 static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
+       /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
+       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
+                        USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index 3cfeb16..362805d 100644 (file)
@@ -1019,7 +1019,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
                tool = MT_TOOL_DIAL;
        else if (unlikely(!confidence_state)) {
                tool = MT_TOOL_PALM;
-               if (!active &&
+               if (!active && mt &&
                    input_mt_is_active(&mt->slots[slotnum])) {
                        /*
                         * The non-confidence was reported for
@@ -1985,6 +1985,9 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_LG,
                HID_USB_DEVICE(USB_VENDOR_ID_LG,
                        USB_DEVICE_ID_LG_MELFAS_MT) },
+       { .driver_data = MT_CLS_LG,
+               HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
+                       USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) },
 
        /* MosArt panels */
        { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
index d1b39c2..0e7b2d9 100644 (file)
@@ -174,6 +174,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
 
        { 0 }
 };
index 8dae0f9..6286204 100644 (file)
@@ -768,8 +768,12 @@ static int steam_probe(struct hid_device *hdev,
 
        if (steam->quirks & STEAM_QUIRK_WIRELESS) {
                hid_info(hdev, "Steam wireless receiver connected");
+               /* If using a wireless adaptor ask for connection status */
+               steam->connected = false;
                steam_request_conn_status(steam);
        } else {
+               /* A wired connection is always present */
+               steam->connected = true;
                ret = steam_register(steam);
                if (ret) {
                        hid_err(hdev,
index c3fc0ce..7a75aff 100644 (file)
@@ -249,13 +249,14 @@ out:
 static __poll_t hidraw_poll(struct file *file, poll_table *wait)
 {
        struct hidraw_list *list = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* hidraw is always writable */
 
        poll_wait(file, &list->hidraw->wait, wait);
        if (list->head != list->tail)
-               return EPOLLIN | EPOLLRDNORM | EPOLLOUT;
+               mask |= EPOLLIN | EPOLLRDNORM;
        if (!list->hidraw->exist)
-               return EPOLLERR | EPOLLHUP;
-       return 0;
+               mask |= EPOLLERR | EPOLLHUP;
+       return mask;
 }
 
 static int hidraw_open(struct inode *inode, struct file *file)
index a358e61..009000c 100644 (file)
@@ -49,6 +49,8 @@
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
 #define I2C_HID_QUIRK_BOGUS_IRQ                        BIT(4)
 #define I2C_HID_QUIRK_RESET_ON_RESUME          BIT(5)
+#define I2C_HID_QUIRK_BAD_INPUT_SIZE           BIT(6)
+
 
 /* flags */
 #define I2C_HID_STARTED                0
@@ -175,6 +177,8 @@ static const struct i2c_hid_quirks {
                 I2C_HID_QUIRK_BOGUS_IRQ },
        { USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
                 I2C_HID_QUIRK_RESET_ON_RESUME },
+       { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
+               I2C_HID_QUIRK_BAD_INPUT_SIZE },
        { 0, 0 }
 };
 
@@ -496,9 +500,15 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
        }
 
        if ((ret_size > size) || (ret_size < 2)) {
-               dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
-                       __func__, size, ret_size);
-               return;
+               if (ihid->quirks & I2C_HID_QUIRK_BAD_INPUT_SIZE) {
+                       ihid->inbuf[0] = size & 0xff;
+                       ihid->inbuf[1] = size >> 8;
+                       ret_size = size;
+               } else {
+                       dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+                               __func__, size, ret_size);
+                       return;
+               }
        }
 
        i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
index 6c1e611..1fb294c 100644 (file)
@@ -24,7 +24,9 @@
 #define ICL_MOBILE_DEVICE_ID   0x34FC
 #define SPT_H_DEVICE_ID                0xA135
 #define CML_LP_DEVICE_ID       0x02FC
+#define CMP_H_DEVICE_ID                0x06FC
 #define EHL_Ax_DEVICE_ID       0x4BB3
+#define TGL_LP_DEVICE_ID       0xA0FC
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 784dcc8..f491d8b 100644 (file)
@@ -34,7 +34,9 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index fa0cc08..8fe3efc 100644 (file)
@@ -766,13 +766,14 @@ unlock:
 static __poll_t uhid_char_poll(struct file *file, poll_table *wait)
 {
        struct uhid_device *uhid = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uhid is always writable */
 
        poll_wait(file, &uhid->waitq, wait);
 
        if (uhid->head != uhid->tail)
-               return EPOLLIN | EPOLLRDNORM;
+               mask |= EPOLLIN | EPOLLRDNORM;
 
-       return 0;
+       return mask;
 }
 
 static const struct file_operations uhid_fops = {
index e421cdf..a970b80 100644 (file)
@@ -241,12 +241,51 @@ static int hiddev_release(struct inode * inode, struct file * file)
        return 0;
 }
 
+static int __hiddev_open(struct hiddev *hiddev, struct file *file)
+{
+       struct hiddev_list *list;
+       int error;
+
+       lockdep_assert_held(&hiddev->existancelock);
+
+       list = vzalloc(sizeof(*list));
+       if (!list)
+               return -ENOMEM;
+
+       mutex_init(&list->thread_lock);
+       list->hiddev = hiddev;
+
+       if (!hiddev->open++) {
+               error = hid_hw_power(hiddev->hid, PM_HINT_FULLON);
+               if (error < 0)
+                       goto err_drop_count;
+
+               error = hid_hw_open(hiddev->hid);
+               if (error < 0)
+                       goto err_normal_power;
+       }
+
+       spin_lock_irq(&hiddev->list_lock);
+       list_add_tail(&list->node, &hiddev->list);
+       spin_unlock_irq(&hiddev->list_lock);
+
+       file->private_data = list;
+
+       return 0;
+
+err_normal_power:
+       hid_hw_power(hiddev->hid, PM_HINT_NORMAL);
+err_drop_count:
+       hiddev->open--;
+       vfree(list);
+       return error;
+}
+
 /*
  * open file op
  */
 static int hiddev_open(struct inode *inode, struct file *file)
 {
-       struct hiddev_list *list;
        struct usb_interface *intf;
        struct hid_device *hid;
        struct hiddev *hiddev;
@@ -255,66 +294,14 @@ static int hiddev_open(struct inode *inode, struct file *file)
        intf = usbhid_find_interface(iminor(inode));
        if (!intf)
                return -ENODEV;
+
        hid = usb_get_intfdata(intf);
        hiddev = hid->hiddev;
 
-       if (!(list = vzalloc(sizeof(struct hiddev_list))))
-               return -ENOMEM;
-       mutex_init(&list->thread_lock);
-       list->hiddev = hiddev;
-       file->private_data = list;
-
-       /*
-        * no need for locking because the USB major number
-        * is shared which usbcore guards against disconnect
-        */
-       if (list->hiddev->exist) {
-               if (!list->hiddev->open++) {
-                       res = hid_hw_open(hiddev->hid);
-                       if (res < 0)
-                               goto bail;
-               }
-       } else {
-               res = -ENODEV;
-               goto bail;
-       }
-
-       spin_lock_irq(&list->hiddev->list_lock);
-       list_add_tail(&list->node, &hiddev->list);
-       spin_unlock_irq(&list->hiddev->list_lock);
-
        mutex_lock(&hiddev->existancelock);
-       /*
-        * recheck exist with existance lock held to
-        * avoid opening a disconnected device
-        */
-       if (!list->hiddev->exist) {
-               res = -ENODEV;
-               goto bail_unlock;
-       }
-       if (!list->hiddev->open++)
-               if (list->hiddev->exist) {
-                       struct hid_device *hid = hiddev->hid;
-                       res = hid_hw_power(hid, PM_HINT_FULLON);
-                       if (res < 0)
-                               goto bail_unlock;
-                       res = hid_hw_open(hid);
-                       if (res < 0)
-                               goto bail_normal_power;
-               }
-       mutex_unlock(&hiddev->existancelock);
-       return 0;
-bail_normal_power:
-       hid_hw_power(hid, PM_HINT_NORMAL);
-bail_unlock:
+       res = hiddev->exist ? __hiddev_open(hiddev, file) : -ENODEV;
        mutex_unlock(&hiddev->existancelock);
 
-       spin_lock_irq(&list->hiddev->list_lock);
-       list_del(&list->node);
-       spin_unlock_irq(&list->hiddev->list_lock);
-bail:
-       file->private_data = NULL;
-       vfree(list);
        return res;
 }
 
index ccb7452..d99a9d4 100644 (file)
@@ -2096,14 +2096,16 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
                    (hdev->product == 0x34d || hdev->product == 0x34e ||  /* MobileStudio Pro */
                     hdev->product == 0x357 || hdev->product == 0x358 ||  /* Intuos Pro 2 */
                     hdev->product == 0x392 ||                            /* Intuos Pro 2 */
-                    hdev->product == 0x398 || hdev->product == 0x399)) { /* MobileStudio Pro */
+                    hdev->product == 0x398 || hdev->product == 0x399 ||  /* MobileStudio Pro */
+                    hdev->product == 0x3AA)) {                           /* MobileStudio Pro */
                        value = (field->logical_maximum - value);
 
                        if (hdev->product == 0x357 || hdev->product == 0x358 ||
                            hdev->product == 0x392)
                                value = wacom_offset_rotation(input, usage, value, 3, 16);
                        else if (hdev->product == 0x34d || hdev->product == 0x34e ||
-                                hdev->product == 0x398 || hdev->product == 0x399)
+                                hdev->product == 0x398 || hdev->product == 0x399 ||
+                                hdev->product == 0x3AA)
                                value = wacom_offset_rotation(input, usage, value, 1, 2);
                }
                else {
index e13af48..5137e62 100644 (file)
@@ -174,7 +174,7 @@ static struct at91_twi_pdata sama5d2_config = {
 
 static struct at91_twi_pdata sam9x60_config = {
        .clk_max_div = 7,
-       .clk_offset = 4,
+       .clk_offset = 3,
        .has_unre_flag = true,
        .has_alt_cmd = true,
        .has_hold_field = true,
index e01b2b5..5ab901a 100644 (file)
@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev {
        struct i2c_adapter adapter;
        struct completion completion;
        struct i2c_msg *curr_msg;
+       struct clk *bus_clk;
        int num_msgs;
        u32 msg_err;
        u8 *msg_buf;
@@ -404,7 +405,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
        struct resource *mem, *irq;
        int ret;
        struct i2c_adapter *adap;
-       struct clk *bus_clk;
        struct clk *mclk;
        u32 bus_clk_rate;
 
@@ -427,11 +427,11 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(mclk);
        }
 
-       bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+       i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
 
-       if (IS_ERR(bus_clk)) {
+       if (IS_ERR(i2c_dev->bus_clk)) {
                dev_err(&pdev->dev, "Could not register clock\n");
-               return PTR_ERR(bus_clk);
+               return PTR_ERR(i2c_dev->bus_clk);
        }
 
        ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
@@ -442,13 +442,13 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                bus_clk_rate = 100000;
        }
 
-       ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
+       ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate);
        if (ret < 0) {
                dev_err(&pdev->dev, "Could not set clock frequency\n");
                return ret;
        }
 
-       ret = clk_prepare_enable(bus_clk);
+       ret = clk_prepare_enable(i2c_dev->bus_clk);
        if (ret) {
                dev_err(&pdev->dev, "Couldn't prepare clock");
                return ret;
@@ -491,10 +491,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
 static int bcm2835_i2c_remove(struct platform_device *pdev)
 {
        struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-       struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
 
-       clk_rate_exclusive_put(bus_clk);
-       clk_disable_unprepare(bus_clk);
+       clk_rate_exclusive_put(i2c_dev->bus_clk);
+       clk_disable_unprepare(i2c_dev->bus_clk);
 
        free_irq(i2c_dev->irq, i2c_dev);
        i2c_del_adapter(&i2c_dev->adapter);
index 9f8dcd3..35b2097 100644 (file)
@@ -186,10 +186,11 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
         * If we can set SDA, we will always create a STOP to ensure additional
         * pulses will do no harm. This is achieved by letting SDA follow SCL
         * half a cycle later. Check the 'incomplete_write_byte' fault injector
-        * for details.
+        * for details. Note that we must honour tsu:sto, 4us, but lets use 5us
+        * here for simplicity.
         */
        bri->set_scl(adap, scl);
-       ndelay(RECOVERY_NDELAY / 2);
+       ndelay(RECOVERY_NDELAY);
        if (bri->set_sda)
                bri->set_sda(adap, scl);
        ndelay(RECOVERY_NDELAY / 2);
@@ -211,7 +212,13 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
                scl = !scl;
                bri->set_scl(adap, scl);
                /* Creating STOP again, see above */
-               ndelay(RECOVERY_NDELAY / 2);
+               if (scl)  {
+                       /* Honour minimum tsu:sto */
+                       ndelay(RECOVERY_NDELAY);
+               } else {
+                       /* Honour minimum tf and thd:dat */
+                       ndelay(RECOVERY_NDELAY / 2);
+               }
                if (bri->set_sda)
                        bri->set_sda(adap, scl);
                ndelay(RECOVERY_NDELAY / 2);
index 9b6ca15..ad5112a 100644 (file)
@@ -3305,8 +3305,10 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
        int rc;
 
        rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
-       if (rc)
+       if (rc) {
                dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
+               return rc;
+       }
 
        if (mr->pages) {
                rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
index 958c1ff..4d07d22 100644 (file)
@@ -2283,13 +2283,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
                        /* Add qp to flush list of the CQ */
                        bnxt_qplib_add_flush_qp(qp);
                } else {
+                       /* Before we complete, do WA 9060 */
+                       if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
+                                     cqe_sq_cons)) {
+                               *lib_qp = qp;
+                               goto out;
+                       }
                        if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
-                               /* Before we complete, do WA 9060 */
-                               if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
-                                             cqe_sq_cons)) {
-                                       *lib_qp = qp;
-                                       goto out;
-                               }
                                cqe->status = CQ_REQ_STATUS_OK;
                                cqe++;
                                (*budget)--;
index adb4a1b..5836fe7 100644 (file)
@@ -81,7 +81,9 @@ void iowait_init(struct iowait *wait, u32 tx_limit,
 void iowait_cancel_work(struct iowait *w)
 {
        cancel_work_sync(&iowait_get_ib_work(w)->iowork);
-       cancel_work_sync(&iowait_get_tid_work(w)->iowork);
+       /* Make sure that the iowork for TID RDMA is used */
+       if (iowait_get_tid_work(w)->iowork.func)
+               cancel_work_sync(&iowait_get_tid_work(w)->iowork);
 }
 
 /**
index e53f542..8a2e0d9 100644 (file)
@@ -4633,6 +4633,15 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
                         */
                        fpsn = full_flow_psn(flow, flow->flow_state.spsn);
                        req->r_ack_psn = psn;
+                       /*
+                        * If resync_psn points to the last flow PSN for a
+                        * segment and the new segment (likely from a new
+                        * request) starts with a new generation number, we
+                        * need to adjust resync_psn accordingly.
+                        */
+                       if (flow->flow_state.generation !=
+                           (resync_psn >> HFI1_KDETH_BTH_SEQ_SHIFT))
+                               resync_psn = mask_psn(fpsn - 1);
                        flow->resync_npkts +=
                                delta_psn(mask_psn(resync_psn + 1), fpsn);
                        /*
index 8637594..dbd96d0 100644 (file)
@@ -169,8 +169,7 @@ static void i40iw_dealloc_ucontext(struct ib_ucontext *context)
 static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
        struct i40iw_ucontext *ucontext;
-       u64 db_addr_offset;
-       u64 push_offset;
+       u64 db_addr_offset, push_offset, pfn;
 
        ucontext = to_ucontext(context);
        if (ucontext->iwdev->sc_dev.is_pf) {
@@ -189,7 +188,6 @@ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 
        if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) {
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-               vma->vm_private_data = ucontext;
        } else {
                if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2)
                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -197,12 +195,12 @@ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        }
 
-       if (io_remap_pfn_range(vma, vma->vm_start,
-                              vma->vm_pgoff + (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> PAGE_SHIFT),
-                              PAGE_SIZE, vma->vm_page_prot))
-               return -EAGAIN;
+       pfn = vma->vm_pgoff +
+             (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >>
+              PAGE_SHIFT);
 
-       return 0;
+       return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
+                                vma->vm_page_prot, NULL);
 }
 
 /**
index d7dd6fc..f918fca 100644 (file)
@@ -224,13 +224,13 @@ static void __pass_event(struct evdev_client *client,
                 */
                client->tail = (client->head - 2) & (client->bufsize - 1);
 
-               client->buffer[client->tail].input_event_sec =
-                                               event->input_event_sec;
-               client->buffer[client->tail].input_event_usec =
-                                               event->input_event_usec;
-               client->buffer[client->tail].type = EV_SYN;
-               client->buffer[client->tail].code = SYN_DROPPED;
-               client->buffer[client->tail].value = 0;
+               client->buffer[client->tail] = (struct input_event) {
+                       .input_event_sec = event->input_event_sec,
+                       .input_event_usec = event->input_event_usec,
+                       .type = EV_SYN,
+                       .code = SYN_DROPPED,
+                       .value = 0,
+               };
 
                client->packet_head = client->tail;
        }
index 5508627..ee6c323 100644 (file)
@@ -878,16 +878,18 @@ static int input_default_setkeycode(struct input_dev *dev,
                }
        }
 
-       __clear_bit(*old_keycode, dev->keybit);
-       __set_bit(ke->keycode, dev->keybit);
-
-       for (i = 0; i < dev->keycodemax; i++) {
-               if (input_fetch_keycode(dev, i) == *old_keycode) {
-                       __set_bit(*old_keycode, dev->keybit);
-                       break; /* Setting the bit twice is useless, so break */
+       if (*old_keycode <= KEY_MAX) {
+               __clear_bit(*old_keycode, dev->keybit);
+               for (i = 0; i < dev->keycodemax; i++) {
+                       if (input_fetch_keycode(dev, i) == *old_keycode) {
+                               __set_bit(*old_keycode, dev->keybit);
+                               /* Setting the bit twice is useless, so break */
+                               break;
+                       }
                }
        }
 
+       __set_bit(ke->keycode, dev->keybit);
        return 0;
 }
 
@@ -943,9 +945,13 @@ int input_set_keycode(struct input_dev *dev,
         * Simulate keyup event if keycode is not present
         * in the keymap anymore
         */
-       if (test_bit(EV_KEY, dev->evbit) &&
-           !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
-           __test_and_clear_bit(old_keycode, dev->key)) {
+       if (old_keycode > KEY_MAX) {
+               dev_warn(dev->dev.parent ?: &dev->dev,
+                        "%s: got too big old keycode %#x\n",
+                        __func__, old_keycode);
+       } else if (test_bit(EV_KEY, dev->evbit) &&
+                  !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+                  __test_and_clear_bit(old_keycode, dev->key)) {
                struct input_value vals[] =  {
                        { EV_KEY, old_keycode, 0 },
                        input_value_sync
index 5379952..9f809ae 100644 (file)
@@ -78,7 +78,13 @@ static void imx_sc_check_for_events(struct work_struct *work)
                return;
        }
 
-       state = (bool)msg.state;
+       /*
+        * The response data from SCU firmware is 4 bytes,
+        * but ONLY the first byte is the key state, other
+        * 3 bytes could be some dirty data, so we should
+        * ONLY take the first byte as key state.
+        */
+       state = (bool)(msg.state & 0xff);
 
        if (state ^ priv->keystate) {
                priv->keystate = state;
index fd25378..f259313 100644 (file)
@@ -74,12 +74,16 @@ static int uinput_dev_event(struct input_dev *dev,
        struct uinput_device    *udev = input_get_drvdata(dev);
        struct timespec64       ts;
 
-       udev->buff[udev->head].type = type;
-       udev->buff[udev->head].code = code;
-       udev->buff[udev->head].value = value;
        ktime_get_ts64(&ts);
-       udev->buff[udev->head].input_event_sec = ts.tv_sec;
-       udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+       udev->buff[udev->head] = (struct input_event) {
+               .input_event_sec = ts.tv_sec,
+               .input_event_usec = ts.tv_nsec / NSEC_PER_USEC,
+               .type = type,
+               .code = code,
+               .value = value,
+       };
+
        udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
        wake_up_interruptible(&udev->waitq);
@@ -689,13 +693,14 @@ static ssize_t uinput_read(struct file *file, char __user *buffer,
 static __poll_t uinput_poll(struct file *file, poll_table *wait)
 {
        struct uinput_device *udev = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uinput is always writable */
 
        poll_wait(file, &udev->waitq, wait);
 
        if (udev->head != udev->tail)
-               return EPOLLIN | EPOLLRDNORM;
+               mask |= EPOLLIN | EPOLLRDNORM;
 
-       return EPOLLOUT | EPOLLWRNORM;
+       return mask;
 }
 
 static int uinput_release(struct inode *inode, struct file *file)
index c363294..a2e96a5 100644 (file)
@@ -1203,7 +1203,6 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
 {
        struct device *dev = msi_desc_to_dev(desc);
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iommu_dma_cookie *cookie;
        struct iommu_dma_msi_page *msi_page;
        static DEFINE_MUTEX(msi_prepare_lock); /* see below */
 
@@ -1212,8 +1211,6 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
                return 0;
        }
 
-       cookie = domain->iova_cookie;
-
        /*
         * In fact the whole prepare operation should already be serialised by
         * irq_domain_mutex further up the callchain, but that's pretty subtle
index 4296661..1801f0a 100644 (file)
@@ -5624,8 +5624,10 @@ static int intel_iommu_add_device(struct device *dev)
 
        group = iommu_group_get_for_dev(dev);
 
-       if (IS_ERR(group))
-               return PTR_ERR(group);
+       if (IS_ERR(group)) {
+               ret = PTR_ERR(group);
+               goto unlink;
+       }
 
        iommu_group_put(group);
 
@@ -5651,7 +5653,8 @@ static int intel_iommu_add_device(struct device *dev)
                                if (!get_private_domain_for_dev(dev)) {
                                        dev_warn(dev,
                                                 "Failed to get a private domain.\n");
-                                       return -ENOMEM;
+                                       ret = -ENOMEM;
+                                       goto unlink;
                                }
 
                                dev_info(dev,
@@ -5666,6 +5669,10 @@ static int intel_iommu_add_device(struct device *dev)
        }
 
        return 0;
+
+unlink:
+       iommu_device_unlink(&iommu->iommu, dev);
+       return ret;
 }
 
 static void intel_iommu_remove_device(struct device *dev)
@@ -5817,6 +5824,13 @@ static void intel_iommu_apply_resv_region(struct device *dev,
        WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
 }
 
+static struct iommu_group *intel_iommu_device_group(struct device *dev)
+{
+       if (dev_is_pci(dev))
+               return pci_device_group(dev);
+       return generic_device_group(dev);
+}
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
 struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
 {
@@ -5989,7 +6003,7 @@ const struct iommu_ops intel_iommu_ops = {
        .get_resv_regions       = intel_iommu_get_resv_regions,
        .put_resv_regions       = intel_iommu_put_resv_regions,
        .apply_resv_region      = intel_iommu_apply_resv_region,
-       .device_group           = pci_device_group,
+       .device_group           = intel_iommu_device_group,
        .dev_has_feat           = intel_iommu_dev_has_feat,
        .dev_feat_enabled       = intel_iommu_dev_feat_enabled,
        .dev_enable_feat        = intel_iommu_dev_enable_feat,
index fdd4075..3ead597 100644 (file)
@@ -751,6 +751,7 @@ err_put_group:
        mutex_unlock(&group->mutex);
        dev->iommu_group = NULL;
        kobject_put(group->devices_kobj);
+       sysfs_remove_link(group->devices_kobj, device->name);
 err_free_name:
        kfree(device->name);
 err_remove_link:
index edf94ee..aa9368b 100644 (file)
@@ -148,13 +148,13 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
        unsigned long timeout;
        u32 syscfg;
 
-       if (state == FL_RESETING || state == FL_PREPARING_ERASE ||
+       if (state == FL_RESETTING || state == FL_PREPARING_ERASE ||
            state == FL_VERIFYING_ERASE) {
                int i = 21;
                unsigned int intr_flags = ONENAND_INT_MASTER;
 
                switch (state) {
-               case FL_RESETING:
+               case FL_RESETTING:
                        intr_flags |= ONENAND_INT_RESET;
                        break;
                case FL_PREPARING_ERASE:
@@ -328,7 +328,8 @@ static inline int omap2_onenand_dma_transfer(struct omap2_onenand *c,
        struct dma_async_tx_descriptor *tx;
        dma_cookie_t cookie;
 
-       tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count, 0);
+       tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count,
+                                      DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
        if (!tx) {
                dev_err(&c->pdev->dev, "Failed to prepare DMA memcpy\n");
                return -EIO;
@@ -375,7 +376,7 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
         * context fallback to PIO mode.
         */
        if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
-           count < 384 || in_interrupt() || oops_in_progress )
+           count < 384 || in_interrupt() || oops_in_progress)
                goto out_copy;
 
        xtra = count & 3;
@@ -422,7 +423,7 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
         * context fallback to PIO mode.
         */
        if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
-           count < 384 || in_interrupt() || oops_in_progress )
+           count < 384 || in_interrupt() || oops_in_progress)
                goto out_copy;
 
        dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
@@ -528,7 +529,8 @@ static int omap2_onenand_probe(struct platform_device *pdev)
                 c->gpmc_cs, c->phys_base, c->onenand.base,
                 c->dma_chan ? "DMA" : "PIO");
 
-       if ((r = onenand_scan(&c->mtd, 1)) < 0)
+       r = onenand_scan(&c->mtd, 1);
+       if (r < 0)
                goto err_release_dma;
 
        freq = omap2_onenand_get_freq(c->onenand.version_id);
index 77bd32a..85640ee 100644 (file)
@@ -2853,7 +2853,7 @@ static int onenand_otp_write_oob_nolock(struct mtd_info *mtd, loff_t to,
 
                /* Exit OTP access mode */
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
 
                status = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
                status &= 0x60;
@@ -2924,7 +2924,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        /* Exit OTP access mode */
        this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        return ret;
 }
@@ -2968,7 +2968,7 @@ static int do_otp_write(struct mtd_info *mtd, loff_t to, size_t len,
 
        /* Exit OTP access mode */
        this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        return ret;
 }
@@ -3008,7 +3008,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
 
                /* Exit OTP access mode */
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
        } else {
                ops.mode = MTD_OPS_PLACE_OOB;
                ops.ooblen = len;
@@ -3413,7 +3413,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
                this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
 
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
 
                printk(KERN_INFO "Die %d boundary: %d%s\n", die,
                       this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@@ -3635,7 +3635,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
        ret = this->wait(mtd, FL_WRITING);
 out:
        this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
        if (!ret)
                /* Recalculate device size on boundary change*/
                flexonenand_get_size(mtd);
@@ -3671,7 +3671,7 @@ static int onenand_chip_probe(struct mtd_info *mtd)
        /* Reset OneNAND to read default register values */
        this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
        /* Wait reset */
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        /* Restore system configuration 1 */
        this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
index 55e5536..beb7987 100644 (file)
@@ -675,12 +675,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
 normal:
        if (count != mtd->writesize) {
                /* Copy the bufferram to memory to prevent unaligned access */
-               memcpy(this->page_buf, p, mtd->writesize);
-               p = this->page_buf + offset;
+               memcpy_fromio(this->page_buf, p, mtd->writesize);
+               memcpy(buffer, this->page_buf + offset, count);
+       } else {
+               memcpy_fromio(buffer, p, count);
        }
 
-       memcpy(buffer, p, count);
-
        return 0;
 }
 
index 3a36285..f6c7102 100644 (file)
@@ -914,8 +914,8 @@ static void cadence_nand_get_caps(struct cdns_nand_ctrl *cdns_ctrl)
 /* Prepare CDMA descriptor. */
 static void
 cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl,
-                              char nf_mem, u32 flash_ptr, char *mem_ptr,
-                              char *ctrl_data_ptr, u16 ctype)
+                              char nf_mem, u32 flash_ptr, dma_addr_t mem_ptr,
+                                  dma_addr_t ctrl_data_ptr, u16 ctype)
 {
        struct cadence_nand_cdma_desc *cdma_desc = cdns_ctrl->cdma_desc;
 
@@ -931,13 +931,13 @@ cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl,
        cdma_desc->command_flags |= CDMA_CF_DMA_MASTER;
        cdma_desc->command_flags  |= CDMA_CF_INT;
 
-       cdma_desc->memory_pointer = (uintptr_t)mem_ptr;
+       cdma_desc->memory_pointer = mem_ptr;
        cdma_desc->status = 0;
        cdma_desc->sync_flag_pointer = 0;
        cdma_desc->sync_arguments = 0;
 
        cdma_desc->command_type = ctype;
-       cdma_desc->ctrl_data_ptr = (uintptr_t)ctrl_data_ptr;
+       cdma_desc->ctrl_data_ptr = ctrl_data_ptr;
 }
 
 static u8 cadence_nand_check_desc_error(struct cdns_nand_ctrl *cdns_ctrl,
@@ -1280,8 +1280,7 @@ cadence_nand_cdma_transfer(struct cdns_nand_ctrl *cdns_ctrl, u8 chip_nr,
        }
 
        cadence_nand_cdma_desc_prepare(cdns_ctrl, chip_nr, page,
-                                      (void *)dma_buf, (void *)dma_ctrl_dat,
-                                      ctype);
+                                      dma_buf, dma_ctrl_dat, ctype);
 
        status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr);
 
@@ -1360,7 +1359,7 @@ static int cadence_nand_erase(struct nand_chip *chip, u32 page)
 
        cadence_nand_cdma_desc_prepare(cdns_ctrl,
                                       cdns_chip->cs[chip->cur_cs],
-                                      page, NULL, NULL,
+                                      page, 0, 0,
                                       CDMA_CT_ERASE);
        status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr);
        if (status) {
index 9e63800..3ba73f1 100644 (file)
@@ -37,6 +37,7 @@
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN           (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
 
+#define FMC2_TIMEOUT_US                        1000
 #define FMC2_TIMEOUT_MS                        1000
 
 /* Timings */
@@ -53,6 +54,8 @@
 #define FMC2_PMEM                      0x88
 #define FMC2_PATT                      0x8c
 #define FMC2_HECCR                     0x94
+#define FMC2_ISR                       0x184
+#define FMC2_ICR                       0x188
 #define FMC2_CSQCR                     0x200
 #define FMC2_CSQCFGR1                  0x204
 #define FMC2_CSQCFGR2                  0x208
 #define FMC2_PATT_ATTHIZ(x)            (((x) & 0xff) << 24)
 #define FMC2_PATT_DEFAULT              0x0a0a0a0a
 
+/* Register: FMC2_ISR */
+#define FMC2_ISR_IHLF                  BIT(1)
+
+/* Register: FMC2_ICR */
+#define FMC2_ICR_CIHLF                 BIT(1)
+
 /* Register: FMC2_CSQCR */
 #define FMC2_CSQCR_CSQSTART            BIT(0)
 
@@ -1322,6 +1331,31 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
                stm32_fmc2_set_buswidth_16(fmc2, true);
 }
 
+static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
+{
+       struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+       const struct nand_sdr_timings *timings;
+       u32 isr, sr;
+
+       /* Check if there is no pending requests to the NAND flash */
+       if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
+                                             sr & FMC2_SR_NWRF, 1,
+                                             FMC2_TIMEOUT_US))
+               dev_warn(fmc2->dev, "Waitrdy timeout\n");
+
+       /* Wait tWB before R/B# signal is low */
+       timings = nand_get_sdr_timings(&chip->data_interface);
+       ndelay(PSEC_TO_NSEC(timings->tWB_max));
+
+       /* R/B# signal is low, clear high level flag */
+       writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR);
+
+       /* Wait R/B# signal is high */
+       return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR,
+                                                isr, isr & FMC2_ISR_IHLF,
+                                                5, 1000 * timeout_ms);
+}
+
 static int stm32_fmc2_exec_op(struct nand_chip *chip,
                              const struct nand_operation *op,
                              bool check_only)
@@ -1366,8 +1400,8 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
                        break;
 
                case NAND_OP_WAITRDY_INSTR:
-                       ret = nand_soft_waitrdy(chip,
-                                               instr->ctx.waitrdy.timeout_ms);
+                       ret = stm32_fmc2_waitrdy(chip,
+                                                instr->ctx.waitrdy.timeout_ms);
                        break;
                }
        }
index 4744bf9..b9f2724 100644 (file)
@@ -247,7 +247,8 @@ static int sm_read_sector(struct sm_ftl *ftl,
 
        /* FTL can contain -1 entries that are by default filled with bits */
        if (block == -1) {
-               memset(buffer, 0xFF, SM_SECTOR_SIZE);
+               if (buffer)
+                       memset(buffer, 0xFF, SM_SECTOR_SIZE);
                return 0;
        }
 
index f4afe12..aeb3ad2 100644 (file)
@@ -4596,6 +4596,7 @@ static void sst_set_default_init(struct spi_nor *nor)
 static void st_micron_set_default_init(struct spi_nor *nor)
 {
        nor->flags |= SNOR_F_HAS_LOCK;
+       nor->flags &= ~SNOR_F_HAS_16BIT_SR;
        nor->params.quad_enable = NULL;
        nor->params.set_4byte = st_micron_set_4byte;
 }
index 4e1789e..eacd428 100644 (file)
 #define TCAN4X5X_MODE_NORMAL BIT(7)
 
 #define TCAN4X5X_DISABLE_WAKE_MSK      (BIT(31) | BIT(30))
+#define TCAN4X5X_DISABLE_INH_MSK       BIT(9)
 
 #define TCAN4X5X_SW_RESET BIT(2)
 
@@ -166,6 +167,28 @@ static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
        }
 }
 
+static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
+{
+       int ret = 0;
+
+       if (priv->reset_gpio) {
+               gpiod_set_value(priv->reset_gpio, 1);
+
+               /* tpulse_width minimum 30us */
+               usleep_range(30, 100);
+               gpiod_set_value(priv->reset_gpio, 0);
+       } else {
+               ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
+                                  TCAN4X5X_SW_RESET);
+               if (ret)
+                       return ret;
+       }
+
+       usleep_range(700, 1000);
+
+       return ret;
+}
+
 static int regmap_spi_gather_write(void *context, const void *reg,
                                   size_t reg_len, const void *val,
                                   size_t val_len)
@@ -348,14 +371,23 @@ static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
                                  TCAN4X5X_DISABLE_WAKE_MSK, 0x00);
 }
 
+static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
+{
+       struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+
+       return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
+                                 TCAN4X5X_DISABLE_INH_MSK, 0x01);
+}
+
 static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
 {
        struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+       int ret;
 
        tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
                                                    GPIOD_OUT_HIGH);
        if (IS_ERR(tcan4x5x->device_wake_gpio)) {
-               if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER)
+               if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER)
                        return -EPROBE_DEFER;
 
                tcan4x5x_disable_wake(cdev);
@@ -366,18 +398,17 @@ static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
        if (IS_ERR(tcan4x5x->reset_gpio))
                tcan4x5x->reset_gpio = NULL;
 
-       usleep_range(700, 1000);
+       ret = tcan4x5x_reset(tcan4x5x);
+       if (ret)
+               return ret;
 
        tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
                                                              "device-state",
                                                              GPIOD_IN);
-       if (IS_ERR(tcan4x5x->device_state_gpio))
+       if (IS_ERR(tcan4x5x->device_state_gpio)) {
                tcan4x5x->device_state_gpio = NULL;
-
-       tcan4x5x->power = devm_regulator_get_optional(cdev->dev,
-                                                     "vsup");
-       if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
+               tcan4x5x_disable_state(cdev);
+       }
 
        return 0;
 }
@@ -412,6 +443,12 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        if (!priv)
                return -ENOMEM;
 
+       priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
+       if (PTR_ERR(priv->power) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       else
+               priv->power = NULL;
+
        mcan_class->device_data = priv;
 
        m_can_class_get_clocks(mcan_class);
@@ -451,11 +488,17 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
                                        &spi->dev, &tcan4x5x_regmap);
 
-       ret = tcan4x5x_parse_config(mcan_class);
+       ret = tcan4x5x_power_enable(priv->power, 1);
        if (ret)
                goto out_clk;
 
-       tcan4x5x_power_enable(priv->power, 1);
+       ret = tcan4x5x_parse_config(mcan_class);
+       if (ret)
+               goto out_power;
+
+       ret = tcan4x5x_init(mcan_class);
+       if (ret)
+               goto out_power;
 
        ret = m_can_class_register(mcan_class);
        if (ret)
index 8caf7af..99101d7 100644 (file)
@@ -381,13 +381,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
        struct net_device *dev = napi->dev;
        struct mscan_regs __iomem *regs = priv->reg_base;
        struct net_device_stats *stats = &dev->stats;
-       int npackets = 0;
-       int ret = 1;
+       int work_done = 0;
        struct sk_buff *skb;
        struct can_frame *frame;
        u8 canrflg;
 
-       while (npackets < quota) {
+       while (work_done < quota) {
                canrflg = in_8(&regs->canrflg);
                if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
                        break;
@@ -408,18 +407,18 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
 
                stats->rx_packets++;
                stats->rx_bytes += frame->can_dlc;
-               npackets++;
+               work_done++;
                netif_receive_skb(skb);
        }
 
-       if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
-               napi_complete(&priv->napi);
-               clear_bit(F_RX_PROGRESS, &priv->flags);
-               if (priv->can.state < CAN_STATE_BUS_OFF)
-                       out_8(&regs->canrier, priv->shadow_canrier);
-               ret = 0;
+       if (work_done < quota) {
+               if (likely(napi_complete_done(&priv->napi, work_done))) {
+                       clear_bit(F_RX_PROGRESS, &priv->flags);
+                       if (priv->can.state < CAN_STATE_BUS_OFF)
+                               out_8(&regs->canrier, priv->shadow_canrier);
+               }
        }
-       return ret;
+       return work_done;
 }
 
 static irqreturn_t mscan_isr(int irq, void *dev_id)
index 2f74f67..a4b4b74 100644 (file)
@@ -918,7 +918,7 @@ static int gs_usb_probe(struct usb_interface *intf,
                             GS_USB_BREQ_HOST_FORMAT,
                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
                             1,
-                            intf->altsetting[0].desc.bInterfaceNumber,
+                            intf->cur_altsetting->desc.bInterfaceNumber,
                             hconf,
                             sizeof(*hconf),
                             1000);
@@ -941,7 +941,7 @@ static int gs_usb_probe(struct usb_interface *intf,
                             GS_USB_BREQ_DEVICE_CONFIG,
                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
                             1,
-                            intf->altsetting[0].desc.bInterfaceNumber,
+                            intf->cur_altsetting->desc.bInterfaceNumber,
                             dconf,
                             sizeof(*dconf),
                             1000);
index 5fc0be5..7ab87a7 100644 (file)
@@ -1590,7 +1590,7 @@ static int kvaser_usb_hydra_setup_endpoints(struct kvaser_usb *dev)
        struct usb_endpoint_descriptor *ep;
        int i;
 
-       iface_desc = &dev->intf->altsetting[0];
+       iface_desc = dev->intf->cur_altsetting;
 
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                ep = &iface_desc->endpoint[i].desc;
index ae4c37e..1b9957f 100644 (file)
@@ -1310,7 +1310,7 @@ static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
        struct usb_endpoint_descriptor *endpoint;
        int i;
 
-       iface_desc = &dev->intf->altsetting[0];
+       iface_desc = dev->intf->cur_altsetting;
 
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
index 120a65d..b016cc2 100644 (file)
@@ -360,6 +360,11 @@ int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
 {
        u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
 
+       /* Use the default high priority for management frames sent to
+        * the CPU.
+        */
+       port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI;
+
        return mv88e6390_g1_monitor_write(chip, ptr, port);
 }
 
index bc5a6b2..5324c6f 100644 (file)
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST         0x2000
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST          0x2100
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST             0x3000
+#define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI     0x00e0
 #define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK                        0x00ff
 
 /* Offset 0x1C: Global Control 2 */
index 7fe256c..0b43c65 100644 (file)
@@ -393,7 +393,7 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port)
 }
 
 static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
-                                   phy_interface_t mode)
+                                   phy_interface_t mode, bool force)
 {
        u8 lane;
        u16 cmode;
@@ -427,8 +427,8 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                cmode = 0;
        }
 
-       /* cmode doesn't change, nothing to do for us */
-       if (cmode == chip->ports[port].cmode)
+       /* cmode doesn't change, nothing to do for us unless forced */
+       if (cmode == chip->ports[port].cmode && !force)
                return 0;
 
        lane = mv88e6xxx_serdes_get_lane(chip, port);
@@ -484,7 +484,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        if (port != 9 && port != 10)
                return -EOPNOTSUPP;
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
@@ -504,7 +504,7 @@ int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                break;
        }
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 static int mv88e6341_port_set_cmode_writable(struct mv88e6xxx_chip *chip,
@@ -555,7 +555,7 @@ int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, true);
 }
 
 int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
index a17a4da..c85e3e2 100644 (file)
@@ -403,6 +403,8 @@ int aq_nic_start(struct aq_nic_s *self)
        if (err < 0)
                goto err_exit;
 
+       aq_nic_set_loopback(self);
+
        err = self->aq_hw_ops->hw_start(self->aq_hw);
        if (err < 0)
                goto err_exit;
@@ -413,8 +415,6 @@ int aq_nic_start(struct aq_nic_s *self)
 
        INIT_WORK(&self->service_task, aq_nic_service_task);
 
-       aq_nic_set_loopback(self);
-
        timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
        aq_nic_service_timer_cb(&self->service_timer);
 
index 58e891a..ec041f7 100644 (file)
@@ -1525,9 +1525,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
        .rx_extract_ts           = hw_atl_b0_rx_extract_ts,
        .extract_hwts            = hw_atl_b0_extract_hwts,
        .hw_set_offload          = hw_atl_b0_hw_offload_set,
-       .hw_get_hw_stats         = hw_atl_utils_get_hw_stats,
-       .hw_get_fw_version       = hw_atl_utils_get_fw_version,
-       .hw_set_offload          = hw_atl_b0_hw_offload_set,
        .hw_set_loopback         = hw_atl_b0_set_loopback,
        .hw_set_fc               = hw_atl_b0_set_fc,
 };
index 8910b62..f547baa 100644 (file)
@@ -667,9 +667,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
        u32 speed;
 
        mpi_state = hw_atl_utils_mpi_get_state(self);
-       speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
-                            FW2X_RATE_2G5 | FW2X_RATE_5G |
-                            FW2X_RATE_10G);
+       speed = mpi_state >> HW_ATL_MPI_SPEED_SHIFT;
 
        if (!speed) {
                link_status->mbps = 0U;
index 035dbb1..ec25fd8 100644 (file)
@@ -1516,8 +1516,10 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
        int ethaddr_bytes = ETH_ALEN;
 
        memset(ppattern + offset, 0xff, magicsync);
-       for (j = 0; j < magicsync; j++)
-               set_bit(len++, (unsigned long *) pmask);
+       for (j = 0; j < magicsync; j++) {
+               pmask[len >> 3] |= BIT(len & 7);
+               len++;
+       }
 
        for (j = 0; j < B44_MAX_PATTERNS; j++) {
                if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
@@ -1529,7 +1531,8 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
                for (k = 0; k< ethaddr_bytes; k++) {
                        ppattern[offset + magicsync +
                                (j * ETH_ALEN) + k] = macaddr[k];
-                       set_bit(len++, (unsigned long *) pmask);
+                       pmask[len >> 3] |= BIT(len & 7);
+                       len++;
                }
        }
        return len - 1;
index c5ee363..a0503b9 100644 (file)
@@ -4088,7 +4088,7 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
        mgmt->rate = 0;
        mgmt->hw.init = &init;
 
-       *tx_clk = clk_register(NULL, &mgmt->hw);
+       *tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
        if (IS_ERR(*tx_clk))
                return PTR_ERR(*tx_clk);
 
@@ -4416,7 +4416,6 @@ err_out_free_netdev:
 
 err_disable_clocks:
        clk_disable_unprepare(tx_clk);
-       clk_unregister(tx_clk);
        clk_disable_unprepare(hclk);
        clk_disable_unprepare(pclk);
        clk_disable_unprepare(rx_clk);
@@ -4446,7 +4445,6 @@ static int macb_remove(struct platform_device *pdev)
                pm_runtime_dont_use_autosuspend(&pdev->dev);
                if (!pm_runtime_suspended(&pdev->dev)) {
                        clk_disable_unprepare(bp->tx_clk);
-                       clk_unregister(bp->tx_clk);
                        clk_disable_unprepare(bp->hclk);
                        clk_disable_unprepare(bp->pclk);
                        clk_disable_unprepare(bp->rx_clk);
index 05c1899..9294027 100644 (file)
@@ -2199,8 +2199,14 @@ static void fec_enet_get_regs(struct net_device *ndev,
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        u32 __iomem *theregs = (u32 __iomem *)fep->hwp;
+       struct device *dev = &fep->pdev->dev;
        u32 *buf = (u32 *)regbuf;
        u32 i, off;
+       int ret;
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               return;
 
        regs->version = fec_enet_register_version;
 
@@ -2216,6 +2222,9 @@ static void fec_enet_get_regs(struct net_device *ndev,
                off >>= 2;
                buf[off] = readl(&theregs[off]);
        }
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static int fec_enet_get_ts_info(struct net_device *ndev,
index edec61d..9f52e72 100644 (file)
@@ -418,8 +418,6 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
        rx->cnt = cnt;
        rx->fill_cnt += work_done;
 
-       /* restock desc ring slots */
-       dma_wmb();      /* Ensure descs are visible before ringing doorbell */
        gve_rx_write_doorbell(priv, rx);
        return gve_rx_work_pending(rx);
 }
index f488943..d0244fe 100644 (file)
@@ -487,10 +487,6 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
                 * may have added descriptors without ringing the doorbell.
                 */
 
-               /* Ensure tx descs from a prior gve_tx are visible before
-                * ringing doorbell.
-                */
-               dma_wmb();
                gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
                return NETDEV_TX_BUSY;
        }
@@ -505,8 +501,6 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
        if (!netif_xmit_stopped(tx->netdev_txq) && netdev_xmit_more())
                return NETDEV_TX_OK;
 
-       /* Ensure tx descs are visible before ringing doorbell */
-       dma_wmb();
        gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
        return NETDEV_TX_OK;
 }
index 68d5930..d48292c 100644 (file)
@@ -122,6 +122,22 @@ enum {
 #endif
 };
 
+#define MLX5E_TTC_NUM_GROUPS   3
+#define MLX5E_TTC_GROUP1_SIZE  (BIT(3) + MLX5E_NUM_TUNNEL_TT)
+#define MLX5E_TTC_GROUP2_SIZE   BIT(1)
+#define MLX5E_TTC_GROUP3_SIZE   BIT(0)
+#define MLX5E_TTC_TABLE_SIZE   (MLX5E_TTC_GROUP1_SIZE +\
+                                MLX5E_TTC_GROUP2_SIZE +\
+                                MLX5E_TTC_GROUP3_SIZE)
+
+#define MLX5E_INNER_TTC_NUM_GROUPS     3
+#define MLX5E_INNER_TTC_GROUP1_SIZE    BIT(3)
+#define MLX5E_INNER_TTC_GROUP2_SIZE    BIT(1)
+#define MLX5E_INNER_TTC_GROUP3_SIZE    BIT(0)
+#define MLX5E_INNER_TTC_TABLE_SIZE     (MLX5E_INNER_TTC_GROUP1_SIZE +\
+                                        MLX5E_INNER_TTC_GROUP2_SIZE +\
+                                        MLX5E_INNER_TTC_GROUP3_SIZE)
+
 #ifdef CONFIG_MLX5_EN_RXNFC
 
 struct mlx5e_ethtool_table {
index 1d6b588..3a97564 100644 (file)
@@ -197,9 +197,10 @@ int mlx5e_health_report(struct mlx5e_priv *priv,
                        struct devlink_health_reporter *reporter, char *err_str,
                        struct mlx5e_err_ctx *err_ctx)
 {
-       if (!reporter) {
-               netdev_err(priv->netdev, err_str);
+       netdev_err(priv->netdev, err_str);
+
+       if (!reporter)
                return err_ctx->recover(&err_ctx->ctx);
-       }
+
        return devlink_health_report(reporter, err_str, err_ctx);
 }
index 15b7f0f..73d3dc0 100644 (file)
@@ -904,22 +904,6 @@ del_rules:
        return err;
 }
 
-#define MLX5E_TTC_NUM_GROUPS   3
-#define MLX5E_TTC_GROUP1_SIZE  (BIT(3) + MLX5E_NUM_TUNNEL_TT)
-#define MLX5E_TTC_GROUP2_SIZE   BIT(1)
-#define MLX5E_TTC_GROUP3_SIZE   BIT(0)
-#define MLX5E_TTC_TABLE_SIZE   (MLX5E_TTC_GROUP1_SIZE +\
-                                MLX5E_TTC_GROUP2_SIZE +\
-                                MLX5E_TTC_GROUP3_SIZE)
-
-#define MLX5E_INNER_TTC_NUM_GROUPS     3
-#define MLX5E_INNER_TTC_GROUP1_SIZE    BIT(3)
-#define MLX5E_INNER_TTC_GROUP2_SIZE    BIT(1)
-#define MLX5E_INNER_TTC_GROUP3_SIZE    BIT(0)
-#define MLX5E_INNER_TTC_TABLE_SIZE     (MLX5E_INNER_TTC_GROUP1_SIZE +\
-                                        MLX5E_INNER_TTC_GROUP2_SIZE +\
-                                        MLX5E_INNER_TTC_GROUP3_SIZE)
-
 static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc,
                                         bool use_ipv)
 {
index 9b32a9c..024e1cd 100644 (file)
@@ -592,7 +592,7 @@ static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp,
        for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
                ttc_params->indir_tirn[tt] = hp->indir_tirn[tt];
 
-       ft_attr->max_fte = MLX5E_NUM_TT;
+       ft_attr->max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
        ft_attr->prio = MLX5E_TC_PRIO;
 }
@@ -2999,6 +2999,25 @@ static struct ip_tunnel_info *dup_tun_info(const struct ip_tunnel_info *tun_info
        return kmemdup(tun_info, tun_size, GFP_KERNEL);
 }
 
+static bool is_duplicated_encap_entry(struct mlx5e_priv *priv,
+                                     struct mlx5e_tc_flow *flow,
+                                     int out_index,
+                                     struct mlx5e_encap_entry *e,
+                                     struct netlink_ext_ack *extack)
+{
+       int i;
+
+       for (i = 0; i < out_index; i++) {
+               if (flow->encaps[i].e != e)
+                       continue;
+               NL_SET_ERR_MSG_MOD(extack, "can't duplicate encap action");
+               netdev_err(priv->netdev, "can't duplicate encap action\n");
+               return true;
+       }
+
+       return false;
+}
+
 static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow,
                              struct net_device *mirred_dev,
@@ -3034,6 +3053,12 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
 
        /* must verify if encap is valid or not */
        if (e) {
+               /* Check that entry was not already attached to this flow */
+               if (is_duplicated_encap_entry(priv, flow, out_index, e, extack)) {
+                       err = -EOPNOTSUPP;
+                       goto out_err;
+               }
+
                mutex_unlock(&esw->offloads.encap_tbl_lock);
                wait_for_completion(&e->res_ready);
 
@@ -3220,6 +3245,26 @@ bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
               same_hw_devs(priv, netdev_priv(out_dev));
 }
 
+static bool is_duplicated_output_device(struct net_device *dev,
+                                       struct net_device *out_dev,
+                                       int *ifindexes, int if_count,
+                                       struct netlink_ext_ack *extack)
+{
+       int i;
+
+       for (i = 0; i < if_count; i++) {
+               if (ifindexes[i] == out_dev->ifindex) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "can't duplicate output to same device");
+                       netdev_err(dev, "can't duplicate output to same device: %s\n",
+                                  out_dev->name);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                struct flow_action *flow_action,
                                struct mlx5e_tc_flow *flow,
@@ -3231,11 +3276,12 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
        struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        const struct ip_tunnel_info *info = NULL;
+       int ifindexes[MLX5_MAX_FLOW_FWD_VPORTS];
        bool ft_flow = mlx5e_is_ft_flow(flow);
        const struct flow_action_entry *act;
+       int err, i, if_count = 0;
        bool encap = false;
        u32 action = 0;
-       int err, i;
 
        if (!flow_action_has_entries(flow_action))
                return -EINVAL;
@@ -3312,6 +3358,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
                                struct net_device *uplink_upper;
 
+                               if (is_duplicated_output_device(priv->netdev,
+                                                               out_dev,
+                                                               ifindexes,
+                                                               if_count,
+                                                               extack))
+                                       return -EOPNOTSUPP;
+
+                               ifindexes[if_count] = out_dev->ifindex;
+                               if_count++;
+
                                rcu_read_lock();
                                uplink_upper =
                                        netdev_master_upper_dev_get_rcu(uplink_dev);
index 9a48c43..8c5df6c 100644 (file)
@@ -531,16 +531,9 @@ static void del_hw_fte(struct fs_node *node)
        }
 }
 
-static void del_sw_fte_rcu(struct rcu_head *head)
-{
-       struct fs_fte *fte = container_of(head, struct fs_fte, rcu);
-       struct mlx5_flow_steering *steering = get_steering(&fte->node);
-
-       kmem_cache_free(steering->ftes_cache, fte);
-}
-
 static void del_sw_fte(struct fs_node *node)
 {
+       struct mlx5_flow_steering *steering = get_steering(node);
        struct mlx5_flow_group *fg;
        struct fs_fte *fte;
        int err;
@@ -553,8 +546,7 @@ static void del_sw_fte(struct fs_node *node)
                                     rhash_fte);
        WARN_ON(err);
        ida_simple_remove(&fg->fte_allocator, fte->index - fg->start_index);
-
-       call_rcu(&fte->rcu, del_sw_fte_rcu);
+       kmem_cache_free(steering->ftes_cache, fte);
 }
 
 static void del_hw_flow_group(struct fs_node *node)
@@ -1633,47 +1625,22 @@ static u64 matched_fgs_get_version(struct list_head *match_head)
 }
 
 static struct fs_fte *
-lookup_fte_for_write_locked(struct mlx5_flow_group *g, const u32 *match_value)
+lookup_fte_locked(struct mlx5_flow_group *g,
+                 const u32 *match_value,
+                 bool take_write)
 {
        struct fs_fte *fte_tmp;
 
-       nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
-
-       fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, match_value, rhash_fte);
-       if (!fte_tmp || !tree_get_node(&fte_tmp->node)) {
-               fte_tmp = NULL;
-               goto out;
-       }
-
-       if (!fte_tmp->node.active) {
-               tree_put_node(&fte_tmp->node, false);
-               fte_tmp = NULL;
-               goto out;
-       }
-       nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
-
-out:
-       up_write_ref_node(&g->node, false);
-       return fte_tmp;
-}
-
-static struct fs_fte *
-lookup_fte_for_read_locked(struct mlx5_flow_group *g, const u32 *match_value)
-{
-       struct fs_fte *fte_tmp;
-
-       if (!tree_get_node(&g->node))
-               return NULL;
-
-       rcu_read_lock();
-       fte_tmp = rhashtable_lookup(&g->ftes_hash, match_value, rhash_fte);
+       if (take_write)
+               nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
+       else
+               nested_down_read_ref_node(&g->node, FS_LOCK_PARENT);
+       fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, match_value,
+                                        rhash_fte);
        if (!fte_tmp || !tree_get_node(&fte_tmp->node)) {
-               rcu_read_unlock();
                fte_tmp = NULL;
                goto out;
        }
-       rcu_read_unlock();
-
        if (!fte_tmp->node.active) {
                tree_put_node(&fte_tmp->node, false);
                fte_tmp = NULL;
@@ -1681,19 +1648,12 @@ lookup_fte_for_read_locked(struct mlx5_flow_group *g, const u32 *match_value)
        }
 
        nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
-
 out:
-       tree_put_node(&g->node, false);
-       return fte_tmp;
-}
-
-static struct fs_fte *
-lookup_fte_locked(struct mlx5_flow_group *g, const u32 *match_value, bool write)
-{
-       if (write)
-               return lookup_fte_for_write_locked(g, match_value);
+       if (take_write)
+               up_write_ref_node(&g->node, false);
        else
-               return lookup_fte_for_read_locked(g, match_value);
+               up_read_ref_node(&g->node);
+       return fte_tmp;
 }
 
 static struct mlx5_flow_handle *
index e8cd997..c2621b9 100644 (file)
@@ -203,7 +203,6 @@ struct fs_fte {
        enum fs_fte_status              status;
        struct mlx5_fc                  *counter;
        struct rhash_head               hash;
-       struct rcu_head rcu;
        int                             modify_mask;
 };
 
index 173e2c1..cf7b8da 100644 (file)
@@ -1193,6 +1193,12 @@ int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
        if (err)
                goto err_load;
 
+       if (boot) {
+               err = mlx5_devlink_register(priv_to_devlink(dev), dev->device);
+               if (err)
+                       goto err_devlink_reg;
+       }
+
        if (mlx5_device_registered(dev)) {
                mlx5_attach_device(dev);
        } else {
@@ -1210,6 +1216,9 @@ out:
        return err;
 
 err_reg_dev:
+       if (boot)
+               mlx5_devlink_unregister(priv_to_devlink(dev));
+err_devlink_reg:
        mlx5_unload(dev);
 err_load:
        if (boot)
@@ -1347,10 +1356,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        request_module_nowait(MLX5_IB_MOD);
 
-       err = mlx5_devlink_register(devlink, &pdev->dev);
-       if (err)
-               goto clean_load;
-
        err = mlx5_crdump_enable(dev);
        if (err)
                dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
@@ -1358,9 +1363,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        pci_save_state(pdev);
        return 0;
 
-clean_load:
-       mlx5_unload_one(dev, true);
-
 err_load_one:
        mlx5_pci_close(dev);
 pci_init_err:
index 32e94d2..e4cff7a 100644 (file)
@@ -209,7 +209,7 @@ static void dr_rule_rehash_copy_ste_ctrl(struct mlx5dr_matcher *matcher,
        /* We need to copy the refcount since this ste
         * may have been traversed several times
         */
-       refcount_set(&new_ste->refcount, refcount_read(&cur_ste->refcount));
+       new_ste->refcount = cur_ste->refcount;
 
        /* Link old STEs rule_mem list to the new ste */
        mlx5dr_rule_update_rule_member(cur_ste, new_ste);
@@ -638,6 +638,9 @@ static int dr_rule_add_member(struct mlx5dr_rule_rx_tx *nic_rule,
        if (!rule_mem)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&rule_mem->list);
+       INIT_LIST_HEAD(&rule_mem->use_ste_list);
+
        rule_mem->ste = ste;
        list_add_tail(&rule_mem->list, &nic_rule->rule_members_list);
 
index a5a2669..c6c7d1d 100644 (file)
@@ -348,7 +348,7 @@ static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src)
        if (dst->next_htbl)
                dst->next_htbl->pointing_ste = dst;
 
-       refcount_set(&dst->refcount, refcount_read(&src->refcount));
+       dst->refcount = src->refcount;
 
        INIT_LIST_HEAD(&dst->rule_list);
        list_splice_tail_init(&src->rule_list, &dst->rule_list);
@@ -565,7 +565,7 @@ bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste)
 
 bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
 {
-       return !refcount_read(&ste->refcount);
+       return !ste->refcount;
 }
 
 /* Init one ste as a pattern for ste data array */
@@ -689,14 +689,14 @@ struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
        htbl->ste_arr = chunk->ste_arr;
        htbl->hw_ste_arr = chunk->hw_ste_arr;
        htbl->miss_list = chunk->miss_list;
-       refcount_set(&htbl->refcount, 0);
+       htbl->refcount = 0;
 
        for (i = 0; i < chunk->num_of_entries; i++) {
                struct mlx5dr_ste *ste = &htbl->ste_arr[i];
 
                ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
                ste->htbl = htbl;
-               refcount_set(&ste->refcount, 0);
+               ste->refcount = 0;
                INIT_LIST_HEAD(&ste->miss_list_node);
                INIT_LIST_HEAD(&htbl->miss_list[i]);
                INIT_LIST_HEAD(&ste->rule_list);
@@ -713,7 +713,7 @@ out_free_htbl:
 
 int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
 {
-       if (refcount_read(&htbl->refcount))
+       if (htbl->refcount)
                return -EBUSY;
 
        mlx5dr_icm_free_chunk(htbl->chunk);
index 290fe61..3fdf4a5 100644 (file)
@@ -123,7 +123,7 @@ struct mlx5dr_matcher_rx_tx;
 struct mlx5dr_ste {
        u8 *hw_ste;
        /* refcount: indicates the num of rules that using this ste */
-       refcount_t refcount;
+       u32 refcount;
 
        /* attached to the miss_list head at each htbl entry */
        struct list_head miss_list_node;
@@ -155,7 +155,7 @@ struct mlx5dr_ste_htbl_ctrl {
 struct mlx5dr_ste_htbl {
        u8 lu_type;
        u16 byte_mask;
-       refcount_t refcount;
+       u32 refcount;
        struct mlx5dr_icm_chunk *chunk;
        struct mlx5dr_ste *ste_arr;
        u8 *hw_ste_arr;
@@ -206,13 +206,14 @@ int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl);
 
 static inline void mlx5dr_htbl_put(struct mlx5dr_ste_htbl *htbl)
 {
-       if (refcount_dec_and_test(&htbl->refcount))
+       htbl->refcount--;
+       if (!htbl->refcount)
                mlx5dr_ste_htbl_free(htbl);
 }
 
 static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
 {
-       refcount_inc(&htbl->refcount);
+       htbl->refcount++;
 }
 
 /* STE utils */
@@ -254,14 +255,15 @@ static inline void mlx5dr_ste_put(struct mlx5dr_ste *ste,
                                  struct mlx5dr_matcher *matcher,
                                  struct mlx5dr_matcher_rx_tx *nic_matcher)
 {
-       if (refcount_dec_and_test(&ste->refcount))
+       ste->refcount--;
+       if (!ste->refcount)
                mlx5dr_ste_free(ste, matcher, nic_matcher);
 }
 
 /* initial as 0, increased only when ste appears in a new rule */
 static inline void mlx5dr_ste_get(struct mlx5dr_ste *ste)
 {
-       refcount_inc(&ste->refcount);
+       ste->refcount++;
 }
 
 void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
index 68cc673..46d43cf 100644 (file)
@@ -651,6 +651,13 @@ mlxsw_sp_qdisc_prio_graft(struct mlxsw_sp_port *mlxsw_sp_port,
            mlxsw_sp_port->tclass_qdiscs[tclass_num].handle == p->child_handle)
                return 0;
 
+       if (!p->child_handle) {
+               /* This is an invisible FIFO replacing the original Qdisc.
+                * Ignore it--the original Qdisc's destroy will follow.
+                */
+               return 0;
+       }
+
        /* See if the grafted qdisc is already offloaded on any tclass. If so,
         * unoffload it.
         */
index c56fcbb..52ed111 100644 (file)
@@ -2296,7 +2296,7 @@ __setup("sxgbeeth=", sxgbe_cmdline_opt);
 
 
 
-MODULE_DESCRIPTION("SAMSUNG 10G/2.5G/1G Ethernet PLATFORM driver");
+MODULE_DESCRIPTION("Samsung 10G/2.5G/1G Ethernet PLATFORM driver");
 
 MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
 MODULE_PARM_DESC(eee_timer, "EEE-LPI Default LS timer value");
index 1c8d84e..01b484c 100644 (file)
@@ -957,6 +957,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
                /* default */
                break;
        case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
                reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
                break;
        case PHY_INTERFACE_MODE_RMII:
index 26353ef..7d40760 100644 (file)
@@ -44,7 +44,7 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
         * rate, which then uses the auto-reparenting feature of the
         * clock driver, and enabling/disabling the clock.
         */
-       if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+       if (phy_interface_mode_is_rgmii(gmac->interface)) {
                clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
                clk_prepare_enable(gmac->tx_clk);
                gmac->clk_enabled = 1;
index 6f51a26..80d59b7 100644 (file)
@@ -106,6 +106,7 @@ MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_DEBUG_FS
+static const struct net_device_ops stmmac_netdev_ops;
 static void stmmac_init_fs(struct net_device *dev);
 static void stmmac_exit_fs(struct net_device *dev);
 #endif
@@ -4256,6 +4257,34 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(stmmac_dma_cap);
 
+/* Use network device events to rename debugfs file entries.
+ */
+static int stmmac_device_event(struct notifier_block *unused,
+                              unsigned long event, void *ptr)
+{
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       if (dev->netdev_ops != &stmmac_netdev_ops)
+               goto done;
+
+       switch (event) {
+       case NETDEV_CHANGENAME:
+               if (priv->dbgfs_dir)
+                       priv->dbgfs_dir = debugfs_rename(stmmac_fs_dir,
+                                                        priv->dbgfs_dir,
+                                                        stmmac_fs_dir,
+                                                        dev->name);
+               break;
+       }
+done:
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block stmmac_notifier = {
+       .notifier_call = stmmac_device_event,
+};
+
 static void stmmac_init_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
@@ -4270,12 +4299,15 @@ static void stmmac_init_fs(struct net_device *dev)
        /* Entry to report the DMA HW features */
        debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev,
                            &stmmac_dma_cap_fops);
+
+       register_netdevice_notifier(&stmmac_notifier);
 }
 
 static void stmmac_exit_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
+       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(priv->dbgfs_dir);
 }
 #endif /* CONFIG_DEBUG_FS */
index cc8d7e7..4775f49 100644 (file)
@@ -320,7 +320,7 @@ out:
 static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
                         struct device_node *np, struct device *dev)
 {
-       bool mdio = false;
+       bool mdio = !of_phy_is_fixed_link(np);
        static const struct of_device_id need_mdio_ids[] = {
                { .compatible = "snps,dwc-qos-ethernet-4.10" },
                {},
index fca471e..f6222ad 100644 (file)
@@ -813,7 +813,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
        lock_sock(sock->sk);
        if (sock->sk->sk_user_data) {
                sk = ERR_PTR(-EBUSY);
-               goto out_sock;
+               goto out_rel_sock;
        }
 
        sk = sock->sk;
@@ -826,8 +826,9 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
 
        setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
 
-out_sock:
+out_rel_sock:
        release_sock(sock->sk);
+out_sock:
        sockfd_put(sock);
        return sk;
 }
index 05631d9..747c054 100644 (file)
@@ -259,7 +259,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
                              struct net_device *src,
                              enum macvlan_mode mode)
 {
-       const struct ethhdr *eth = eth_hdr(skb);
+       const struct ethhdr *eth = skb_eth_hdr(skb);
        const struct macvlan_dev *vlan;
        struct sk_buff *nskb;
        unsigned int i;
index 1585eeb..ee7a718 100644 (file)
@@ -566,6 +566,9 @@ static int phylink_register_sfp(struct phylink *pl,
        struct sfp_bus *bus;
        int ret;
 
+       if (!fwnode)
+               return 0;
+
        bus = sfp_bus_find_fwnode(fwnode);
        if (IS_ERR(bus)) {
                ret = PTR_ERR(bus);
index f940dc6..fb47810 100644 (file)
@@ -2724,11 +2724,6 @@ static int lan78xx_stop(struct net_device *net)
        return 0;
 }
 
-static int lan78xx_linearize(struct sk_buff *skb)
-{
-       return skb_linearize(skb);
-}
-
 static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev,
                                       struct sk_buff *skb, gfp_t flags)
 {
@@ -2740,8 +2735,10 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev,
                return NULL;
        }
 
-       if (lan78xx_linearize(skb) < 0)
+       if (skb_linearize(skb)) {
+               dev_kfree_skb_any(skb);
                return NULL;
+       }
 
        tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_;
 
index 3ec6b50..1c5159d 100644 (file)
@@ -2541,7 +2541,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                ndst = &rt->dst;
                skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM);
 
-               tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+               tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
                ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
                err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
                                      vni, md, flags, udp_sum);
@@ -2581,7 +2581,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 
                skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM);
 
-               tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+               tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
                ttl = ttl ? : ip6_dst_hoplimit(ndst);
                skb_scrub_packet(skb, xnet);
                err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
index e2e679a..77ccf36 100644 (file)
@@ -708,7 +708,7 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb,
 
                                        spin_lock_irqsave(&sdla_lock, flags);
                                        SDLA_WINDOW(dev, addr);
-                                       pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+                                       pbuf = (void *)(dev->mem_start + (addr & SDLA_ADDR_MASK));
                                        __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
                                        SDLA_WINDOW(dev, addr);
                                        pbuf->opp_flag = 1;
index 667f18f..5dc32b7 100644 (file)
@@ -222,6 +222,8 @@ static blk_status_t nvme_error_status(u16 status)
        case NVME_SC_CAP_EXCEEDED:
                return BLK_STS_NOSPC;
        case NVME_SC_LBA_RANGE:
+       case NVME_SC_CMD_INTERRUPTED:
+       case NVME_SC_NS_NOT_READY:
                return BLK_STS_TARGET;
        case NVME_SC_BAD_ATTRIBUTES:
        case NVME_SC_ONCS_NOT_SUPPORTED:
index 56c21b5..72a7e41 100644 (file)
@@ -24,6 +24,16 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd)
        return len;
 }
 
+static u32 nvmet_feat_data_len(struct nvmet_req *req, u32 cdw10)
+{
+       switch (cdw10 & 0xff) {
+       case NVME_FEAT_HOST_ID:
+               return sizeof(req->sq->ctrl->hostid);
+       default:
+               return 0;
+       }
+}
+
 u64 nvmet_get_log_page_offset(struct nvme_command *cmd)
 {
        return le64_to_cpu(cmd->get_log_page.lpo);
@@ -778,7 +788,7 @@ static void nvmet_execute_get_features(struct nvmet_req *req)
        u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
        u16 status = 0;
 
-       if (!nvmet_check_data_len(req, 0))
+       if (!nvmet_check_data_len(req, nvmet_feat_data_len(req, cdw10)))
                return;
 
        switch (cdw10 & 0xff) {
index ead06c6..12e71a3 100644 (file)
@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state {
 enum cpcap_gpio_mode {
        CPCAP_DM_DP,
        CPCAP_MDM_RX_TX,
-       CPCAP_UNKNOWN,
+       CPCAP_UNKNOWN_DISABLED, /* Seems to disable USB lines */
        CPCAP_OTG_DM_DP,
 };
 
@@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
        struct iio_channel *id;
        struct regulator *vusb;
        atomic_t active;
+       unsigned int vbus_provider:1;
+       unsigned int docked:1;
 };
 
 static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
@@ -207,6 +209,19 @@ static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
 static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
 static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
 
+static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
+                                      enum musb_vbus_id_status status)
+{
+       int error;
+
+       error = musb_mailbox(status);
+       if (!error)
+               return;
+
+       dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
+               __func__, error);
+}
+
 static void cpcap_usb_detect(struct work_struct *work)
 {
        struct cpcap_phy_ddata *ddata;
@@ -220,16 +235,66 @@ static void cpcap_usb_detect(struct work_struct *work)
        if (error)
                return;
 
-       if (s.id_ground) {
-               dev_dbg(ddata->dev, "id ground, USB host mode\n");
+       vbus = cpcap_usb_vbus_valid(ddata);
+
+       /* We need to kick the VBUS as USB A-host */
+       if (s.id_ground && ddata->vbus_provider) {
+               dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
+
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+                                          CPCAP_BIT_VBUSSTBY_EN |
+                                          CPCAP_BIT_VBUSEN_SPI,
+                                          CPCAP_BIT_VBUSEN_SPI);
+               if (error)
+                       goto out_err;
+
+               return;
+       }
+
+       if (vbus && s.id_ground && ddata->docked) {
+               dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");
+
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               return;
+       }
+
+       /* No VBUS needed with docks */
+       if (vbus && s.id_ground && !ddata->vbus_provider) {
+               dev_dbg(ddata->dev, "connected to a dock\n");
+
+               ddata->docked = true;
+
                error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
 
-               error = musb_mailbox(MUSB_ID_GROUND);
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               /*
+                * Force check state again after musb has reoriented,
+                * otherwise devices won't enumerate after loading PHY
+                * driver.
+                */
+               schedule_delayed_work(&ddata->detect_work,
+                                     msecs_to_jiffies(1000));
+
+               return;
+       }
+
+       if (s.id_ground && !ddata->docked) {
+               dev_dbg(ddata->dev, "id ground, USB host mode\n");
+
+               ddata->vbus_provider = true;
+
+               error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
 
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
                error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
                                           CPCAP_BIT_VBUSSTBY_EN |
                                           CPCAP_BIT_VBUSEN_SPI,
@@ -248,43 +313,26 @@ static void cpcap_usb_detect(struct work_struct *work)
 
        vbus = cpcap_usb_vbus_valid(ddata);
 
+       /* Otherwise assume we're connected to a USB host */
        if (vbus) {
-               /* Are we connected to a docking station with vbus? */
-               if (s.id_ground) {
-                       dev_dbg(ddata->dev, "connected to a dock\n");
-
-                       /* No VBUS needed with docks */
-                       error = cpcap_usb_set_usb_mode(ddata);
-                       if (error)
-                               goto out_err;
-                       error = musb_mailbox(MUSB_ID_GROUND);
-                       if (error)
-                               goto out_err;
-
-                       return;
-               }
-
-               /* Otherwise assume we're connected to a USB host */
                dev_dbg(ddata->dev, "connected to USB host\n");
                error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
-               error = musb_mailbox(MUSB_VBUS_VALID);
-               if (error)
-                       goto out_err;
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
 
                return;
        }
 
+       ddata->vbus_provider = false;
+       ddata->docked = false;
+       cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
+
        /* Default to debug UART mode */
        error = cpcap_usb_set_uart_mode(ddata);
        if (error)
                goto out_err;
 
-       error = musb_mailbox(MUSB_VBUS_OFF);
-       if (error)
-               goto out_err;
-
        dev_dbg(ddata->dev, "set UART mode\n");
 
        return;
@@ -376,7 +424,8 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
 {
        int error;
 
-       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+       /* Disable lines to prevent glitches from waking up mdm6600 */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
        if (error)
                goto out_err;
 
@@ -403,6 +452,11 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
+       /* Enable UART mode */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+       if (error)
+               goto out_err;
+
        return 0;
 
 out_err:
@@ -415,7 +469,8 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
 {
        int error;
 
-       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+       /* Disable lines to prevent glitches from waking up mdm6600 */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
        if (error)
                return error;
 
@@ -434,12 +489,6 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
-       error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
-                                  CPCAP_BIT_USBXCVREN,
-                                  CPCAP_BIT_USBXCVREN);
-       if (error)
-               goto out_err;
-
        error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
                                   CPCAP_BIT_PU_SPI |
                                   CPCAP_BIT_DMPD_SPI |
@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
+       /* Enable USB mode */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+       if (error)
+               goto out_err;
+
        return 0;
 
 out_err:
@@ -649,9 +703,7 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev)
        if (error)
                dev_err(ddata->dev, "could not set UART mode\n");
 
-       error = musb_mailbox(MUSB_VBUS_OFF);
-       if (error)
-               dev_err(ddata->dev, "could not set mailbox\n");
+       cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
 
        usb_remove_phy(&ddata->phy);
        cancel_delayed_work_sync(&ddata->detect_work);
index ee184d5..f20524f 100644 (file)
@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work)
        struct phy_mdm6600 *ddata;
        struct device *dev;
        DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES);
-       int error, i, val = 0;
+       int error;
 
        ddata = container_of(work, struct phy_mdm6600, status_work.work);
        dev = ddata->dev;
@@ -212,16 +212,11 @@ static void phy_mdm6600_status(struct work_struct *work)
        if (error)
                return;
 
-       for (i = 0; i < PHY_MDM6600_NR_STATUS_LINES; i++) {
-               val |= test_bit(i, values) << i;
-               dev_dbg(ddata->dev, "XXX %s: i: %i values[i]: %i val: %i\n",
-                       __func__, i, test_bit(i, values), val);
-       }
-       ddata->status = values[0];
+       ddata->status = values[0] & ((1 << PHY_MDM6600_NR_STATUS_LINES) - 1);
 
        dev_info(dev, "modem status: %i %s\n",
                 ddata->status,
-                phy_mdm6600_status_name[ddata->status & 7]);
+                phy_mdm6600_status_name[ddata->status]);
        complete(&ddata->ack);
 }
 
index 091e203..66f9172 100644 (file)
@@ -66,7 +66,7 @@
 /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
 #define CLAMP_EN                               BIT(0) /* enables i/o clamp_n */
 
-#define PHY_INIT_COMPLETE_TIMEOUT              1000
+#define PHY_INIT_COMPLETE_TIMEOUT              10000
 #define POWER_DOWN_DELAY_US_MIN                        10
 #define POWER_DOWN_DELAY_US_MAX                        11
 
index 2b97fb1..9ca20c9 100644 (file)
@@ -603,6 +603,8 @@ static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw,
 {
        const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+       rate = (rate / 1000) * 1000;
+
        for (; cfg->pixclock != 0; cfg++)
                if (cfg->pixclock == rate && !cfg->fracdiv)
                        break;
@@ -755,6 +757,8 @@ static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
 {
        const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+       rate = (rate / 1000) * 1000;
+
        for (; cfg->pixclock != 0; cfg++)
                if (cfg->pixclock == rate)
                        break;
index f1806fd..530426a 100644 (file)
@@ -2,6 +2,7 @@
 config PINCTRL_LOCHNAGAR
        tristate "Cirrus Logic Lochnagar pinctrl driver"
        depends on MFD_LOCHNAGAR
+       select GPIOLIB
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
index 3c80828..bbc919b 100644 (file)
@@ -441,6 +441,7 @@ static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
                return ret;
 
        meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
+       bit = bit << 1;
 
        ret = regmap_read(pc->reg_ds, reg, &val);
        if (ret)
index a67701e..2e5b6a6 100644 (file)
@@ -1295,6 +1295,9 @@ struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv)
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        int ret;
 
+       if (!rapl_defaults)
+               return ERR_PTR(-ENODEV);
+
        rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
        if (!rp)
                return ERR_PTR(-ENOMEM);
index 989506b..16f0c85 100644 (file)
@@ -413,10 +413,13 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
                int i;
 
                for (i = 0; i < rate_count; i++) {
-                       if (ramp <= slew_rates[i])
-                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
-                       else
+                       if (ramp > slew_rates[i])
                                break;
+
+                       if (id == AXP20X_DCDC2)
+                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(i);
+                       else
+                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
                }
 
                if (cfg == 0xff) {
@@ -605,7 +608,7 @@ static const struct regulator_desc axp22x_regulators[] = {
                 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
        AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
                 AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
-                AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
+                AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
        AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
                 AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
                 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
index ec76402..5bf8a2d 100644 (file)
@@ -101,7 +101,6 @@ static const struct regulator_ops bd70528_ldo_ops = {
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_time_sel = regulator_set_voltage_time_sel,
-       .set_ramp_delay = bd70528_set_ramp_delay,
 };
 
 static const struct regulator_ops bd70528_led_ops = {
index df2829d..2ecd875 100644 (file)
@@ -172,20 +172,7 @@ int mc146818_set_time(struct rtc_time *time)
        save_control = CMOS_READ(RTC_CONTROL);
        CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-
-#ifdef CONFIG_X86
-       if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-            boot_cpu_data.x86 == 0x17) ||
-            boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
-               CMOS_WRITE((save_freq_select & (~RTC_DIV_RESET2)),
-                       RTC_FREQ_SELECT);
-               save_freq_select &= ~RTC_DIV_RESET2;
-       } else
-               CMOS_WRITE((save_freq_select | RTC_DIV_RESET2),
-                       RTC_FREQ_SELECT);
-#else
-       CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT);
-#endif
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 
 #ifdef CONFIG_MACH_DECSTATION
        CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
index 5249fc9..9135e21 100644 (file)
@@ -47,7 +47,7 @@ static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data)
                irqen = irqsta & ~RTC_IRQ_EN_AL;
                mutex_lock(&rtc->lock);
                if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
-                                irqen) < 0)
+                                irqen) == 0)
                        mtk_rtc_write_trigger(rtc);
                mutex_unlock(&rtc->lock);
 
@@ -169,12 +169,12 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
        mutex_unlock(&rtc->lock);
 
-       tm->tm_sec = data[RTC_OFFSET_SEC];
-       tm->tm_min = data[RTC_OFFSET_MIN];
-       tm->tm_hour = data[RTC_OFFSET_HOUR];
-       tm->tm_mday = data[RTC_OFFSET_DOM];
-       tm->tm_mon = data[RTC_OFFSET_MTH];
-       tm->tm_year = data[RTC_OFFSET_YEAR];
+       tm->tm_sec = data[RTC_OFFSET_SEC] & RTC_AL_SEC_MASK;
+       tm->tm_min = data[RTC_OFFSET_MIN] & RTC_AL_MIN_MASK;
+       tm->tm_hour = data[RTC_OFFSET_HOUR] & RTC_AL_HOU_MASK;
+       tm->tm_mday = data[RTC_OFFSET_DOM] & RTC_AL_DOM_MASK;
+       tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK;
+       tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK;
 
        tm->tm_year += RTC_MIN_YEAR_OFFSET;
        tm->tm_mon--;
@@ -195,14 +195,25 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        tm->tm_year -= RTC_MIN_YEAR_OFFSET;
        tm->tm_mon++;
 
-       data[RTC_OFFSET_SEC] = tm->tm_sec;
-       data[RTC_OFFSET_MIN] = tm->tm_min;
-       data[RTC_OFFSET_HOUR] = tm->tm_hour;
-       data[RTC_OFFSET_DOM] = tm->tm_mday;
-       data[RTC_OFFSET_MTH] = tm->tm_mon;
-       data[RTC_OFFSET_YEAR] = tm->tm_year;
-
        mutex_lock(&rtc->lock);
+       ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+                              data, RTC_OFFSET_COUNT);
+       if (ret < 0)
+               goto exit;
+
+       data[RTC_OFFSET_SEC] = ((data[RTC_OFFSET_SEC] & ~(RTC_AL_SEC_MASK)) |
+                               (tm->tm_sec & RTC_AL_SEC_MASK));
+       data[RTC_OFFSET_MIN] = ((data[RTC_OFFSET_MIN] & ~(RTC_AL_MIN_MASK)) |
+                               (tm->tm_min & RTC_AL_MIN_MASK));
+       data[RTC_OFFSET_HOUR] = ((data[RTC_OFFSET_HOUR] & ~(RTC_AL_HOU_MASK)) |
+                               (tm->tm_hour & RTC_AL_HOU_MASK));
+       data[RTC_OFFSET_DOM] = ((data[RTC_OFFSET_DOM] & ~(RTC_AL_DOM_MASK)) |
+                               (tm->tm_mday & RTC_AL_DOM_MASK));
+       data[RTC_OFFSET_MTH] = ((data[RTC_OFFSET_MTH] & ~(RTC_AL_MTH_MASK)) |
+                               (tm->tm_mon & RTC_AL_MTH_MASK));
+       data[RTC_OFFSET_YEAR] = ((data[RTC_OFFSET_YEAR] & ~(RTC_AL_YEA_MASK)) |
+                               (tm->tm_year & RTC_AL_YEA_MASK));
+
        if (alm->enabled) {
                ret = regmap_bulk_write(rtc->regmap,
                                        rtc->addr_base + RTC_AL_SEC,
index 8dcd20b..852f5f3 100644 (file)
@@ -379,6 +379,22 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node)
 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
                      sun50i_h6_rtc_clk_init);
 
+/*
+ * The R40 user manual is self-conflicting on whether the prescaler is
+ * fixed or configurable. The clock diagram shows it as fixed, but there
+ * is also a configurable divider in the RTC block.
+ */
+static const struct sun6i_rtc_clk_data sun8i_r40_rtc_data = {
+       .rc_osc_rate = 16000000,
+       .fixed_prescaler = 512,
+};
+static void __init sun8i_r40_rtc_clk_init(struct device_node *node)
+{
+       sun6i_rtc_clk_init(node, &sun8i_r40_rtc_data);
+}
+CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc",
+                     sun8i_r40_rtc_clk_init);
+
 static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
        .rc_osc_rate = 32000,
        .has_out_clk = 1,
index a9ffff3..a506939 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
-#include <asm/sifive_l2_cache.h>
+#include <soc/sifive/sifive_l2_cache.h>
 
 #define SIFIVE_L2_DIRECCFIX_LOW 0x100
 #define SIFIVE_L2_DIRECCFIX_HIGH 0x104
index 76d6b94..5a25da3 100644 (file)
@@ -172,9 +172,11 @@ static inline u32 rx_max(struct dw_spi *dws)
 
 static void dw_writer(struct dw_spi *dws)
 {
-       u32 max = tx_max(dws);
+       u32 max;
        u16 txw = 0;
 
+       spin_lock(&dws->buf_lock);
+       max = tx_max(dws);
        while (max--) {
                /* Set the tx word if the transfer's original "tx" is not null */
                if (dws->tx_end - dws->len) {
@@ -186,13 +188,16 @@ static void dw_writer(struct dw_spi *dws)
                dw_write_io_reg(dws, DW_SPI_DR, txw);
                dws->tx += dws->n_bytes;
        }
+       spin_unlock(&dws->buf_lock);
 }
 
 static void dw_reader(struct dw_spi *dws)
 {
-       u32 max = rx_max(dws);
+       u32 max;
        u16 rxw;
 
+       spin_lock(&dws->buf_lock);
+       max = rx_max(dws);
        while (max--) {
                rxw = dw_read_io_reg(dws, DW_SPI_DR);
                /* Care rx only if the transfer's original "rx" is not null */
@@ -204,6 +209,7 @@ static void dw_reader(struct dw_spi *dws)
                }
                dws->rx += dws->n_bytes;
        }
+       spin_unlock(&dws->buf_lock);
 }
 
 static void int_error_stop(struct dw_spi *dws, const char *msg)
@@ -276,18 +282,20 @@ static int dw_spi_transfer_one(struct spi_controller *master,
 {
        struct dw_spi *dws = spi_controller_get_devdata(master);
        struct chip_data *chip = spi_get_ctldata(spi);
+       unsigned long flags;
        u8 imask = 0;
        u16 txlevel = 0;
        u32 cr0;
        int ret;
 
        dws->dma_mapped = 0;
-
+       spin_lock_irqsave(&dws->buf_lock, flags);
        dws->tx = (void *)transfer->tx_buf;
        dws->tx_end = dws->tx + transfer->len;
        dws->rx = transfer->rx_buf;
        dws->rx_end = dws->rx + transfer->len;
        dws->len = transfer->len;
+       spin_unlock_irqrestore(&dws->buf_lock, flags);
 
        spi_enable_chip(dws, 0);
 
@@ -471,6 +479,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
        dws->type = SSI_MOTO_SPI;
        dws->dma_inited = 0;
        dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
+       spin_lock_init(&dws->buf_lock);
 
        spi_controller_set_devdata(master, dws);
 
index 38c7de1..1bf5713 100644 (file)
@@ -119,6 +119,7 @@ struct dw_spi {
        size_t                  len;
        void                    *tx;
        void                    *tx_end;
+       spinlock_t              buf_lock;
        void                    *rx;
        void                    *rx_end;
        int                     dma_mapped;
index 442cff7..8428b69 100644 (file)
@@ -185,6 +185,7 @@ struct fsl_dspi {
        struct spi_transfer                     *cur_transfer;
        struct spi_message                      *cur_msg;
        struct chip_data                        *cur_chip;
+       size_t                                  progress;
        size_t                                  len;
        const void                              *tx;
        void                                    *rx;
@@ -586,21 +587,14 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi)
        dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT;
 
        if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) {
-               /* Write two TX FIFO entries first, and then the corresponding
-                * CMD FIFO entry.
+               /* Write the CMD FIFO entry first, and then the two
+                * corresponding TX FIFO entries.
                 */
                u32 data = dspi_pop_tx(dspi);
 
-               if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE) {
-                       /* LSB */
-                       tx_fifo_write(dspi, data & 0xFFFF);
-                       tx_fifo_write(dspi, data >> 16);
-               } else {
-                       /* MSB */
-                       tx_fifo_write(dspi, data >> 16);
-                       tx_fifo_write(dspi, data & 0xFFFF);
-               }
                cmd_fifo_write(dspi);
+               tx_fifo_write(dspi, data & 0xFFFF);
+               tx_fifo_write(dspi, data >> 16);
        } else {
                /* Write one entry to both TX FIFO and CMD FIFO
                 * simultaneously.
@@ -658,7 +652,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
        u32 spi_tcr;
 
        spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer,
-                               dspi->tx - dspi->bytes_per_word, !dspi->irq);
+                               dspi->progress, !dspi->irq);
 
        /* Get transfer counter (in number of SPI transfers). It was
         * reset to 0 when transfer(s) were started.
@@ -667,6 +661,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
        spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
        /* Update total number of bytes that were transferred */
        msg->actual_length += spi_tcnt * dspi->bytes_per_word;
+       dspi->progress += spi_tcnt;
 
        trans_mode = dspi->devtype_data->trans_mode;
        if (trans_mode == DSPI_EOQ_MODE)
@@ -679,7 +674,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
                return 0;
 
        spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
-                              dspi->tx, !dspi->irq);
+                              dspi->progress, !dspi->irq);
 
        if (trans_mode == DSPI_EOQ_MODE)
                dspi_eoq_write(dspi);
@@ -768,6 +763,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
                dspi->rx = transfer->rx_buf;
                dspi->rx_end = dspi->rx + transfer->len;
                dspi->len = transfer->len;
+               dspi->progress = 0;
                /* Validated transfer specific frame size (defaults applied) */
                dspi->bits_per_word = transfer->bits_per_word;
                if (transfer->bits_per_word <= 8)
@@ -789,7 +785,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
                                     SPI_CTARE_DTCP(1));
 
                spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
-                                      dspi->tx, !dspi->irq);
+                                      dspi->progress, !dspi->irq);
 
                trans_mode = dspi->devtype_data->trans_mode;
                switch (trans_mode) {
index 47cde18..ce9b301 100644 (file)
@@ -290,25 +290,32 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
        }
 }
 
-static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
+static void uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv *priv,
+                                           unsigned int threshold)
 {
-       unsigned int fifo_threshold, fill_bytes;
        u32 val;
 
-       fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
-                               bytes_per_word(priv->bits_per_word));
-       fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
-
-       fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
-
-       /* set fifo threshold */
        val = readl(priv->base + SSI_FC);
        val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
-       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
-       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
+       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, SSI_FIFO_DEPTH - threshold);
+       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, threshold);
        writel(val, priv->base + SSI_FC);
+}
+
+static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
+{
+       unsigned int fifo_threshold, fill_words;
+       unsigned int bpw = bytes_per_word(priv->bits_per_word);
+
+       fifo_threshold = DIV_ROUND_UP(priv->rx_bytes, bpw);
+       fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
+
+       uniphier_spi_set_fifo_threshold(priv, fifo_threshold);
+
+       fill_words = fifo_threshold -
+               DIV_ROUND_UP(priv->rx_bytes - priv->tx_bytes, bpw);
 
-       while (fill_bytes--)
+       while (fill_words--)
                uniphier_spi_send(priv);
 }
 
index 5e4c453..8994545 100644 (file)
@@ -1499,8 +1499,7 @@ static void spi_pump_messages(struct kthread_work *work)
  *                         advances its @tx buffer pointer monotonically.
  * @ctlr: Pointer to the spi_controller structure of the driver
  * @xfer: Pointer to the transfer being timestamped
- * @tx: Pointer to the current word within the xfer->tx_buf that the driver is
- *     preparing to transmit right now.
+ * @progress: How many words (not bytes) have been transferred so far
  * @irqs_off: If true, will disable IRQs and preemption for the duration of the
  *           transfer, for less jitter in time measurement. Only compatible
  *           with PIO drivers. If true, must follow up with
@@ -1510,21 +1509,19 @@ static void spi_pump_messages(struct kthread_work *work)
  */
 void spi_take_timestamp_pre(struct spi_controller *ctlr,
                            struct spi_transfer *xfer,
-                           const void *tx, bool irqs_off)
+                           size_t progress, bool irqs_off)
 {
-       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
-
        if (!xfer->ptp_sts)
                return;
 
        if (xfer->timestamped_pre)
                return;
 
-       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_pre * bytes_per_word))
+       if (progress < xfer->ptp_sts_word_pre)
                return;
 
        /* Capture the resolution of the timestamp */
-       xfer->ptp_sts_word_pre = (tx - xfer->tx_buf) / bytes_per_word;
+       xfer->ptp_sts_word_pre = progress;
 
        xfer->timestamped_pre = true;
 
@@ -1546,23 +1543,20 @@ EXPORT_SYMBOL_GPL(spi_take_timestamp_pre);
  *                          timestamped.
  * @ctlr: Pointer to the spi_controller structure of the driver
  * @xfer: Pointer to the transfer being timestamped
- * @tx: Pointer to the current word within the xfer->tx_buf that the driver has
- *     just transmitted.
+ * @progress: How many words (not bytes) have been transferred so far
  * @irqs_off: If true, will re-enable IRQs and preemption for the local CPU.
  */
 void spi_take_timestamp_post(struct spi_controller *ctlr,
                             struct spi_transfer *xfer,
-                            const void *tx, bool irqs_off)
+                            size_t progress, bool irqs_off)
 {
-       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
-
        if (!xfer->ptp_sts)
                return;
 
        if (xfer->timestamped_post)
                return;
 
-       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_post * bytes_per_word))
+       if (progress < xfer->ptp_sts_word_post)
                return;
 
        ptp_read_system_postts(xfer->ptp_sts);
@@ -1573,7 +1567,7 @@ void spi_take_timestamp_post(struct spi_controller *ctlr,
        }
 
        /* Capture the resolution of the timestamp */
-       xfer->ptp_sts_word_post = (tx - xfer->tx_buf) / bytes_per_word;
+       xfer->ptp_sts_word_post = progress;
 
        xfer->timestamped_post = true;
 }
index dbff0f7..ddc0dc9 100644 (file)
@@ -46,8 +46,8 @@
 #define PCI171X_RANGE_UNI      BIT(4)
 #define PCI171X_RANGE_GAIN(x)  (((x) & 0x7) << 0)
 #define PCI171X_MUX_REG                0x04    /* W:   A/D multiplexor control */
-#define PCI171X_MUX_CHANH(x)   (((x) & 0xf) << 8)
-#define PCI171X_MUX_CHANL(x)   (((x) & 0xf) << 0)
+#define PCI171X_MUX_CHANH(x)   (((x) & 0xff) << 8)
+#define PCI171X_MUX_CHANL(x)   (((x) & 0xff) << 0)
 #define PCI171X_MUX_CHAN(x)    (PCI171X_MUX_CHANH(x) | PCI171X_MUX_CHANL(x))
 #define PCI171X_STATUS_REG     0x06    /* R:   status register */
 #define PCI171X_STATUS_IRQ     BIT(11) /* 1=IRQ occurred */
index a7cac07..b5d42f4 100644 (file)
@@ -37,6 +37,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
        {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
        {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+       {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
        {}      /* Terminating entry */
index 8d19ae7..4e651b6 100644 (file)
@@ -449,8 +449,8 @@ int vnt_vt3184_init(struct vnt_private *priv)
 
        memcpy(array, addr, length);
 
-       ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
-                             MESSAGE_REQUEST_BBREG, length, array);
+       ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
+                                    MESSAGE_REQUEST_BBREG, length, array);
        if (ret)
                goto end;
 
index 56cd77f..7958fc1 100644 (file)
@@ -719,7 +719,7 @@ end:
  */
 int vnt_radio_power_on(struct vnt_private *priv)
 {
-       int ret = true;
+       int ret = 0;
 
        vnt_exit_deep_sleep(priv);
 
index 6074ced..50e1c89 100644 (file)
@@ -259,6 +259,7 @@ struct vnt_private {
        u8 mac_hw;
        /* netdev */
        struct usb_device *usb;
+       struct usb_interface *intf;
 
        u64 tsf_time;
        u8 rx_rate;
index 4ac85ec..9cb924c 100644 (file)
@@ -949,7 +949,7 @@ static const struct ieee80211_ops vnt_mac_ops = {
 
 int vnt_init(struct vnt_private *priv)
 {
-       if (!(vnt_init_registers(priv)))
+       if (vnt_init_registers(priv))
                return -EAGAIN;
 
        SET_IEEE80211_PERM_ADDR(priv->hw, priv->permanent_net_addr);
@@ -992,6 +992,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
        priv = hw->priv;
        priv->hw = hw;
        priv->usb = udev;
+       priv->intf = intf;
 
        vnt_set_options(priv);
 
index d3304df..d977d47 100644 (file)
@@ -59,7 +59,9 @@ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
 
        kfree(usb_buffer);
 
-       if (ret >= 0 && ret < (int)length)
+       if (ret == (int)length)
+               ret = 0;
+       else
                ret = -EIO;
 
 end_unlock:
@@ -74,6 +76,23 @@ int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
                               reg_off, reg, sizeof(u8), &data);
 }
 
+int vnt_control_out_blocks(struct vnt_private *priv,
+                          u16 block, u8 reg, u16 length, u8 *data)
+{
+       int ret = 0, i;
+
+       for (i = 0; i < length; i += block) {
+               u16 len = min_t(int, length - i, block);
+
+               ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
+                                     i, reg, len, data + i);
+               if (ret)
+                       goto end;
+       }
+end:
+       return ret;
+}
+
 int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
                   u16 index, u16 length, u8 *buffer)
 {
@@ -103,7 +122,9 @@ int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 
        kfree(usb_buffer);
 
-       if (ret >= 0 && ret < (int)length)
+       if (ret == (int)length)
+               ret = 0;
+       else
                ret = -EIO;
 
 end_unlock:
index 95147ec..b65d9c0 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "device.h"
 
+#define VNT_REG_BLOCK_SIZE     64
+
 int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
                    u16 index, u16 length, u8 *buffer);
 int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
@@ -26,6 +28,9 @@ int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
 int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
 
+int vnt_control_out_blocks(struct vnt_private *priv,
+                          u16 block, u8 reg, u16 len, u8 *data);
+
 int vnt_start_interrupt_urb(struct vnt_private *priv);
 int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb);
 int vnt_tx_context(struct vnt_private *priv,
index 3eb2f11..2c5250c 100644 (file)
@@ -99,6 +99,7 @@ void vnt_run_command(struct work_struct *work)
                if (vnt_init(priv)) {
                        /* If fail all ends TODO retry */
                        dev_err(&priv->usb->dev, "failed to start\n");
+                       usb_set_intfdata(priv->intf, NULL);
                        ieee80211_free_hw(priv->hw);
                        return;
                }
index 015e7d2..0e7cf52 100644 (file)
@@ -110,6 +110,9 @@ static int tsens_register(struct tsens_priv *priv)
        irq = platform_get_irq_byname(pdev, "uplow");
        if (irq < 0) {
                ret = irq;
+               /* For old DTs with no IRQ defined */
+               if (irq == -ENXIO)
+                       ret = 0;
                goto err_put_device;
        }
 
index 226adee..ce5309d 100644 (file)
@@ -663,6 +663,12 @@ static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
        return AE_OK;
 }
 
+static const struct acpi_device_id serdev_acpi_devices_blacklist[] = {
+       { "INT3511", 0 },
+       { "INT3512", 0 },
+       { },
+};
+
 static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
                                          void *data, void **return_value)
 {
@@ -675,6 +681,10 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
        if (acpi_device_enumerated(adev))
                return AE_OK;
 
+       /* Skip if black listed */
+       if (!acpi_match_device_ids(adev, serdev_acpi_devices_blacklist))
+               return AE_OK;
+
        if (acpi_serdev_check_resources(ctrl, adev))
                return AE_OK;
 
index 5023c85..044c3cb 100644 (file)
@@ -89,8 +89,7 @@ void tty_port_link_device(struct tty_port *port,
 {
        if (WARN_ON(index >= driver->num))
                return;
-       if (!driver->ports[index])
-               driver->ports[index] = port;
+       driver->ports[index] = port;
 }
 EXPORT_SYMBOL_GPL(tty_port_link_device);
 
index 4c1e755..02f6ca2 100644 (file)
@@ -1375,13 +1375,10 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
  */
 static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
 {
-       struct cdns3_device *priv_dev;
-       struct cdns3 *cdns = data;
+       struct cdns3_device *priv_dev = data;
        irqreturn_t ret = IRQ_NONE;
        u32 reg;
 
-       priv_dev = cdns->gadget_dev;
-
        /* check USB device interrupt */
        reg = readl(&priv_dev->regs->usb_ists);
        if (reg) {
@@ -1419,14 +1416,12 @@ static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
  */
 static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data)
 {
-       struct cdns3_device *priv_dev;
-       struct cdns3 *cdns = data;
+       struct cdns3_device *priv_dev = data;
        irqreturn_t ret = IRQ_NONE;
        unsigned long flags;
        int bit;
        u32 reg;
 
-       priv_dev = cdns->gadget_dev;
        spin_lock_irqsave(&priv_dev->lock, flags);
 
        reg = readl(&priv_dev->regs->usb_ists);
@@ -2539,7 +2534,7 @@ void cdns3_gadget_exit(struct cdns3 *cdns)
 
        priv_dev = cdns->gadget_dev;
 
-       devm_free_irq(cdns->dev, cdns->dev_irq, cdns);
+       devm_free_irq(cdns->dev, cdns->dev_irq, priv_dev);
 
        pm_runtime_mark_last_busy(cdns->dev);
        pm_runtime_put_autosuspend(cdns->dev);
@@ -2710,7 +2705,8 @@ static int __cdns3_gadget_init(struct cdns3 *cdns)
        ret = devm_request_threaded_irq(cdns->dev, cdns->dev_irq,
                                        cdns3_device_irq_handler,
                                        cdns3_device_thread_irq_handler,
-                                       IRQF_SHARED, dev_name(cdns->dev), cdns);
+                                       IRQF_SHARED, dev_name(cdns->dev),
+                                       cdns->gadget_dev);
 
        if (ret)
                goto err0;
index b45ceb9..48e4a5c 100644 (file)
@@ -26,6 +26,7 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
        struct regulator *reg_vbus;
+       bool enabled;
 };
 
 static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
@@ -37,7 +38,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
        int ret = 0;
        int port = HCS_N_PORTS(ehci->hcs_params);
 
-       if (priv->reg_vbus) {
+       if (priv->reg_vbus && enable != priv->enabled) {
                if (port > 1) {
                        dev_warn(dev,
                                "Not support multi-port regulator control\n");
@@ -53,6 +54,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
                                enable ? "enable" : "disable", ret);
                        return ret;
                }
+               priv->enabled = enable;
        }
 
        if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
index 5f40117..26bc05e 100644 (file)
@@ -203,9 +203,58 @@ static const unsigned short super_speed_maxpacket_maxes[4] = {
        [USB_ENDPOINT_XFER_INT] = 1024,
 };
 
-static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
-    int asnum, struct usb_host_interface *ifp, int num_ep,
-    unsigned char *buffer, int size)
+static bool endpoint_is_duplicate(struct usb_endpoint_descriptor *e1,
+               struct usb_endpoint_descriptor *e2)
+{
+       if (e1->bEndpointAddress == e2->bEndpointAddress)
+               return true;
+
+       if (usb_endpoint_xfer_control(e1) || usb_endpoint_xfer_control(e2)) {
+               if (usb_endpoint_num(e1) == usb_endpoint_num(e2))
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * Check for duplicate endpoint addresses in other interfaces and in the
+ * altsetting currently being parsed.
+ */
+static bool config_endpoint_is_duplicate(struct usb_host_config *config,
+               int inum, int asnum, struct usb_endpoint_descriptor *d)
+{
+       struct usb_endpoint_descriptor *epd;
+       struct usb_interface_cache *intfc;
+       struct usb_host_interface *alt;
+       int i, j, k;
+
+       for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+               intfc = config->intf_cache[i];
+
+               for (j = 0; j < intfc->num_altsetting; ++j) {
+                       alt = &intfc->altsetting[j];
+
+                       if (alt->desc.bInterfaceNumber == inum &&
+                                       alt->desc.bAlternateSetting != asnum)
+                               continue;
+
+                       for (k = 0; k < alt->desc.bNumEndpoints; ++k) {
+                               epd = &alt->endpoint[k].desc;
+
+                               if (endpoint_is_duplicate(epd, d))
+                                       return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+static int usb_parse_endpoint(struct device *ddev, int cfgno,
+               struct usb_host_config *config, int inum, int asnum,
+               struct usb_host_interface *ifp, int num_ep,
+               unsigned char *buffer, int size)
 {
        unsigned char *buffer0 = buffer;
        struct usb_endpoint_descriptor *d;
@@ -242,13 +291,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                goto skip_to_next_endpoint_or_interface_descriptor;
 
        /* Check for duplicate endpoint addresses */
-       for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
-               if (ifp->endpoint[i].desc.bEndpointAddress ==
-                   d->bEndpointAddress) {
-                       dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
-                           cfgno, inum, asnum, d->bEndpointAddress);
-                       goto skip_to_next_endpoint_or_interface_descriptor;
-               }
+       if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+               dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+                               cfgno, inum, asnum, d->bEndpointAddress);
+               goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
@@ -346,12 +392,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                        endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
        }
 
-       /* Validate the wMaxPacketSize field */
+       /*
+        * Validate the wMaxPacketSize field.
+        * Some devices have isochronous endpoints in altsetting 0;
+        * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0
+        * (see the end of section 5.6.3), so don't warn about them.
+        */
        maxp = usb_endpoint_maxp(&endpoint->desc);
-       if (maxp == 0) {
-               dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
+       if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
+               dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
                    cfgno, inum, asnum, d->bEndpointAddress);
-               goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
        /* Find the highest legal maxpacket size for this endpoint */
@@ -522,8 +572,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
                if (((struct usb_descriptor_header *) buffer)->bDescriptorType
                     == USB_DT_INTERFACE)
                        break;
-               retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
-                   num_ep, buffer, size);
+               retval = usb_parse_endpoint(ddev, cfgno, config, inum, asnum,
+                               alt, num_ep, buffer, size);
                if (retval < 0)
                        return retval;
                ++n;
index f229ad6..8c4e5ad 100644 (file)
@@ -2692,7 +2692,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 #define SET_ADDRESS_TRIES      2
 #define GET_DESCRIPTOR_TRIES   2
 #define SET_CONFIG_TRIES       (2 * (use_both_schemes + 1))
-#define USE_NEW_SCHEME(i, scheme)      ((i) / 2 == (int)scheme)
+#define USE_NEW_SCHEME(i, scheme)      ((i) / 2 == (int)(scheme))
 
 #define HUB_ROOT_RESET_TIME    60      /* times are in msec */
 #define HUB_SHORT_RESET_TIME   10
index 0c960a9..154f3f3 100644 (file)
@@ -2467,6 +2467,13 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
 
 static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
 {
+       /*
+        * For OUT direction, host may send less than the setup
+        * length. Return true for all OUT requests.
+        */
+       if (!req->direction)
+               return true;
+
        return req->request.actual == req->request.length;
 }
 
index ae70ce2..797d6ac 100644 (file)
@@ -445,6 +445,7 @@ config USB_TEGRA_XUDC
        tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller"
        depends on ARCH_TEGRA || COMPILE_TEST
        depends on PHY_TEGRA_XUSB
+       select USB_ROLE_SWITCH
        help
         Enables NVIDIA Tegra USB 3.0 device mode controller driver.
 
index 38183ac..1371b0c 100644 (file)
@@ -415,13 +415,17 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
        }
 
        da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
-       if (IS_ERR(da8xx_ohci->oc_gpio))
+       if (IS_ERR(da8xx_ohci->oc_gpio)) {
+               error = PTR_ERR(da8xx_ohci->oc_gpio);
                goto err;
+       }
 
        if (da8xx_ohci->oc_gpio) {
                oc_irq = gpiod_to_irq(da8xx_ohci->oc_gpio);
-               if (oc_irq < 0)
+               if (oc_irq < 0) {
+                       error = oc_irq;
                        goto err;
+               }
 
                error = devm_request_threaded_irq(dev, oc_irq, NULL,
                                ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING |
index 5261f8d..e3b8c84 100644 (file)
@@ -75,14 +75,17 @@ static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
 static int jz4740_musb_init(struct musb *musb)
 {
        struct device *dev = musb->controller->parent;
+       int err;
 
        if (dev->of_node)
                musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
        else
                musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
        if (IS_ERR(musb->xceiv)) {
-               dev_err(dev, "No transceiver configured\n");
-               return PTR_ERR(musb->xceiv);
+               err = PTR_ERR(musb->xceiv);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "No transceiver configured: %d", err);
+               return err;
        }
 
        /* Silicon does not implement ConfigData register.
index 15cca91..5ebf30b 100644 (file)
@@ -1840,6 +1840,9 @@ ATTRIBUTE_GROUPS(musb);
 #define MUSB_QUIRK_B_INVALID_VBUS_91   (MUSB_DEVCTL_BDEVICE | \
                                         (2 << MUSB_DEVCTL_VBUS_SHIFT) | \
                                         MUSB_DEVCTL_SESSION)
+#define MUSB_QUIRK_B_DISCONNECT_99     (MUSB_DEVCTL_BDEVICE | \
+                                        (3 << MUSB_DEVCTL_VBUS_SHIFT) | \
+                                        MUSB_DEVCTL_SESSION)
 #define MUSB_QUIRK_A_DISCONNECT_19     ((3 << MUSB_DEVCTL_VBUS_SHIFT) | \
                                         MUSB_DEVCTL_SESSION)
 
@@ -1862,6 +1865,11 @@ static void musb_pm_runtime_check_session(struct musb *musb)
        s = MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV |
                MUSB_DEVCTL_HR;
        switch (devctl & ~s) {
+       case MUSB_QUIRK_B_DISCONNECT_99:
+               musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n");
+               schedule_delayed_work(&musb->irq_work,
+                                     msecs_to_jiffies(1000));
+               break;
        case MUSB_QUIRK_B_INVALID_VBUS_91:
                if (musb->quirk_retries && !musb->flush_irq_work) {
                        musb_dbg(musb,
@@ -2310,6 +2318,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_disable_interrupts(musb);
        musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
 
+       /* MUSB_POWER_SOFTCONN might be already set, JZ4740 does this. */
+       musb_writeb(musb->mregs, MUSB_POWER, 0);
+
        /* Init IRQ workqueue before request_irq */
        INIT_DELAYED_WORK(&musb->irq_work, musb_irq_work);
        INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
index 5fc6825..2d3751d 100644 (file)
@@ -425,7 +425,7 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
        controller->controller.channel_abort = dma_channel_abort;
 
        if (request_irq(irq, dma_controller_irq, 0,
-                       dev_name(musb->controller), &controller->controller)) {
+                       dev_name(musb->controller), controller)) {
                dev_err(dev, "request_irq %d failed!\n", irq);
                musb_dma_controller_destroy(&controller->controller);
 
index e9491d4..2d919d0 100644 (file)
@@ -567,6 +567,9 @@ static void option_instat_callback(struct urb *urb);
 /* Interface must have two endpoints */
 #define NUMEP2         BIT(16)
 
+/* Device needs ZLP */
+#define ZLP            BIT(17)
+
 
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -1172,6 +1175,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(3) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1102, 0xff),    /* Telit ME910 (ECM) */
          .driver_info = NCTRL(0) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110a, 0xff),    /* Telit ME910G1 */
+         .driver_info = NCTRL(0) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
@@ -1196,6 +1201,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff),    /* Telit LN940 (MBIM) */
          .driver_info = NCTRL(0) },
+       { USB_DEVICE(TELIT_VENDOR_ID, 0x9010),                          /* Telit SBL FN980 flashing device */
+         .driver_info = NCTRL(0) | ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) },
@@ -2097,6 +2104,9 @@ static int option_attach(struct usb_serial *serial)
        if (!(device_flags & NCTRL(iface_desc->bInterfaceNumber)))
                data->use_send_setup = 1;
 
+       if (device_flags & ZLP)
+               data->use_zlp = 1;
+
        spin_lock_init(&data->susp_lock);
 
        usb_set_serial_data(serial, data);
index 1c120ea..934e936 100644 (file)
@@ -38,6 +38,7 @@ struct usb_wwan_intf_private {
        spinlock_t susp_lock;
        unsigned int suspended:1;
        unsigned int use_send_setup:1;
+       unsigned int use_zlp:1;
        int in_flight;
        unsigned int open_ports;
        void *private;
index 7e855c8..13be21a 100644 (file)
@@ -461,6 +461,7 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                                      void (*callback) (struct urb *))
 {
        struct usb_serial *serial = port->serial;
+       struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
        struct urb *urb;
 
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
@@ -471,6 +472,9 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                          usb_sndbulkpipe(serial->dev, endpoint) | dir,
                          buf, len, callback, ctx);
 
+       if (intfdata->use_zlp && dir == USB_DIR_OUT)
+               urb->transfer_flags |= URB_ZERO_PACKET;
+
        return urb;
 }
 
index c1f7073..8b4ff9f 100644 (file)
@@ -432,20 +432,30 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
 
        if (status & TCPC_ALERT_RX_STATUS) {
                struct pd_message msg;
-               unsigned int cnt;
+               unsigned int cnt, payload_cnt;
                u16 header;
 
                regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt);
+               /*
+                * 'cnt' corresponds to READABLE_BYTE_COUNT in section 4.4.14
+                * of the TCPCI spec [Rev 2.0 Ver 1.0 October 2017] and is
+                * defined in table 4-36 as one greater than the number of
+                * bytes received. And that number includes the header. So:
+                */
+               if (cnt > 3)
+                       payload_cnt = cnt - (1 + sizeof(msg.header));
+               else
+                       payload_cnt = 0;
 
                tcpci_read16(tcpci, TCPC_RX_HDR, &header);
                msg.header = cpu_to_le16(header);
 
-               if (WARN_ON(cnt > sizeof(msg.payload)))
-                       cnt = sizeof(msg.payload);
+               if (WARN_ON(payload_cnt > sizeof(msg.payload)))
+                       payload_cnt = sizeof(msg.payload);
 
-               if (cnt > 0)
+               if (payload_cnt > 0)
                        regmap_raw_read(tcpci->regmap, TCPC_RX_DATA,
-                                       &msg.payload, cnt);
+                                       &msg.payload, payload_cnt);
 
                /* Read complete, clear RX status alert bit */
                tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
index 8569bbd..831c947 100644 (file)
@@ -94,15 +94,15 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
 #define UCSI_ENABLE_NTFY_CMD_COMPLETE          BIT(16)
 #define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE    BIT(17)
 #define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE     BIT(18)
-#define UCSI_ENABLE_NTFY_CAP_CHANGE            BIT(19)
-#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE      BIT(20)
-#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE     BIT(21)
-#define UCSI_ENABLE_NTFY_CAM_CHANGE            BIT(22)
-#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE     BIT(23)
-#define UCSI_ENABLE_NTFY_PARTNER_CHANGE                BIT(24)
-#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE                BIT(25)
-#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE      BIT(26)
-#define UCSI_ENABLE_NTFY_ERROR                 BIT(27)
+#define UCSI_ENABLE_NTFY_CAP_CHANGE            BIT(21)
+#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE      BIT(22)
+#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE     BIT(23)
+#define UCSI_ENABLE_NTFY_CAM_CHANGE            BIT(24)
+#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE     BIT(25)
+#define UCSI_ENABLE_NTFY_PARTNER_CHANGE                BIT(27)
+#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE                BIT(28)
+#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE      BIT(30)
+#define UCSI_ENABLE_NTFY_ERROR                 BIT(31)
 #define UCSI_ENABLE_NTFY_ALL                   0xdbe70000
 
 /* SET_UOR command bits */
index 1679e0d..cec868f 100644 (file)
@@ -687,6 +687,7 @@ config MAX63XX_WATCHDOG
 config MAX77620_WATCHDOG
        tristate "Maxim Max77620 Watchdog Timer"
        depends on MFD_MAX77620 || COMPILE_TEST
+       select WATCHDOG_CORE
        help
         This is the driver for the Max77620 watchdog timer.
         Say 'Y' here to enable the watchdog timer support for
@@ -1444,6 +1445,7 @@ config SMSC37B787_WDT
 config TQMX86_WDT
        tristate "TQ-Systems TQMX86 Watchdog Timer"
        depends on X86
+       select WATCHDOG_CORE
        help
        This is the driver for the hardware watchdog timer in the TQMX86 IO
        controller found on some of their ComExpress Modules.
index 0a87c6f..11b9e7c 100644 (file)
@@ -112,7 +112,7 @@ static int imx7ulp_wdt_restart(struct watchdog_device *wdog,
 {
        struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog);
 
-       imx7ulp_wdt_enable(wdt->base, true);
+       imx7ulp_wdt_enable(wdog, true);
        imx7ulp_wdt_set_timeout(&wdt->wdd, 1);
 
        /* wait for wdog to fire */
index 1cccf8e..8e6dfe7 100644 (file)
@@ -602,7 +602,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
                set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
 
        /* Request the IRQ only after the watchdog is disabled */
-       irq = platform_get_irq(pdev, 0);
+       irq = platform_get_irq_optional(pdev, 0);
        if (irq > 0) {
                /*
                 * Not all supported platforms specify an interrupt for the
@@ -617,7 +617,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
        }
 
        /* Optional 2nd interrupt for pretimeout */
-       irq = platform_get_irq(pdev, 1);
+       irq = platform_get_irq_optional(pdev, 1);
        if (irq > 0) {
                orion_wdt_info.options |= WDIOF_PRETIMEOUT;
                ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
index 2348760..6e524c8 100644 (file)
@@ -188,6 +188,7 @@ static struct platform_driver rn5t618_wdt_driver = {
 
 module_platform_driver(rn5t618_wdt_driver);
 
+MODULE_ALIAS("platform:rn5t618-wdt");
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 MODULE_DESCRIPTION("RN5T618 watchdog driver");
 MODULE_LICENSE("GPL v2");
index fdf533f..56a4a40 100644 (file)
@@ -420,7 +420,7 @@ static int wdt_find(int addr)
                cr_wdt_csr = NCT6102D_WDT_CSR;
                break;
        case NCT6116_ID:
-               ret = nct6102;
+               ret = nct6116;
                cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
                cr_wdt_control = NCT6102D_WDT_CONTROL;
                cr_wdt_csr = NCT6102D_WDT_CSR;
index e94a661..18a87ec 100644 (file)
@@ -3031,7 +3031,7 @@ static void end_bio_bh_io_sync(struct bio *bio)
  * errors, this only handles the "we need to be able to
  * do IO at the final sector" case.
  */
-void guard_bio_eod(int op, struct bio *bio)
+void guard_bio_eod(struct bio *bio)
 {
        sector_t maxsector;
        struct hd_struct *part;
@@ -3095,15 +3095,15 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
 
-       /* Take care of bh's that straddle the end of the device */
-       guard_bio_eod(op, bio);
-
        if (buffer_meta(bh))
                op_flags |= REQ_META;
        if (buffer_prio(bh))
                op_flags |= REQ_PRIO;
        bio_set_op_attrs(bio, op, op_flags);
 
+       /* Take care of bh's that straddle the end of the device */
+       guard_bio_eod(bio);
+
        if (wbc) {
                wbc_init_bio(wbc, bio);
                wbc_account_cgroup_owner(wbc, bh->b_page, bh->b_size);
index 00dfe17..c5e6eff 100644 (file)
@@ -352,7 +352,7 @@ static struct kobject *cdev_get(struct cdev *p)
 
        if (owner && !try_module_get(owner))
                return NULL;
-       kobj = kobject_get(&p->kobj);
+       kobj = kobject_get_unless_zero(&p->kobj);
        if (!kobj)
                module_put(owner);
        return kobj;
index 4a7da1d..e3fa695 100644 (file)
@@ -38,7 +38,7 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait)
 /*
  * buffer.c
  */
-extern void guard_bio_eod(int rw, struct bio *bio);
+extern void guard_bio_eod(struct bio *bio);
 extern int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
                get_block_t *get_block, struct iomap *iomap);
 
index 562e3a1..38b5405 100644 (file)
@@ -1863,18 +1863,6 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
                else
                        ret2 = loop_rw_iter(READ, req->file, kiocb, &iter);
 
-               /*
-                * In case of a short read, punt to async. This can happen
-                * if we have data partially cached. Alternatively we can
-                * return the short read, in which case the application will
-                * need to issue another SQE and wait for it. That SQE will
-                * need async punt anyway, so it's more efficient to do it
-                * here.
-                */
-               if (force_nonblock && !(req->flags & REQ_F_NOWAIT) &&
-                   (req->flags & REQ_F_ISREG) &&
-                   ret2 > 0 && ret2 < io_size)
-                       ret2 = -EAGAIN;
                /* Catch -EAGAIN return for forced non-blocking submission */
                if (!force_nonblock || ret2 != -EAGAIN) {
                        kiocb_done(kiocb, ret2, nxt, req->in_async);
index a63620c..ccba3c4 100644 (file)
@@ -62,7 +62,7 @@ static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio)
 {
        bio->bi_end_io = mpage_end_io;
        bio_set_op_attrs(bio, op, op_flags);
-       guard_bio_eod(op, bio);
+       guard_bio_eod(bio);
        submit_bio(bio);
        return NULL;
 }
index 487ee39..013486b 100644 (file)
@@ -583,12 +583,12 @@ static int ramoops_init_przs(const char *name,
                prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig,
                                               &cxt->ecc_info,
                                               cxt->memtype, flags, label);
+               kfree(label);
                if (IS_ERR(prz_ar[i])) {
                        err = PTR_ERR(prz_ar[i]);
                        dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
                                name, record_size,
                                (unsigned long long)*paddr, err);
-                       kfree(label);
 
                        while (i > 0) {
                                i--;
@@ -629,12 +629,12 @@ static int ramoops_init_prz(const char *name,
        label = kasprintf(GFP_KERNEL, "ramoops:%s", name);
        *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
                                  cxt->memtype, PRZ_FLAG_ZAP_OLD, label);
+       kfree(label);
        if (IS_ERR(*prz)) {
                int err = PTR_ERR(*prz);
 
                dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
                        name, sz, (unsigned long long)*paddr, err);
-               kfree(label);
                return err;
        }
 
index 8823f65..1f4d8c0 100644 (file)
@@ -574,7 +574,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
        /* Initialize general buffer state. */
        raw_spin_lock_init(&prz->buffer_lock);
        prz->flags = flags;
-       prz->label = label;
+       prz->label = kstrdup(label, GFP_KERNEL);
 
        ret = persistent_ram_buffer_map(start, size, prz, memtype);
        if (ret)
index 679a422..a81c13a 100644 (file)
@@ -153,26 +153,4 @@ static inline void bvec_advance(const struct bio_vec *bvec,
        }
 }
 
-/*
- * Get the last single-page segment from the multi-page bvec and store it
- * in @seg
- */
-static inline void mp_bvec_last_segment(const struct bio_vec *bvec,
-                                       struct bio_vec *seg)
-{
-       unsigned total = bvec->bv_offset + bvec->bv_len;
-       unsigned last_page = (total - 1) / PAGE_SIZE;
-
-       seg->bv_page = bvec->bv_page + last_page;
-
-       /* the whole segment is inside the last page */
-       if (bvec->bv_offset >= last_page * PAGE_SIZE) {
-               seg->bv_offset = bvec->bv_offset % PAGE_SIZE;
-               seg->bv_len = bvec->bv_len;
-       } else {
-               seg->bv_offset = 0;
-               seg->bv_len = total - last_page * PAGE_SIZE;
-       }
-}
-
 #endif /* __LINUX_BVEC_ITER_H */
index 9b3c720..5e3d455 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/can/error.h>
 #include <linux/can/led.h>
 #include <linux/can/netlink.h>
+#include <linux/can/skb.h>
 #include <linux/netdevice.h>
 
 /*
@@ -91,6 +92,36 @@ struct can_priv {
 #define get_can_dlc(i)         (min_t(__u8, (i), CAN_MAX_DLC))
 #define get_canfd_dlc(i)       (min_t(__u8, (i), CANFD_MAX_DLC))
 
+/* Check for outgoing skbs that have not been created by the CAN subsystem */
+static inline bool can_skb_headroom_valid(struct net_device *dev,
+                                         struct sk_buff *skb)
+{
+       /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
+       if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
+               return false;
+
+       /* af_packet does not apply CAN skb specific settings */
+       if (skb->ip_summed == CHECKSUM_NONE) {
+               /* init headroom */
+               can_skb_prv(skb)->ifindex = dev->ifindex;
+               can_skb_prv(skb)->skbcnt = 0;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+               /* preform proper loopback on capable devices */
+               if (dev->flags & IFF_ECHO)
+                       skb->pkt_type = PACKET_LOOPBACK;
+               else
+                       skb->pkt_type = PACKET_HOST;
+
+               skb_reset_mac_header(skb);
+               skb_reset_network_header(skb);
+               skb_reset_transport_header(skb);
+       }
+
+       return true;
+}
+
 /* Drop a given socketbuffer if it does not contain a valid CAN frame. */
 static inline bool can_dropped_invalid_skb(struct net_device *dev,
                                          struct sk_buff *skb)
@@ -108,6 +139,9 @@ static inline bool can_dropped_invalid_skb(struct net_device *dev,
        } else
                goto inval_skb;
 
+       if (!can_skb_headroom_valid(dev, skb))
+               goto inval_skb;
+
        return false;
 
 inval_skb:
index 76cf11e..8a9792a 100644 (file)
@@ -24,6 +24,14 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
        return (struct ethhdr *)skb_mac_header(skb);
 }
 
+/* Prefer this version in TX path, instead of
+ * skb_reset_mac_header() + eth_hdr()
+ */
+static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb)
+{
+       return (struct ethhdr *)skb->data;
+}
+
 static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
 {
        return (struct ethhdr *)skb_inner_mac_header(skb);
index f84b916..7dfb63b 100644 (file)
 
 #define RTC_AL_SEC             0x0018
 
+#define RTC_AL_SEC_MASK        0x003f
+#define RTC_AL_MIN_MASK        0x003f
+#define RTC_AL_HOU_MASK        0x001f
+#define RTC_AL_DOM_MASK        0x001f
+#define RTC_AL_DOW_MASK        0x0007
+#define RTC_AL_MTH_MASK        0x000f
+#define RTC_AL_YEA_MASK        0x007f
+
 #define RTC_PDN2               0x002e
 #define RTC_PDN2_PWRON_ALARM   BIT(4)
 
index ecc88a4..c04f690 100644 (file)
@@ -40,7 +40,7 @@ typedef enum {
        FL_READING,
        FL_CACHEDPRG,
        /* These 4 come from onenand_state_t, which has been unified here */
-       FL_RESETING,
+       FL_RESETTING,
        FL_OTPING,
        FL_PREPARING_ERASE,
        FL_VERIFYING_ERASE,
index 98fe866..3a67a7e 100644 (file)
@@ -689,10 +689,10 @@ extern void spi_finalize_current_transfer(struct spi_controller *ctlr);
 /* Helper calls for driver to timestamp transfer */
 void spi_take_timestamp_pre(struct spi_controller *ctlr,
                            struct spi_transfer *xfer,
-                           const void *tx, bool irqs_off);
+                           size_t progress, bool irqs_off);
 void spi_take_timestamp_post(struct spi_controller *ctlr,
                             struct spi_transfer *xfer,
-                            const void *tx, bool irqs_off);
+                            size_t progress, bool irqs_off);
 
 /* the spi driver core manages memory for the spi_controller classdev */
 extern struct spi_controller *__spi_alloc_controller(struct device *host,
index 85ec745..966146f 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * 10G controller driver for Samsung EXYNOS SoCs
+ * 10G controller driver for Samsung Exynos SoCs
  *
  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
index f0897b3..415b8f4 100644 (file)
@@ -106,6 +106,12 @@ struct flow_offload {
 };
 
 #define NF_FLOW_TIMEOUT (30 * HZ)
+#define nf_flowtable_time_stamp        (u32)jiffies
+
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+       return (__s32)(timeout - nf_flowtable_time_stamp);
+}
 
 struct nf_flow_route {
        struct {
diff --git a/include/soc/sifive/sifive_l2_cache.h b/include/soc/sifive/sifive_l2_cache.h
new file mode 100644 (file)
index 0000000..92ade10
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SiFive L2 Cache Controller header file
+ *
+ */
+
+#ifndef __SOC_SIFIVE_L2_CACHE_H
+#define __SOC_SIFIVE_L2_CACHE_H
+
+extern int register_sifive_l2_error_notifier(struct notifier_block *nb);
+extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
+
+#define SIFIVE_L2_ERR_TYPE_CE 0
+#define SIFIVE_L2_ERR_TYPE_UE 1
+
+#endif /* __SOC_SIFIVE_L2_CACHE_H */
index 95fba04..3f249e1 100644 (file)
@@ -18,13 +18,13 @@ DECLARE_EVENT_CLASS(preemptirq_template,
        TP_ARGS(ip, parent_ip),
 
        TP_STRUCT__entry(
-               __field(u32, caller_offs)
-               __field(u32, parent_offs)
+               __field(s32, caller_offs)
+               __field(s32, parent_offs)
        ),
 
        TP_fast_assign(
-               __entry->caller_offs = (u32)(ip - (unsigned long)_stext);
-               __entry->parent_offs = (u32)(parent_ip - (unsigned long)_stext);
+               __entry->caller_offs = (s32)(ip - (unsigned long)_stext);
+               __entry->parent_offs = (s32)(parent_ip - (unsigned long)_stext);
        ),
 
        TP_printk("caller=%pS parent=%pS",
index f056b2a..9a61c28 100644 (file)
@@ -34,6 +34,7 @@ struct input_event {
        __kernel_ulong_t __sec;
 #if defined(__sparc__) && defined(__arch64__)
        unsigned int __usec;
+       unsigned int __pad;
 #else
        __kernel_ulong_t __usec;
 #endif
index 4fb20ab..9e43b72 100644 (file)
@@ -35,8 +35,8 @@ void cgroup_bpf_offline(struct cgroup *cgrp)
  */
 static void cgroup_bpf_release(struct work_struct *work)
 {
-       struct cgroup *cgrp = container_of(work, struct cgroup,
-                                          bpf.release_work);
+       struct cgroup *p, *cgrp = container_of(work, struct cgroup,
+                                              bpf.release_work);
        enum bpf_cgroup_storage_type stype;
        struct bpf_prog_array *old_array;
        unsigned int type;
@@ -65,6 +65,9 @@ static void cgroup_bpf_release(struct work_struct *work)
 
        mutex_unlock(&cgroup_mutex);
 
+       for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
+               cgroup_bpf_put(p);
+
        percpu_ref_exit(&cgrp->bpf.refcnt);
        cgroup_put(cgrp);
 }
@@ -199,6 +202,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
  */
 #define        NR ARRAY_SIZE(cgrp->bpf.effective)
        struct bpf_prog_array *arrays[NR] = {};
+       struct cgroup *p;
        int ret, i;
 
        ret = percpu_ref_init(&cgrp->bpf.refcnt, cgroup_bpf_release_fn, 0,
@@ -206,6 +210,9 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
        if (ret)
                return ret;
 
+       for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
+               cgroup_bpf_get(p);
+
        for (i = 0; i < NR; i++)
                INIT_LIST_HEAD(&cgrp->bpf.progs[i]);
 
index 6f63ae7..ce85e70 100644 (file)
@@ -6264,6 +6264,7 @@ static bool may_access_skb(enum bpf_prog_type type)
 static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
        struct bpf_reg_state *regs = cur_regs(env);
+       static const int ctx_reg = BPF_REG_6;
        u8 mode = BPF_MODE(insn->code);
        int i, err;
 
@@ -6297,7 +6298,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
        }
 
        /* check whether implicit source operand (register R6) is readable */
-       err = check_reg_arg(env, BPF_REG_6, SRC_OP);
+       err = check_reg_arg(env, ctx_reg, SRC_OP);
        if (err)
                return err;
 
@@ -6316,7 +6317,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
                return -EINVAL;
        }
 
-       if (regs[BPF_REG_6].type != PTR_TO_CTX) {
+       if (regs[ctx_reg].type != PTR_TO_CTX) {
                verbose(env,
                        "at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
                return -EINVAL;
@@ -6329,6 +6330,10 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        return err;
        }
 
+       err = check_ctx_reg(env, &regs[ctx_reg], ctx_reg);
+       if (err < 0)
+               return err;
+
        /* reset caller saved regs to unreadable */
        for (i = 0; i < CALLER_SAVED_REGS; i++) {
                mark_reg_not_init(env, regs, caller_saved[i]);
index 2508a4f..0808095 100644 (file)
@@ -2578,6 +2578,16 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 #endif
 
 #ifdef __ARCH_WANT_SYS_CLONE3
+
+/*
+ * copy_thread implementations handle CLONE_SETTLS by reading the TLS value from
+ * the registers containing the syscall arguments for clone. This doesn't work
+ * with clone3 since the TLS value is passed in clone_args instead.
+ */
+#ifndef CONFIG_HAVE_COPY_THREAD_TLS
+#error clone3 requires copy_thread_tls support in arch
+#endif
+
 noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
                                              struct clone_args __user *uargs,
                                              size_t usize)
index a265973..1af321d 100644 (file)
@@ -96,6 +96,20 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func,
        return 0;
 }
 
+/*
+ * Not all archs define MCOUNT_INSN_SIZE which is used to look for direct
+ * functions. But those archs currently don't support direct functions
+ * anyway, and ftrace_find_rec_direct() is just a stub for them.
+ * Define MCOUNT_INSN_SIZE to keep those archs compiling.
+ */
+#ifndef MCOUNT_INSN_SIZE
+/* Make sure this only works without direct calls */
+# ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+#  error MCOUNT_INSN_SIZE not defined with direct calls enabled
+# endif
+# define MCOUNT_INSN_SIZE 0
+#endif
+
 int function_graph_enter(unsigned long ret, unsigned long func,
                         unsigned long frame_pointer, unsigned long *retp)
 {
index ac99a35..9bf1f2c 100644 (file)
@@ -526,8 +526,7 @@ static int function_stat_show(struct seq_file *m, void *v)
        }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       avg = rec->time;
-       do_div(avg, rec->counter);
+       avg = div64_ul(rec->time, rec->counter);
        if (tracing_thresh && (avg < tracing_thresh))
                goto out;
 #endif
@@ -553,7 +552,8 @@ static int function_stat_show(struct seq_file *m, void *v)
                 * Divide only 1000 for ns^2 -> us^2 conversion.
                 * trace_print_graph_duration will divide 1000 again.
                 */
-               do_div(stddev, rec->counter * (rec->counter - 1) * 1000);
+               stddev = div64_ul(stddev,
+                                 rec->counter * (rec->counter - 1) * 1000);
        }
 
        trace_seq_init(&s);
index d45079e..22bcf7c 100644 (file)
@@ -195,7 +195,7 @@ static int parse_entry(char *str, struct trace_event_call *call, void **pentry)
        unsigned long irq_flags;
        void *entry = NULL;
        int entry_size;
-       u64 val;
+       u64 val = 0;
        int len;
 
        entry = trace_alloc_entry(call, &entry_size);
index 5e43b96..617e297 100644 (file)
@@ -630,7 +630,7 @@ static void start_wakeup_tracer(struct trace_array *tr)
        if (ret) {
                pr_info("wakeup trace: Couldn't activate tracepoint"
                        " probe to kernel_sched_migrate_task\n");
-               return;
+               goto fail_deprobe_sched_switch;
        }
 
        wakeup_reset(tr);
@@ -648,6 +648,8 @@ static void start_wakeup_tracer(struct trace_array *tr)
                printk(KERN_ERR "failed to start wakeup tracer\n");
 
        return;
+fail_deprobe_sched_switch:
+       unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
 fail_deprobe_wake_new:
        unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
 fail_deprobe:
index 344e4c1..87de6ed 100644 (file)
@@ -381,7 +381,7 @@ int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
                       int prefix_type, int rowsize, int groupsize,
                       const void *buf, size_t len, bool ascii)
 {
-               unsigned int save_len = s->seq.len;
+       unsigned int save_len = s->seq.len;
 
        if (s->full)
                return 0;
index 4df9a20..c557f42 100644 (file)
@@ -283,6 +283,11 @@ static void check_stack(unsigned long ip, unsigned long *stack)
        local_irq_restore(flags);
 }
 
+/* Some archs may not define MCOUNT_INSN_SIZE */
+#ifndef MCOUNT_INSN_SIZE
+# define MCOUNT_INSN_SIZE 0
+#endif
+
 static void
 stack_trace_call(unsigned long ip, unsigned long parent_ip,
                 struct ftrace_ops *op, struct pt_regs *pt_regs)
index 9c64852..71e4ffc 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -90,12 +90,6 @@ static void unmap_region(struct mm_struct *mm,
  * MAP_PRIVATE r: (no) no      r: (yes) yes    r: (no) yes     r: (no) yes
  *             w: (no) no      w: (no) no      w: (copy) copy  w: (no) no
  *             x: (no) no      x: (no) yes     x: (no) yes     x: (yes) yes
- *
- * On arm64, PROT_EXEC has the following behaviour for both MAP_SHARED and
- * MAP_PRIVATE:
- *                                                             r: (no) no
- *                                                             w: (no) no
- *                                                             x: (yes) yes
  */
 pgprot_t protection_map[16] __ro_after_init = {
        __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
index c46daf0..bb7ec1a 100644 (file)
@@ -126,6 +126,7 @@ int vlan_check_real_dev(struct net_device *real_dev,
 void vlan_setup(struct net_device *dev);
 int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack);
 void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
+void vlan_dev_uninit(struct net_device *dev);
 bool vlan_dev_inherit_address(struct net_device *dev,
                              struct net_device *real_dev);
 
index e5bff5c..2a78da4 100644 (file)
@@ -586,7 +586,8 @@ static int vlan_dev_init(struct net_device *dev)
        return 0;
 }
 
-static void vlan_dev_uninit(struct net_device *dev)
+/* Note: this function might be called multiple times for the same device. */
+void vlan_dev_uninit(struct net_device *dev)
 {
        struct vlan_priority_tci_mapping *pm;
        struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
index c482a6f..0db85ae 100644 (file)
@@ -108,11 +108,13 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
        struct ifla_vlan_flags *flags;
        struct ifla_vlan_qos_mapping *m;
        struct nlattr *attr;
-       int rem;
+       int rem, err;
 
        if (data[IFLA_VLAN_FLAGS]) {
                flags = nla_data(data[IFLA_VLAN_FLAGS]);
-               vlan_dev_change_flags(dev, flags->flags, flags->mask);
+               err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
+               if (err)
+                       return err;
        }
        if (data[IFLA_VLAN_INGRESS_QOS]) {
                nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
@@ -123,7 +125,9 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
        if (data[IFLA_VLAN_EGRESS_QOS]) {
                nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
                        m = nla_data(attr);
-                       vlan_dev_set_egress_priority(dev, m->from, m->to);
+                       err = vlan_dev_set_egress_priority(dev, m->from, m->to);
+                       if (err)
+                               return err;
                }
        }
        return 0;
@@ -179,10 +183,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        err = vlan_changelink(dev, tb, data, extack);
-       if (err < 0)
-               return err;
-
-       return register_vlan_dev(dev, extack);
+       if (!err)
+               err = register_vlan_dev(dev, extack);
+       if (err)
+               vlan_dev_uninit(dev);
+       return err;
 }
 
 static inline size_t vlan_qos_map_size(unsigned int n)
index 214154b..069f72e 100644 (file)
@@ -384,10 +384,11 @@ next:             ;
        return 1;
 }
 
-static inline int check_target(struct arpt_entry *e, const char *name)
+static int check_target(struct arpt_entry *e, struct net *net, const char *name)
 {
        struct xt_entry_target *t = arpt_get_target(e);
        struct xt_tgchk_param par = {
+               .net       = net,
                .table     = name,
                .entryinfo = e,
                .target    = t->u.kernel.target,
@@ -399,8 +400,9 @@ static inline int check_target(struct arpt_entry *e, const char *name)
        return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
 }
 
-static inline int
-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+static int
+find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
+                unsigned int size,
                 struct xt_percpu_counter_alloc_state *alloc_state)
 {
        struct xt_entry_target *t;
@@ -419,7 +421,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
        }
        t->u.kernel.target = target;
 
-       ret = check_target(e, name);
+       ret = check_target(e, net, name);
        if (ret)
                goto err;
        return 0;
@@ -512,7 +514,9 @@ static inline void cleanup_entry(struct arpt_entry *e)
 /* Checks and translates the user-supplied table segment (held in
  * newinfo).
  */
-static int translate_table(struct xt_table_info *newinfo, void *entry0,
+static int translate_table(struct net *net,
+                          struct xt_table_info *newinfo,
+                          void *entry0,
                           const struct arpt_replace *repl)
 {
        struct xt_percpu_counter_alloc_state alloc_state = { 0 };
@@ -569,7 +573,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
        /* Finally, each sanity check must pass */
        i = 0;
        xt_entry_foreach(iter, entry0, newinfo->size) {
-               ret = find_check_entry(iter, repl->name, repl->size,
+               ret = find_check_entry(iter, net, repl->name, repl->size,
                                       &alloc_state);
                if (ret != 0)
                        break;
@@ -974,7 +978,7 @@ static int do_replace(struct net *net, const void __user *user,
                goto free_newinfo;
        }
 
-       ret = translate_table(newinfo, loc_cpu_entry, &tmp);
+       ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
        if (ret != 0)
                goto free_newinfo;
 
@@ -1149,7 +1153,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
        }
 }
 
-static int translate_compat_table(struct xt_table_info **pinfo,
+static int translate_compat_table(struct net *net,
+                                 struct xt_table_info **pinfo,
                                  void **pentry0,
                                  const struct compat_arpt_replace *compatr)
 {
@@ -1217,7 +1222,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
        repl.num_counters = 0;
        repl.counters = NULL;
        repl.size = newinfo->size;
-       ret = translate_table(newinfo, entry1, &repl);
+       ret = translate_table(net, newinfo, entry1, &repl);
        if (ret)
                goto free_newinfo;
 
@@ -1270,7 +1275,7 @@ static int compat_do_replace(struct net *net, void __user *user,
                goto free_newinfo;
        }
 
-       ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
+       ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
        if (ret != 0)
                goto free_newinfo;
 
@@ -1546,7 +1551,7 @@ int arpt_register_table(struct net *net,
        loc_cpu_entry = newinfo->entries;
        memcpy(loc_cpu_entry, repl->entries, repl->size);
 
-       ret = translate_table(newinfo, loc_cpu_entry, repl);
+       ret = translate_table(net, newinfo, loc_cpu_entry, repl);
        if (ret != 0)
                goto out_free;
 
index 88b987c..0238b55 100644 (file)
@@ -1727,8 +1727,11 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
                }
 
                /* Ignore very old stuff early */
-               if (!after(sp[used_sacks].end_seq, prior_snd_una))
+               if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
+                       if (i == 0)
+                               first_sack_index = -1;
                        continue;
+               }
 
                used_sacks++;
        }
index 169e0a0..cf895bc 100644 (file)
@@ -1848,6 +1848,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
        struct ip_set *set;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
        int ret = 0;
+       u32 lineno;
 
        if (unlikely(protocol_min_failed(attr) ||
                     !attr[IPSET_ATTR_SETNAME] ||
@@ -1864,7 +1865,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
                return -IPSET_ERR_PROTOCOL;
 
        rcu_read_lock_bh();
-       ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
+       ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
        rcu_read_unlock_bh();
        /* Userspace can't trigger element to be re-added */
        if (ret == -EAGAIN)
index b6b14db..b3f4a33 100644 (file)
@@ -677,6 +677,9 @@ static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
        unsigned int *timeouts = data;
        int i;
 
+       if (!timeouts)
+                timeouts = dn->dccp_timeout;
+
        /* set default DCCP timeouts. */
        for (i=0; i<CT_DCCP_MAX; i++)
                timeouts[i] = dn->dccp_timeout[i];
index fce3d93..0399ae8 100644 (file)
@@ -594,6 +594,9 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[],
        struct nf_sctp_net *sn = nf_sctp_pernet(net);
        int i;
 
+       if (!timeouts)
+               timeouts = sn->timeouts;
+
        /* set default SCTP timeouts. */
        for (i=0; i<SCTP_CONNTRACK_MAX; i++)
                timeouts[i] = sn->timeouts[i];
index 9889d52..e33a73c 100644 (file)
@@ -134,11 +134,6 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
 #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT        (120 * HZ)
 #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT        (30 * HZ)
 
-static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
-{
-       return (__s32)(timeout - (u32)jiffies);
-}
-
 static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
 {
        const struct nf_conntrack_l4proto *l4proto;
@@ -232,7 +227,7 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 {
        int err;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
 
        err = rhashtable_insert_fast(&flow_table->rhashtable,
                                     &flow->tuplehash[0].node,
index b9e7dd6..7ea2ddc 100644 (file)
@@ -280,7 +280,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
                return NF_DROP;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
        skb->tstamp = 0;
@@ -509,7 +509,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_nat_ipv6(flow, skb, dir) < 0)
                return NF_DROP;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
        skb->tstamp = 0;
index 0d72e5c..d06969a 100644 (file)
@@ -166,24 +166,38 @@ static int flow_offload_eth_dst(struct net *net,
                                enum flow_offload_tuple_dir dir,
                                struct nf_flow_rule *flow_rule)
 {
-       const struct flow_offload_tuple *tuple = &flow->tuplehash[dir].tuple;
        struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule);
        struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule);
+       const void *daddr = &flow->tuplehash[!dir].tuple.src_v4;
+       const struct dst_entry *dst_cache;
+       unsigned char ha[ETH_ALEN];
        struct neighbour *n;
        u32 mask, val;
+       u8 nud_state;
        u16 val16;
 
-       n = dst_neigh_lookup(tuple->dst_cache, &tuple->dst_v4);
+       dst_cache = flow->tuplehash[dir].tuple.dst_cache;
+       n = dst_neigh_lookup(dst_cache, daddr);
        if (!n)
                return -ENOENT;
 
+       read_lock_bh(&n->lock);
+       nud_state = n->nud_state;
+       ether_addr_copy(ha, n->ha);
+       read_unlock_bh(&n->lock);
+
+       if (!(nud_state & NUD_VALID)) {
+               neigh_release(n);
+               return -ENOENT;
+       }
+
        mask = ~0xffffffff;
-       memcpy(&val, n->ha, 4);
+       memcpy(&val, ha, 4);
        flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 0,
                            &val, &mask);
 
        mask = ~0x0000ffff;
-       memcpy(&val16, n->ha + 4, 2);
+       memcpy(&val16, ha + 4, 2);
        val = val16;
        flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
                            &val, &mask);
@@ -335,22 +349,26 @@ static void flow_offload_port_snat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff0000), port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
                port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
                offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
                port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
                offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        default:
                return;
        }
-       port = htonl(port << 16);
+
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
                            &port, &mask);
 }
@@ -361,22 +379,26 @@ static void flow_offload_port_dnat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff), port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
-               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);
+               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
-               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port);
+               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        default:
                return;
        }
-       port = htonl(port);
+
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
                            &port, &mask);
 }
@@ -759,9 +781,9 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
                           struct flow_offload *flow)
 {
        struct flow_offload_work *offload;
-       s64 delta;
+       __s32 delta;
 
-       delta = flow->timeout - jiffies;
+       delta = nf_flow_timeout_delta(flow->timeout);
        if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10) ||
            flow->flags & FLOW_OFFLOAD_HW_DYING)
                return;
index 273f383..43f05b3 100644 (file)
@@ -5984,6 +5984,7 @@ nft_flowtable_type_get(struct net *net, u8 family)
        return ERR_PTR(-ENOENT);
 }
 
+/* Only called from error and netdev event paths. */
 static void nft_unregister_flowtable_hook(struct net *net,
                                          struct nft_flowtable *flowtable,
                                          struct nft_hook *hook)
@@ -5999,7 +6000,7 @@ static void nft_unregister_flowtable_net_hooks(struct net *net,
        struct nft_hook *hook;
 
        list_for_each_entry(hook, &flowtable->hook_list, list)
-               nft_unregister_flowtable_hook(net, flowtable, hook);
+               nf_unregister_net_hook(net, &hook->ops);
 }
 
 static int nft_register_flowtable_net_hooks(struct net *net,
@@ -6448,12 +6449,14 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
 {
        struct nft_hook *hook, *next;
 
+       flowtable->data.type->free(&flowtable->data);
        list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
+               flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
+                                           FLOW_BLOCK_UNBIND);
                list_del_rcu(&hook->list);
                kfree(hook);
        }
        kfree(flowtable->name);
-       flowtable->data.type->free(&flowtable->data);
        module_put(flowtable->data.type->owner);
        kfree(flowtable);
 }
@@ -6497,6 +6500,7 @@ static void nft_flowtable_event(unsigned long event, struct net_device *dev,
                if (hook->ops.dev != dev)
                        continue;
 
+               /* flow_offload_netdev_event() cleans up entries for us. */
                nft_unregister_flowtable_hook(dev_net(dev), flowtable, hook);
                list_del_rcu(&hook->list);
                kfree_rcu(hook, rcu);
index dd82ff2..b70b489 100644 (file)
@@ -200,9 +200,6 @@ static void nft_flow_offload_activate(const struct nft_ctx *ctx,
 static void nft_flow_offload_destroy(const struct nft_ctx *ctx,
                                     const struct nft_expr *expr)
 {
-       struct nft_flow_offload *priv = nft_expr_priv(expr);
-
-       priv->flowtable->use--;
        nf_ct_netns_put(ctx->net, ctx->family);
 }
 
index 88f98f2..3d24d45 100644 (file)
@@ -196,7 +196,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
        hdr->size = cpu_to_le32(len);
        hdr->confirm_rx = 0;
 
-       skb_put_padto(skb, ALIGN(len, 4));
+       skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
 
        mutex_lock(&node->ep_lock);
        if (node->ep)
index e0f4040..2277369 100644 (file)
@@ -1769,7 +1769,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                                                      q->avg_window_begin));
                        u64 b = q->avg_window_bytes * (u64)NSEC_PER_SEC;
 
-                       do_div(b, window_interval);
+                       b = div64_u64(b, window_interval);
                        q->avg_peak_bandwidth =
                                cake_ewma(q->avg_peak_bandwidth, b,
                                          b > q->avg_peak_bandwidth ? 2 : 8);
index ff4c5e9..a5a2954 100644 (file)
@@ -786,10 +786,12 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
        if (tb[TCA_FQ_QUANTUM]) {
                u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
 
-               if (quantum > 0)
+               if (quantum > 0 && quantum <= (1 << 20)) {
                        q->quantum = quantum;
-               else
+               } else {
+                       NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
                        err = -EINVAL;
+               }
        }
 
        if (tb[TCA_FQ_INITIAL_QUANTUM])
index 18b884c..6479417 100644 (file)
@@ -292,8 +292,14 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
        struct tc_prio_qopt_offload graft_offload;
        unsigned long band = arg - 1;
 
-       if (new == NULL)
-               new = &noop_qdisc;
+       if (!new) {
+               new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                       TC_H_MAKE(sch->handle, arg), extack);
+               if (!new)
+                       new = &noop_qdisc;
+               else
+                       qdisc_hash_add(new, true);
+       }
 
        *old = qdisc_replace(sch, new, &q->queues[band]);
 
index acd737d..834e9f8 100644 (file)
@@ -1363,8 +1363,10 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        /* Generate an INIT ACK chunk.  */
                        new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC,
                                                     0);
-                       if (!new_obj)
-                               goto nomem;
+                       if (!new_obj) {
+                               error = -ENOMEM;
+                               break;
+                       }
 
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
@@ -1386,7 +1388,8 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        if (!new_obj) {
                                if (cmd->obj.chunk)
                                        sctp_chunk_free(cmd->obj.chunk);
-                               goto nomem;
+                               error = -ENOMEM;
+                               break;
                        }
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
@@ -1433,8 +1436,10 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
 
                        /* Generate a SHUTDOWN chunk.  */
                        new_obj = sctp_make_shutdown(asoc, chunk);
-                       if (!new_obj)
-                               goto nomem;
+                       if (!new_obj) {
+                               error = -ENOMEM;
+                               break;
+                       }
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
                        break;
@@ -1770,11 +1775,17 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        break;
                }
 
-               if (error)
+               if (error) {
+                       cmd = sctp_next_cmd(commands);
+                       while (cmd) {
+                               if (cmd->verb == SCTP_CMD_REPLY)
+                                       sctp_chunk_free(cmd->obj.chunk);
+                               cmd = sctp_next_cmd(commands);
+                       }
                        break;
+               }
        }
 
-out:
        /* If this is in response to a received chunk, wait until
         * we are done with the packet to open the queue so that we don't
         * send multiple packets in response to a single request.
@@ -1789,7 +1800,4 @@ out:
                sp->data_ready_signalled = 0;
 
        return error;
-nomem:
-       error = -ENOMEM;
-       goto out;
 }
index 11255e9..ee49a9f 100644 (file)
@@ -9,7 +9,7 @@ tipc-y  += addr.o bcast.o bearer.o \
           core.o link.o discover.o msg.o  \
           name_distr.o  subscr.o monitor.o name_table.o net.o  \
           netlink.o netlink_compat.o node.o socket.o eth_media.o \
-          topsrv.o socket.o group.o trace.o
+          topsrv.o group.o trace.o
 
 CFLAGS_trace.o += -I$(src)
 
@@ -20,5 +20,3 @@ tipc-$(CONFIG_TIPC_CRYPTO)    += crypto.o
 
 
 obj-$(CONFIG_TIPC_DIAG)        += diag.o
-
-tipc_diag-y    := diag.o
index 0254bb7..2175163 100644 (file)
@@ -204,8 +204,8 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                return -ENOMEM;
        }
 
-       attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1,
-                               sizeof(struct nlattr *), GFP_KERNEL);
+       attrbuf = kcalloc(tipc_genl_family.maxattr + 1,
+                         sizeof(struct nlattr *), GFP_KERNEL);
        if (!attrbuf) {
                err = -ENOMEM;
                goto err_out;
index 6552f98..f9b4fb9 100644 (file)
@@ -287,12 +287,12 @@ static void tipc_sk_respond(struct sock *sk, struct sk_buff *skb, int err)
  *
  * Caller must hold socket lock
  */
-static void tsk_rej_rx_queue(struct sock *sk)
+static void tsk_rej_rx_queue(struct sock *sk, int error)
 {
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue(&sk->sk_receive_queue)))
-               tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
+               tipc_sk_respond(sk, skb, error);
 }
 
 static bool tipc_sk_connected(struct sock *sk)
@@ -545,34 +545,45 @@ static void __tipc_shutdown(struct socket *sock, int error)
        /* Remove pending SYN */
        __skb_queue_purge(&sk->sk_write_queue);
 
-       /* Reject all unreceived messages, except on an active connection
-        * (which disconnects locally & sends a 'FIN+' to peer).
-        */
-       while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-               if (TIPC_SKB_CB(skb)->bytes_read) {
-                       kfree_skb(skb);
-                       continue;
-               }
-               if (!tipc_sk_type_connectionless(sk) &&
-                   sk->sk_state != TIPC_DISCONNECTING) {
-                       tipc_set_sk_state(sk, TIPC_DISCONNECTING);
-                       tipc_node_remove_conn(net, dnode, tsk->portid);
-               }
-               tipc_sk_respond(sk, skb, error);
+       /* Remove partially received buffer if any */
+       skb = skb_peek(&sk->sk_receive_queue);
+       if (skb && TIPC_SKB_CB(skb)->bytes_read) {
+               __skb_unlink(skb, &sk->sk_receive_queue);
+               kfree_skb(skb);
        }
 
-       if (tipc_sk_type_connectionless(sk))
+       /* Reject all unreceived messages if connectionless */
+       if (tipc_sk_type_connectionless(sk)) {
+               tsk_rej_rx_queue(sk, error);
                return;
+       }
 
-       if (sk->sk_state != TIPC_DISCONNECTING) {
+       switch (sk->sk_state) {
+       case TIPC_CONNECTING:
+       case TIPC_ESTABLISHED:
+               tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+               tipc_node_remove_conn(net, dnode, tsk->portid);
+               /* Send a FIN+/- to its peer */
+               skb = __skb_dequeue(&sk->sk_receive_queue);
+               if (skb) {
+                       __skb_queue_purge(&sk->sk_receive_queue);
+                       tipc_sk_respond(sk, skb, error);
+                       break;
+               }
                skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
                                      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
                                      tsk_own_node(tsk), tsk_peer_port(tsk),
                                      tsk->portid, error);
                if (skb)
                        tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
-               tipc_node_remove_conn(net, dnode, tsk->portid);
-               tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+               break;
+       case TIPC_LISTEN:
+               /* Reject all SYN messages */
+               tsk_rej_rx_queue(sk, error);
+               break;
+       default:
+               __skb_queue_purge(&sk->sk_receive_queue);
+               break;
        }
 }
 
@@ -2432,8 +2443,8 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
                        return sock_intr_errno(*timeo_p);
 
                add_wait_queue(sk_sleep(sk), &wait);
-               done = sk_wait_event(sk, timeo_p,
-                                    sk->sk_state != TIPC_CONNECTING, &wait);
+               done = sk_wait_event(sk, timeo_p, tipc_sk_connected(sk),
+                                    &wait);
                remove_wait_queue(sk_sleep(sk), &wait);
        } while (!done);
        return 0;
@@ -2643,7 +2654,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
         * Reject any stray messages received by new socket
         * before the socket lock was taken (very, very unlikely)
         */
-       tsk_rej_rx_queue(new_sk);
+       tsk_rej_rx_queue(new_sk, TIPC_ERR_NO_PORT);
 
        /* Connect new socket to it's peer */
        tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
index 906b1e2..286361e 100644 (file)
@@ -363,7 +363,6 @@ static const struct regmap_config hda_regmap_cfg = {
        .reg_write = hda_reg_write,
        .use_single_read = true,
        .use_single_write = true,
-       .disable_locking = true,
 };
 
 /**
index 1cd4906..f2ea352 100644 (file)
@@ -412,6 +412,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0672:
                alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
                break;
+       case 0x10ec0222:
        case 0x10ec0623:
                alc_update_coef_idx(codec, 0x19, 1<<13, 0);
                break;
@@ -430,6 +431,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
                break;
        case 0x10ec0899:
        case 0x10ec0900:
+       case 0x10ec0b00:
        case 0x10ec1168:
        case 0x10ec1220:
                alc_update_coef_idx(codec, 0x7, 1<<1, 0);
@@ -2526,6 +2528,7 @@ static int patch_alc882(struct hda_codec *codec)
        case 0x10ec0882:
        case 0x10ec0885:
        case 0x10ec0900:
+       case 0x10ec0b00:
        case 0x10ec1220:
                break;
        default:
@@ -7257,6 +7260,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@@ -9255,6 +9259,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
+       HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
        {} /* terminator */
index a1db1bc..5faecbe 100644 (file)
@@ -505,15 +505,20 @@ static int fsl_audmix_probe(struct platform_device *pdev)
                                              ARRAY_SIZE(fsl_audmix_dai));
        if (ret) {
                dev_err(dev, "failed to register ASoC DAI\n");
-               return ret;
+               goto err_disable_pm;
        }
 
        priv->pdev = platform_device_register_data(dev, mdrv, 0, NULL, 0);
        if (IS_ERR(priv->pdev)) {
                ret = PTR_ERR(priv->pdev);
                dev_err(dev, "failed to register platform %s: %d\n", mdrv, ret);
+               goto err_disable_pm;
        }
 
+       return 0;
+
+err_disable_pm:
+       pm_runtime_disable(dev);
        return ret;
 }
 
@@ -521,6 +526,8 @@ static int fsl_audmix_remove(struct platform_device *pdev)
 {
        struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev);
 
+       pm_runtime_disable(&pdev->dev);
+
        if (priv->pdev)
                platform_device_unregister(priv->pdev);
 
index a22f972..5f1bf6d 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/clk.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
-#include <asm/cpu_device_id.h>
 #include <linux/acpi.h>
 #include <sound/core.h>
 #include <sound/jack.h>
index 1c84ff1..8ef0efe 100644 (file)
@@ -479,6 +479,12 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
                goto free_rtd;
 
        rtd->dev = dev;
+       INIT_LIST_HEAD(&rtd->list);
+       INIT_LIST_HEAD(&rtd->component_list);
+       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
+       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
+       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
+       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
        dev_set_drvdata(dev, rtd);
        INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
 
@@ -494,12 +500,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
        /*
         * rtd remaining settings
         */
-       INIT_LIST_HEAD(&rtd->component_list);
-       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
-       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
-       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
-       INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
-
        rtd->card = card;
        rtd->dai_link = dai_link;
        if (!rtd->dai_link->ops)
@@ -1871,6 +1871,8 @@ match:
 
                        /* convert non BE into BE */
                        dai_link->no_pcm = 1;
+                       dai_link->dpcm_playback = 1;
+                       dai_link->dpcm_capture = 1;
 
                        /* override any BE fixups */
                        dai_link->be_hw_params_fixup =
index b286131..92e4f4d 100644 (file)
@@ -548,12 +548,12 @@ static void remove_link(struct snd_soc_component *comp,
        if (dobj->ops && dobj->ops->link_unload)
                dobj->ops->link_unload(comp, dobj);
 
+       list_del(&dobj->list);
+       snd_soc_remove_dai_link(comp->card, link);
+
        kfree(link->name);
        kfree(link->stream_name);
        kfree(link->cpus->dai_name);
-
-       list_del(&dobj->list);
-       snd_soc_remove_dai_link(comp->card, link);
        kfree(link);
 }
 
index cfefcfd..aef6ca1 100644 (file)
@@ -209,7 +209,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
 
        priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains,
                                          sizeof(*priv->pd_dev), GFP_KERNEL);
-       if (!priv)
+       if (!priv->pd_dev)
                return -ENOMEM;
 
        priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains,
@@ -304,6 +304,9 @@ static int imx8_probe(struct snd_sof_dev *sdev)
        }
        sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
 
+       /* set default mailbox offset for FW ready message */
+       sdev->dsp_box.offset = MBOX_OFFSET;
+
        return 0;
 
 exit_pdev_unregister:
index 8796f38..896d219 100644 (file)
@@ -216,6 +216,8 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
                link_dev = hda_link_stream_assign(bus, substream);
                if (!link_dev)
                        return -EBUSY;
+
+               snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
        }
 
        stream_tag = hdac_stream(link_dev)->stream_tag;
@@ -228,8 +230,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
-
        link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
        if (!link)
                return -EINVAL;
@@ -361,6 +361,13 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
        bus = hstream->bus;
        rtd = snd_pcm_substream_chip(substream);
        link_dev = snd_soc_dai_get_dma_data(dai, substream);
+
+       if (!link_dev) {
+               dev_dbg(dai->dev,
+                       "%s: link_dev is not assigned\n", __func__);
+               return -EINVAL;
+       }
+
        hda_stream = hstream_to_sof_hda_stream(link_dev);
 
        /* free the link DMA channel in the FW */
index 5994e10..5fdfbaa 100644 (file)
@@ -826,6 +826,9 @@ void snd_sof_ipc_free(struct snd_sof_dev *sdev)
 {
        struct snd_sof_ipc *ipc = sdev->ipc;
 
+       if (!ipc)
+               return;
+
        /* disable sending of ipc's */
        mutex_lock(&ipc->tx_mutex);
        ipc->disable_ipc_tx = true;
index 3fd28ee..3769d9c 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
  * @slave_config: dma slave channel runtime config pointer
  * @phys_addr: SPDIFRX registers physical base address
  * @lock: synchronization enabling lock
+ * @irq_lock: prevent race condition with IRQ on stream state
  * @cs: channel status buffer
  * @ub: user data buffer
  * @irq: SPDIFRX interrupt line
@@ -240,6 +240,7 @@ struct stm32_spdifrx_data {
        struct dma_slave_config slave_config;
        dma_addr_t phys_addr;
        spinlock_t lock;  /* Sync enabling lock */
+       spinlock_t irq_lock; /* Prevent race condition on stream state */
        unsigned char cs[SPDIFRX_CS_BYTES_NB];
        unsigned char ub[SPDIFRX_UB_BYTES_NB];
        int irq;
@@ -320,6 +321,7 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
 static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
 {
        int cr, cr_mask, imr, ret;
+       unsigned long flags;
 
        /* Enable IRQs */
        imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE;
@@ -327,7 +329,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
        if (ret)
                return ret;
 
-       spin_lock(&spdifrx->lock);
+       spin_lock_irqsave(&spdifrx->lock, flags);
 
        spdifrx->refcount++;
 
@@ -362,7 +364,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
                                "Failed to start synchronization\n");
        }
 
-       spin_unlock(&spdifrx->lock);
+       spin_unlock_irqrestore(&spdifrx->lock, flags);
 
        return ret;
 }
@@ -370,11 +372,12 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
 static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
 {
        int cr, cr_mask, reg;
+       unsigned long flags;
 
-       spin_lock(&spdifrx->lock);
+       spin_lock_irqsave(&spdifrx->lock, flags);
 
        if (--spdifrx->refcount) {
-               spin_unlock(&spdifrx->lock);
+               spin_unlock_irqrestore(&spdifrx->lock, flags);
                return;
        }
 
@@ -393,7 +396,7 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
        regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, &reg);
        regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, &reg);
 
-       spin_unlock(&spdifrx->lock);
+       spin_unlock_irqrestore(&spdifrx->lock, flags);
 }
 
 static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
@@ -480,8 +483,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
        memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB);
        memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB);
 
-       pinctrl_pm_select_default_state(&spdifrx->pdev->dev);
-
        ret = stm32_spdifrx_dma_ctrl_start(spdifrx);
        if (ret < 0)
                return ret;
@@ -513,7 +514,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
 
 end:
        clk_disable_unprepare(spdifrx->kclk);
-       pinctrl_pm_select_sleep_state(&spdifrx->pdev->dev);
 
        return ret;
 }
@@ -665,7 +665,6 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = {
 static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
 {
        struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid;
-       struct snd_pcm_substream *substream = spdifrx->substream;
        struct platform_device *pdev = spdifrx->pdev;
        unsigned int cr, mask, sr, imr;
        unsigned int flags, sync_state;
@@ -745,14 +744,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
                        return IRQ_HANDLED;
                }
 
-               if (substream)
-                       snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+               spin_lock(&spdifrx->irq_lock);
+               if (spdifrx->substream)
+                       snd_pcm_stop(spdifrx->substream,
+                                    SNDRV_PCM_STATE_DISCONNECTED);
+               spin_unlock(&spdifrx->irq_lock);
 
                return IRQ_HANDLED;
        }
 
-       if (err_xrun && substream)
-               snd_pcm_stop_xrun(substream);
+       spin_lock(&spdifrx->irq_lock);
+       if (err_xrun && spdifrx->substream)
+               snd_pcm_stop_xrun(spdifrx->substream);
+       spin_unlock(&spdifrx->irq_lock);
 
        return IRQ_HANDLED;
 }
@@ -761,9 +765,12 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *cpu_dai)
 {
        struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&spdifrx->irq_lock, flags);
        spdifrx->substream = substream;
+       spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
 
        ret = clk_prepare_enable(spdifrx->kclk);
        if (ret)
@@ -839,8 +846,12 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream,
                                   struct snd_soc_dai *cpu_dai)
 {
        struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned long flags;
 
+       spin_lock_irqsave(&spdifrx->irq_lock, flags);
        spdifrx->substream = NULL;
+       spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
+
        clk_disable_unprepare(spdifrx->kclk);
 }
 
@@ -944,6 +955,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
        spdifrx->pdev = pdev;
        init_completion(&spdifrx->cs_completion);
        spin_lock_init(&spdifrx->lock);
+       spin_lock_init(&spdifrx->irq_lock);
 
        platform_set_drvdata(pdev, spdifrx);
 
index a81c206..8218403 100644 (file)
@@ -1397,6 +1397,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
        case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
        case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
+       case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */
        case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
        case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
        case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
index 6e4626a..8f40573 100755 (executable)
@@ -1,6 +1,9 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
 ALL_TESTS="loopback_test"
 NUM_NETIFS=2
 source tc_common.sh
@@ -72,6 +75,11 @@ setup_prepare()
 
        h1_create
        h2_create
+
+       if ethtool -k $h1 | grep loopback | grep -q fixed; then
+               log_test "SKIP: dev $h1 does not support loopback feature"
+               exit $ksft_skip
+       fi
 }
 
 cleanup()