Merge remote-tracking branch 'stable/linux-4.19.y' into rpi-4.19.y
authorpopcornmix <popcornmix@gmail.com>
Mon, 11 Nov 2019 15:58:41 +0000 (15:58 +0000)
committerpopcornmix <popcornmix@gmail.com>
Mon, 11 Nov 2019 15:58:41 +0000 (15:58 +0000)
270 files changed:
Documentation/admin-guide/kernel-parameters.txt
Makefile
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/logicpd-torpedo-som.dtsi
arch/arm/kernel/head-common.S
arch/arm/kernel/head-nommu.S
arch/arm/mach-davinci/dm365.c
arch/arm/mm/alignment.c
arch/arm/mm/proc-v7m.S
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi
arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
arch/arm64/boot/dts/ti/k3-am65-main.dtsi
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/ftrace.c
arch/mips/bcm63xx/prom.c
arch/mips/fw/sni/sniprom.c
arch/mips/include/asm/bmips.h
arch/mips/include/asm/cmpxchg.h
arch/mips/kernel/smp-bmips.c
arch/powerpc/include/asm/cputable.h
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/tlb-radix.c
arch/powerpc/platforms/powernv/memtrace.c
arch/powerpc/platforms/powernv/smp.c
arch/s390/include/asm/uaccess.h
arch/s390/kernel/idle.c
arch/s390/mm/cmm.c
arch/x86/events/amd/core.c
arch/x86/include/asm/intel-family.h
arch/x86/platform/efi/efi.c
arch/x86/xen/enlighten.c
drivers/block/nbd.c
drivers/block/zram/zram_drv.c
drivers/clk/imgtec/clk-boston.c
drivers/crypto/chelsio/chtls/chtls_cm.c
drivers/crypto/chelsio/chtls/chtls_io.c
drivers/dma/qcom/bam_dma.c
drivers/dma/ti/cppi41.c
drivers/firmware/efi/cper.c
drivers/gpio/gpio-max77620.c
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
drivers/hid/hid-axff.c
drivers/hid/hid-core.c
drivers/hid/hid-dr.c
drivers/hid/hid-emsff.c
drivers/hid/hid-gaff.c
drivers/hid/hid-holtekff.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lg2ff.c
drivers/hid/hid-lg3ff.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lgff.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-sony.c
drivers/hid/hid-steam.c
drivers/hid/hid-tmff.c
drivers/hid/hid-zpff.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/i2c/busses/i2c-stm32f7.c
drivers/iio/accel/bmc150-accel-core.c
drivers/iio/adc/meson_saradc.c
drivers/iio/imu/adis_buffer.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/irqchip/irq-gic-v3-its.c
drivers/isdn/capi/capi.c
drivers/md/bcache/sysfs.c
drivers/md/dm-snap.c
drivers/media/platform/vimc/vimc-sensor.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/phy/bcm7xxx.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lan78xx.c
drivers/net/usb/r8152.c
drivers/net/usb/sr9800.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath6kl/usb.c
drivers/net/wireless/ath/wil6210/txrx_edma.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/realtek/rtlwifi/ps.c
drivers/nfc/pn533/usb.c
drivers/of/unittest.c
drivers/pci/pcie/pme.c
drivers/pci/quirks.c
drivers/pinctrl/bcm/pinctrl-ns2-mux.c
drivers/platform/x86/intel_atomisp2_pm.c
drivers/platform/x86/pmc_atom.c
drivers/power/supply/max14656_charger_detector.c
drivers/regulator/of_regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/ti-abb-regulator.c
drivers/rtc/rtc-pcf8523.c
drivers/scsi/Kconfig
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_nvmet.h
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/sni_53c710.c
drivers/staging/mt7621-pinctrl/Kconfig
drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/target/iscsi/cxgbit/cxgbit_cm.c
drivers/target/target_core_device.c
drivers/thunderbolt/nhi.c
drivers/tty/n_hdlc.c
drivers/tty/serial/8250/8250_men_mcb.c
drivers/tty/serial/owl-uart.c
drivers/tty/serial/serial_mctrl_gpio.c
drivers/usb/core/hub.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/udc/core.c
drivers/usb/host/xhci-debugfs.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/serial/whiteheat.c
drivers/usb/serial/whiteheat.h
drivers/usb/storage/scsiglue.c
drivers/usb/storage/uas.c
drivers/virt/vboxguest/vboxguest_utils.c
fs/binfmt_script.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/netmisc.c
fs/cifs/smb2file.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/ext4/ioctl.c
fs/f2fs/recovery.c
fs/f2fs/super.c
fs/fuse/dir.c
fs/fuse/file.c
fs/nfs/delegation.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/write.c
fs/ocfs2/aops.c
fs/ocfs2/ioctl.c
fs/ocfs2/xattr.c
include/linux/gfp.h
include/linux/skbuff.h
include/net/busy_poll.h
include/net/flow_dissector.h
include/net/fq.h
include/net/fq_impl.h
include/net/llc_conn.h
include/net/net_namespace.h
include/net/sch_generic.h
include/net/sock.h
include/trace/events/rxrpc.h
kernel/sched/cputime.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
net/atm/common.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/hard-interface.c
net/batman-adv/types.h
net/bluetooth/af_bluetooth.c
net/caif/caif_socket.c
net/core/datagram.c
net/core/dev.c
net/core/ethtool.c
net/core/flow_dissector.c
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/ipv4.c
net/decnet/af_decnet.c
net/dsa/dsa2.c
net/ipv4/datagram.c
net/ipv4/fib_frontend.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_gre.c
net/ipv6/udp.c
net/llc/llc_c_ac.c
net/llc/llc_conn.c
net/llc/llc_s_ac.c
net/llc/llc_sap.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/nfc/llcp_sock.c
net/openvswitch/datapath.c
net/phonet/socket.c
net/rxrpc/peer_object.c
net/rxrpc/sendmsg.c
net/sched/sch_hhf.c
net/sched/sch_netem.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c
net/sctp/socket.c
net/tipc/socket.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/wireless/Makefile
net/wireless/nl80211.c
samples/bpf/bpf_load.c
scripts/setlocalversion
sound/core/timer.c
sound/firewire/bebob/bebob_stream.c
sound/hda/hdac_controller.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/pcm3168a.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_adsp.c
sound/soc/rockchip/rockchip_i2s.c
sound/usb/quirks.c
tools/lib/subcmd/Makefile
tools/perf/arch/powerpc/util/header.c
tools/perf/arch/s390/util/header.c
tools/perf/arch/x86/util/header.c
tools/perf/builtin-c2c.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-script.c
tools/perf/pmu-events/jevents.c
tools/perf/tests/perf-hooks.c
tools/perf/util/annotate.c
tools/perf/util/map.c
tools/power/x86/turbostat/turbostat.c
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/reuseport_dualstack.c
tools/testing/selftests/powerpc/mm/Makefile
tools/testing/selftests/powerpc/mm/tlbie_test.c [new file with mode: 0644]

index 16607b1..a855f83 100644 (file)
                                the unplug protocol
                        never -- do not unplug even if version check succeeds
 
+       xen_legacy_crash        [X86,XEN]
+                       Crash from Xen panic notifier, without executing late
+                       panic() code such as dumping handler.
+
        xen_nopvspin    [X86,XEN]
                        Disables the ticketlock slowpath using Xen PV
                        optimizations.
index 3c146e8..c2c0cf2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 4
 PATCHLEVEL = 19
-SUBLEVEL = 81
+SUBLEVEL = 83
 EXTRAVERSION =
 NAME = "People's Front"
 
@@ -835,6 +835,12 @@ KBUILD_CFLAGS   += $(call cc-option,-Werror=designated-init)
 # change __FILE__ to the relative path from the srctree
 KBUILD_CFLAGS  += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
 
+# ensure -fcf-protection is disabled when using retpoline as it is
+# incompatible with -mindirect-branch=thunk-extern
+ifdef CONFIG_RETPOLINE
+KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
+endif
+
 # use the deterministic mode of AR if available
 KBUILD_ARFLAGS := $(call ar-option,D)
 
index a7f697b..90f5bdf 100644 (file)
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302d0000 0x10000>;
                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
                                         <&clks IMX7D_GPT1_ROOT_CLK>;
                                clock-names = "ipg", "per";
                        };
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302e0000 0x10000>;
                                interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
                                         <&clks IMX7D_GPT2_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302f0000 0x10000>;
                                interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
                                         <&clks IMX7D_GPT3_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x30300000 0x10000>;
                                interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
                                         <&clks IMX7D_GPT4_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
index 7d2302e..9354da4 100644 (file)
 &twl_gpio {
        ti,use-leds;
 };
+
+&twl_keypad {
+       status = "disabled";
+};
index 997b023..9328f20 100644 (file)
@@ -72,7 +72,7 @@ ENDPROC(__vet_atags)
  * The following fragment of code is executed with the MMU on in MMU mode,
  * and uses absolute addresses; this is not position independent.
  *
- *  r0  = cp#15 control register
+ *  r0  = cp#15 control register (exc_ret for M-class)
  *  r1  = machine ID
  *  r2  = atags/dtb pointer
  *  r9  = processor ID
@@ -141,7 +141,8 @@ __mmap_switched_data:
 #ifdef CONFIG_CPU_CP15
        .long   cr_alignment                    @ r3
 #else
-       .long   0                               @ r3
+M_CLASS(.long  exc_ret)                        @ r3
+AR_CLASS(.long 0)                              @ r3
 #endif
        .size   __mmap_switched_data, . - __mmap_switched_data
 
index cab8947..326a97a 100644 (file)
@@ -205,6 +205,8 @@ M_CLASS(streq       r3, [r12, #PMSAv8_MAIR1])
        bic     r0, r0, #V7M_SCB_CCR_IC
 #endif
        str     r0, [r12, V7M_SCB_CCR]
+       /* Pass exc_ret to __mmap_switched */
+       mov     r0, r10
 #endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */
        ret     lr
 ENDPROC(__after_proc_init)
index 4266591..83ca89a 100644 (file)
@@ -458,8 +458,8 @@ static s8 dm365_queue_priority_mapping[][2] = {
 };
 
 static const struct dma_slave_map dm365_edma_map[] = {
-       { "davinci-mcbsp.0", "tx", EDMA_FILTER_PARAM(0, 2) },
-       { "davinci-mcbsp.0", "rx", EDMA_FILTER_PARAM(0, 3) },
+       { "davinci-mcbsp", "tx", EDMA_FILTER_PARAM(0, 2) },
+       { "davinci-mcbsp", "rx", EDMA_FILTER_PARAM(0, 3) },
        { "davinci_voicecodec", "tx", EDMA_FILTER_PARAM(0, 2) },
        { "davinci_voicecodec", "rx", EDMA_FILTER_PARAM(0, 3) },
        { "spi_davinci.2", "tx", EDMA_FILTER_PARAM(0, 10) },
index bd2c739..84a6bba 100644 (file)
@@ -768,6 +768,36 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
        return NULL;
 }
 
+static int alignment_get_arm(struct pt_regs *regs, u32 *ip, unsigned long *inst)
+{
+       u32 instr = 0;
+       int fault;
+
+       if (user_mode(regs))
+               fault = get_user(instr, ip);
+       else
+               fault = probe_kernel_address(ip, instr);
+
+       *inst = __mem_to_opcode_arm(instr);
+
+       return fault;
+}
+
+static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst)
+{
+       u16 instr = 0;
+       int fault;
+
+       if (user_mode(regs))
+               fault = get_user(instr, ip);
+       else
+               fault = probe_kernel_address(ip, instr);
+
+       *inst = __mem_to_opcode_thumb16(instr);
+
+       return fault;
+}
+
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
@@ -775,10 +805,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        unsigned long instr = 0, instrptr;
        int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
        unsigned int type;
-       unsigned int fault;
        u16 tinstr = 0;
        int isize = 4;
        int thumb2_32b = 0;
+       int fault;
 
        if (interrupts_enabled(regs))
                local_irq_enable();
@@ -787,15 +817,14 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
        if (thumb_mode(regs)) {
                u16 *ptr = (u16 *)(instrptr & ~1);
-               fault = probe_kernel_address(ptr, tinstr);
-               tinstr = __mem_to_opcode_thumb16(tinstr);
+
+               fault = alignment_get_thumb(regs, ptr, &tinstr);
                if (!fault) {
                        if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
                            IS_T32(tinstr)) {
                                /* Thumb-2 32-bit */
-                               u16 tinst2 = 0;
-                               fault = probe_kernel_address(ptr + 1, tinst2);
-                               tinst2 = __mem_to_opcode_thumb16(tinst2);
+                               u16 tinst2;
+                               fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
                                instr = __opcode_thumb32_compose(tinstr, tinst2);
                                thumb2_32b = 1;
                        } else {
@@ -804,8 +833,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                        }
                }
        } else {
-               fault = probe_kernel_address((void *)instrptr, instr);
-               instr = __mem_to_opcode_arm(instr);
+               fault = alignment_get_arm(regs, (void *)instrptr, &instr);
        }
 
        if (fault) {
index 92e8418..9c2978c 100644 (file)
@@ -135,13 +135,11 @@ __v7m_setup_cont:
        dsb
        mov     r6, lr                  @ save LR
        ldr     sp, =init_thread_union + THREAD_START_SP
-       stmia   sp, {r0-r3, r12}
        cpsie   i
        svc     #0
 1:     cpsid   i
-       ldr     r0, =exc_ret
-       orr     lr, lr, #EXC_RET_THREADMODE_PROCESSSTACK
-       str     lr, [r0]
+       /* Calculate exc_ret */
+       orr     r10, lr, #EXC_RET_THREADMODE_PROCESSSTACK
        ldmia   sp, {r0-r3, r12}
        str     r5, [r12, #11 * 4]      @ restore the original SVC vector entry
        mov     lr, r6                  @ restore LR
index 24f1aac..d5b6e81 100644 (file)
                reg = <1>;
        };
 };
+
+&reg_dc1sw {
+       /*
+        * Ethernet PHY needs 30ms to properly power up and some more
+        * to initialize. 100ms should be plenty of time to finish
+        * whole process.
+        */
+       regulator-enable-ramp-delay = <100000>;
+};
index c21f233..285cb71 100644 (file)
 };
 
 &reg_dc1sw {
+       /*
+        * Ethernet PHY needs 30ms to properly power up and some more
+        * to initialize. 100ms should be plenty of time to finish
+        * whole process.
+        */
+       regulator-enable-ramp-delay = <100000>;
        regulator-name = "vcc-phy";
 };
 
index 8a3a770..56789cc 100644 (file)
 
                pinmux: pinmux@14029c {
                        compatible = "pinctrl-single";
-                       reg = <0x0014029c 0x250>;
+                       reg = <0x0014029c 0x26c>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        pinctrl-single,register-width = <32>;
                        pinctrl-single,function-mask = <0xf>;
                        pinctrl-single,gpio-range = <
-                               &range 0 154 MODE_GPIO
+                               &range 0  91 MODE_GPIO
+                               &range 95 60 MODE_GPIO
                                >;
                        range: gpio-range {
                                #pinctrl-single,gpio-range-cells = <3>;
index e283480..84101ea 100644 (file)
                                        <&pinmux 108 16 27>,
                                        <&pinmux 135 77 6>,
                                        <&pinmux 141 67 4>,
-                                       <&pinmux 145 149 6>,
-                                       <&pinmux 151 91 4>;
+                                       <&pinmux 145 149 6>;
                };
 
                i2c1: i2c@e0000 {
index 2409344..e23c576 100644 (file)
@@ -21,7 +21,7 @@
                 */
                interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
 
-               gic_its: gic-its@18200000 {
+               gic_its: gic-its@1820000 {
                        compatible = "arm,gic-v3-its";
                        reg = <0x01820000 0x10000>;
                        msi-controller;
index 9b7d5ab..fa770c0 100644 (file)
@@ -68,6 +68,7 @@
 #define ARM_CPU_IMP_BRCM               0x42
 #define ARM_CPU_IMP_QCOM               0x51
 #define ARM_CPU_IMP_NVIDIA             0x4E
+#define ARM_CPU_IMP_HISI               0x48
 
 #define ARM_CPU_PART_AEM_V8            0xD0F
 #define ARM_CPU_PART_FOUNDATION                0xD00
@@ -96,6 +97,8 @@
 #define NVIDIA_CPU_PART_DENVER         0x003
 #define NVIDIA_CPU_PART_CARMEL         0x004
 
+#define HISI_CPU_PART_TSV110           0xD01
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
 #define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER)
 #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
+#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
 
 #ifndef __ASSEMBLY__
 
index 78b942c..e060c27 100644 (file)
 #define PROT_DEFAULT           (_PROT_DEFAULT | PTE_MAYBE_NG)
 #define PROT_SECT_DEFAULT      (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
 
-#define PROT_DEVICE_nGnRnE     (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
-#define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
-#define PROT_NORMAL_WT         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
-#define PROT_NORMAL            (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
+#define PROT_DEVICE_nGnRnE     (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
+#define PROT_NORMAL_WT         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
+#define PROT_NORMAL            (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
 
 #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_SECT_NORMAL       (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
@@ -91,8 +91,9 @@
 #define PAGE_S2_DEVICE         __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PAGE_S2_XN)
 
 #define PAGE_NONE              __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
-#define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
-#define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
+/* shared+writable pages are clean by default, hence PTE_RDONLY|PTE_WRITE */
+#define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
+#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)
index 70852e9..9d3442d 100644 (file)
@@ -177,6 +177,9 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops)
        struct insn_emulation *insn;
 
        insn = kzalloc(sizeof(*insn), GFP_KERNEL);
+       if (!insn)
+               return;
+
        insn->ops = ops;
        insn->min = INSN_UNDEF;
 
@@ -241,6 +244,8 @@ static void __init register_insn_emulation_sysctl(void)
 
        insns_sysctl = kcalloc(nr_insn_emulated + 1, sizeof(*sysctl),
                               GFP_KERNEL);
+       if (!insns_sysctl)
+               return;
 
        raw_spin_lock_irqsave(&insn_emulation_lock, flags);
        list_for_each_entry(insn, &insn_emulation, node) {
index ff5beb5..220ebfa 100644 (file)
@@ -906,6 +906,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
                MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+               MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
                { /* sentinel */ }
        };
        char const *str = "kpti command line option";
index 7eff8af..b661839 100644 (file)
@@ -119,10 +119,16 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
                        /*
                         * Ensure updated trampoline is visible to instruction
-                        * fetch before we patch in the branch.
+                        * fetch before we patch in the branch. Although the
+                        * architecture doesn't require an IPI in this case,
+                        * Neoverse-N1 erratum #1542419 does require one
+                        * if the TLB maintenance in module_enable_ro() is
+                        * skipped due to rodata_enabled. It doesn't seem worth
+                        * it to make it conditional given that this is
+                        * certainly not a fast-path.
                         */
-                       __flush_icache_range((unsigned long)&dst[0],
-                                            (unsigned long)&dst[1]);
+                       flush_icache_range((unsigned long)&dst[0],
+                                          (unsigned long)&dst[1]);
                }
                addr = (unsigned long)dst;
 #else /* CONFIG_ARM64_MODULE_PLTS */
index 7019e29..bbbf805 100644 (file)
@@ -84,7 +84,7 @@ void __init prom_init(void)
                 * Here we will start up CPU1 in the background and ask it to
                 * reconfigure itself then go back to sleep.
                 */
-               memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20);
+               memcpy((void *)0xa0000200, bmips_smp_movevec, 0x20);
                __sync();
                set_c0_cause(C_SW0);
                cpumask_set_cpu(1, &bmips_booted_mask);
index 8772617..80112f2 100644 (file)
@@ -43,7 +43,7 @@
 
 /* O32 stack has to be 8-byte aligned. */
 static u64 o32_stk[4096];
-#define O32_STK          &o32_stk[sizeof(o32_stk)]
+#define O32_STK          (&o32_stk[ARRAY_SIZE(o32_stk)])
 
 #define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
                                     __asm__(#fun " = call_o32")
index bf6a8af..581a6a3 100644 (file)
@@ -75,11 +75,11 @@ static inline int register_bmips_smp_ops(void)
 #endif
 }
 
-extern char bmips_reset_nmi_vec;
-extern char bmips_reset_nmi_vec_end;
-extern char bmips_smp_movevec;
-extern char bmips_smp_int_vec;
-extern char bmips_smp_int_vec_end;
+extern char bmips_reset_nmi_vec[];
+extern char bmips_reset_nmi_vec_end[];
+extern char bmips_smp_movevec[];
+extern char bmips_smp_int_vec[];
+extern char bmips_smp_int_vec_end[];
 
 extern int bmips_smp_enabled;
 extern int bmips_cpu_offset;
index 89e9fb7..520ca16 100644 (file)
@@ -73,8 +73,8 @@ extern unsigned long __xchg_called_with_bad_pointer(void)
 extern unsigned long __xchg_small(volatile void *ptr, unsigned long val,
                                  unsigned int size);
 
-static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
-                                  int size)
+static __always_inline
+unsigned long __xchg(volatile void *ptr, unsigned long x, int size)
 {
        switch (size) {
        case 1:
@@ -146,8 +146,9 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
 extern unsigned long __cmpxchg_small(volatile void *ptr, unsigned long old,
                                     unsigned long new, unsigned int size);
 
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, unsigned int size)
+static __always_inline
+unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                       unsigned long new, unsigned int size)
 {
        switch (size) {
        case 1:
index 159e83a..5ec546b 100644 (file)
@@ -457,10 +457,10 @@ static void bmips_wr_vec(unsigned long dst, char *start, char *end)
 
 static inline void bmips_nmi_handler_setup(void)
 {
-       bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec,
-               &bmips_reset_nmi_vec_end);
-       bmips_wr_vec(BMIPS_WARM_RESTART_VEC, &bmips_smp_int_vec,
-               &bmips_smp_int_vec_end);
+       bmips_wr_vec(BMIPS_NMI_RESET_VEC, bmips_reset_nmi_vec,
+               bmips_reset_nmi_vec_end);
+       bmips_wr_vec(BMIPS_WARM_RESTART_VEC, bmips_smp_int_vec,
+               bmips_smp_int_vec_end);
 }
 
 struct reset_vec_info {
index 6a6804c..3ce690e 100644 (file)
@@ -214,6 +214,7 @@ static inline void cpu_feature_keys_init(void) { }
 #define CPU_FTR_P9_TM_XER_SO_BUG       LONG_ASM_CONST(0x0000200000000000)
 #define CPU_FTR_P9_TLBIE_STQ_BUG       LONG_ASM_CONST(0x0000400000000000)
 #define CPU_FTR_P9_TIDR                        LONG_ASM_CONST(0x0000800000000000)
+#define CPU_FTR_P9_TLBIE_ERAT_BUG      LONG_ASM_CONST(0x0001000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -460,7 +461,7 @@ static inline void cpu_feature_keys_init(void) { }
            CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
            CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
            CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \
-           CPU_FTR_P9_TLBIE_STQ_BUG | CPU_FTR_P9_TIDR)
+           CPU_FTR_P9_TLBIE_STQ_BUG | CPU_FTR_P9_TLBIE_ERAT_BUG | CPU_FTR_P9_TIDR)
 #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
 #define CPU_FTRS_POWER9_DD2_1 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1)
 #define CPU_FTRS_POWER9_DD2_2 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1 | \
index f3b8e04..c6f4190 100644 (file)
@@ -717,6 +717,8 @@ static __init void update_tlbie_feature_flag(unsigned long pvr)
                        WARN_ONCE(1, "Unknown PVR");
                        cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_STQ_BUG;
                }
+
+               cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_ERAT_BUG;
        }
 }
 
index 7c68d83..02ab86b 100644 (file)
@@ -434,6 +434,37 @@ static inline int is_mmio_hpte(unsigned long v, unsigned long r)
                (HPTE_R_KEY_HI | HPTE_R_KEY_LO));
 }
 
+static inline void fixup_tlbie_lpid(unsigned long rb_value, unsigned long lpid)
+{
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               /* Radix flush for a hash guest */
+
+               unsigned long rb,rs,prs,r,ric;
+
+               rb = PPC_BIT(52); /* IS = 2 */
+               rs = 0;  /* lpid = 0 */
+               prs = 0; /* partition scoped */
+               r = 1;   /* radix format */
+               ric = 0; /* RIC_FLSUH_TLB */
+
+               /*
+                * Need the extra ptesync to make sure we don't
+                * re-order the tlbie
+                */
+               asm volatile("ptesync": : :"memory");
+               asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
+                            : : "r"(rb), "i"(r), "i"(prs),
+                              "i"(ric), "r"(rs) : "memory");
+       }
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
+                            "r" (rb_value), "r" (lpid));
+       }
+}
+
 static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
                      long npages, int global, bool need_sync)
 {
@@ -452,16 +483,7 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
                                     "r" (rbvalues[i]), "r" (kvm->arch.lpid));
                }
 
-               if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
-                       /*
-                        * Need the extra ptesync to make sure we don't
-                        * re-order the tlbie
-                        */
-                       asm volatile("ptesync": : :"memory");
-                       asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
-                                    "r" (rbvalues[0]), "r" (kvm->arch.lpid));
-               }
-
+               fixup_tlbie_lpid(rbvalues[i - 1], kvm->arch.lpid);
                asm volatile("eieio; tlbsync; ptesync" : : : "memory");
        } else {
                if (need_sync)
index 0c13561..42a48c5 100644 (file)
@@ -201,8 +201,31 @@ static inline unsigned long  ___tlbie(unsigned long vpn, int psize,
        return va;
 }
 
-static inline void fixup_tlbie(unsigned long vpn, int psize, int apsize, int ssize)
+static inline void fixup_tlbie_vpn(unsigned long vpn, int psize,
+                                  int apsize, int ssize)
 {
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               /* Radix flush for a hash guest */
+
+               unsigned long rb,rs,prs,r,ric;
+
+               rb = PPC_BIT(52); /* IS = 2 */
+               rs = 0;  /* lpid = 0 */
+               prs = 0; /* partition scoped */
+               r = 1;   /* radix format */
+               ric = 0; /* RIC_FLSUH_TLB */
+
+               /*
+                * Need the extra ptesync to make sure we don't
+                * re-order the tlbie
+                */
+               asm volatile("ptesync": : :"memory");
+               asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
+                            : : "r"(rb), "i"(r), "i"(prs),
+                              "i"(ric), "r"(rs) : "memory");
+       }
+
+
        if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
                /* Need the extra ptesync to ensure we don't reorder tlbie*/
                asm volatile("ptesync": : :"memory");
@@ -287,7 +310,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize,
                asm volatile("ptesync": : :"memory");
        } else {
                __tlbie(vpn, psize, apsize, ssize);
-               fixup_tlbie(vpn, psize, apsize, ssize);
+               fixup_tlbie_vpn(vpn, psize, apsize, ssize);
                asm volatile("eieio; tlbsync; ptesync": : :"memory");
        }
        if (lock_tlbie && !use_local)
@@ -860,7 +883,7 @@ static void native_flush_hash_range(unsigned long number, int local)
                /*
                 * Just do one more with the last used values.
                 */
-               fixup_tlbie(vpn, psize, psize, ssize);
+               fixup_tlbie_vpn(vpn, psize, psize, ssize);
                asm volatile("eieio; tlbsync; ptesync":::"memory");
 
                if (lock_tlbie)
index 0cddae4..62be0e5 100644 (file)
@@ -215,21 +215,82 @@ static inline void __tlbie_lpid_va(unsigned long va, unsigned long lpid,
        trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
 }
 
-static inline void fixup_tlbie(void)
+
+static inline void fixup_tlbie_va(unsigned long va, unsigned long pid,
+                                 unsigned long ap)
 {
-       unsigned long pid = 0;
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_va(va, 0, ap, RIC_FLUSH_TLB);
+       }
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_va(va, pid, ap, RIC_FLUSH_TLB);
+       }
+}
+
+static inline void fixup_tlbie_va_range(unsigned long va, unsigned long pid,
+                                       unsigned long ap)
+{
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_pid(0, RIC_FLUSH_TLB);
+       }
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_va(va, pid, ap, RIC_FLUSH_TLB);
+       }
+}
+
+static inline void fixup_tlbie_pid(unsigned long pid)
+{
+       /*
+        * We can use any address for the invalidation, pick one which is
+        * probably unused as an optimisation.
+        */
        unsigned long va = ((1UL << 52) - 1);
 
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_pid(0, RIC_FLUSH_TLB);
+       }
+
        if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
                asm volatile("ptesync": : :"memory");
                __tlbie_va(va, pid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
        }
 }
 
+
+static inline void fixup_tlbie_lpid_va(unsigned long va, unsigned long lpid,
+                                      unsigned long ap)
+{
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_lpid_va(va, 0, ap, RIC_FLUSH_TLB);
+       }
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_lpid_va(va, lpid, ap, RIC_FLUSH_TLB);
+       }
+}
+
 static inline void fixup_tlbie_lpid(unsigned long lpid)
 {
+       /*
+        * We can use any address for the invalidation, pick one which is
+        * probably unused as an optimisation.
+        */
        unsigned long va = ((1UL << 52) - 1);
 
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_lpid(0, RIC_FLUSH_TLB);
+       }
+
        if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
                asm volatile("ptesync": : :"memory");
                __tlbie_lpid_va(va, lpid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
@@ -277,6 +338,7 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
        switch (ric) {
        case RIC_FLUSH_TLB:
                __tlbie_pid(pid, RIC_FLUSH_TLB);
+               fixup_tlbie_pid(pid);
                break;
        case RIC_FLUSH_PWC:
                __tlbie_pid(pid, RIC_FLUSH_PWC);
@@ -284,8 +346,8 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
        case RIC_FLUSH_ALL:
        default:
                __tlbie_pid(pid, RIC_FLUSH_ALL);
+               fixup_tlbie_pid(pid);
        }
-       fixup_tlbie();
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -329,6 +391,7 @@ static inline void _tlbie_lpid(unsigned long lpid, unsigned long ric)
        switch (ric) {
        case RIC_FLUSH_TLB:
                __tlbie_lpid(lpid, RIC_FLUSH_TLB);
+               fixup_tlbie_lpid(lpid);
                break;
        case RIC_FLUSH_PWC:
                __tlbie_lpid(lpid, RIC_FLUSH_PWC);
@@ -336,8 +399,8 @@ static inline void _tlbie_lpid(unsigned long lpid, unsigned long ric)
        case RIC_FLUSH_ALL:
        default:
                __tlbie_lpid(lpid, RIC_FLUSH_ALL);
+               fixup_tlbie_lpid(lpid);
        }
-       fixup_tlbie_lpid(lpid);
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -410,6 +473,8 @@ static inline void __tlbie_va_range(unsigned long start, unsigned long end,
 
        for (addr = start; addr < end; addr += page_size)
                __tlbie_va(addr, pid, ap, RIC_FLUSH_TLB);
+
+       fixup_tlbie_va_range(addr - page_size, pid, ap);
 }
 
 static inline void _tlbie_va(unsigned long va, unsigned long pid,
@@ -419,7 +484,7 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
 
        asm volatile("ptesync": : :"memory");
        __tlbie_va(va, pid, ap, ric);
-       fixup_tlbie();
+       fixup_tlbie_va(va, pid, ap);
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -430,7 +495,7 @@ static inline void _tlbie_lpid_va(unsigned long va, unsigned long lpid,
 
        asm volatile("ptesync": : :"memory");
        __tlbie_lpid_va(va, lpid, ap, ric);
-       fixup_tlbie_lpid(lpid);
+       fixup_tlbie_lpid_va(va, lpid, ap);
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -442,7 +507,6 @@ static inline void _tlbie_va_range(unsigned long start, unsigned long end,
        if (also_pwc)
                __tlbie_pid(pid, RIC_FLUSH_PWC);
        __tlbie_va_range(start, end, pid, page_size, psize);
-       fixup_tlbie();
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -773,7 +837,7 @@ is_local:
                        if (gflush)
                                __tlbie_va_range(gstart, gend, pid,
                                                PUD_SIZE, MMU_PAGE_1G);
-                       fixup_tlbie();
+
                        asm volatile("eieio; tlbsync; ptesync": : :"memory");
                }
        }
index a29fdf8..232bf59 100644 (file)
@@ -70,6 +70,7 @@ static int change_memblock_state(struct memory_block *mem, void *arg)
        return 0;
 }
 
+/* called with device_hotplug_lock held */
 static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages)
 {
        u64 end_pfn = start_pfn + nr_pages - 1;
@@ -110,6 +111,7 @@ static u64 memtrace_alloc_node(u32 nid, u64 size)
        /* Trace memory needs to be aligned to the size */
        end_pfn = round_down(end_pfn - nr_pages, nr_pages);
 
+       lock_device_hotplug();
        for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) {
                if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) {
                        /*
@@ -118,7 +120,6 @@ static u64 memtrace_alloc_node(u32 nid, u64 size)
                         * we never try to remove memory that spans two iomem
                         * resources.
                         */
-                       lock_device_hotplug();
                        end_pfn = base_pfn + nr_pages;
                        for (pfn = base_pfn; pfn < end_pfn; pfn += bytes>> PAGE_SHIFT) {
                                remove_memory(nid, pfn << PAGE_SHIFT, bytes);
@@ -127,6 +128,7 @@ static u64 memtrace_alloc_node(u32 nid, u64 size)
                        return base_pfn << PAGE_SHIFT;
                }
        }
+       unlock_device_hotplug();
 
        return 0;
 }
index db09c70..fdd9577 100644 (file)
@@ -150,20 +150,25 @@ static int pnv_smp_cpu_disable(void)
        return 0;
 }
 
+static void pnv_flush_interrupts(void)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               if (xive_enabled())
+                       xive_flush_interrupt();
+               else
+                       icp_opal_flush_interrupt();
+       } else {
+               icp_native_flush_interrupt();
+       }
+}
+
 static void pnv_smp_cpu_kill_self(void)
 {
+       unsigned long srr1, unexpected_mask, wmask;
        unsigned int cpu;
-       unsigned long srr1, wmask;
        u64 lpcr_val;
 
        /* Standard hot unplug procedure */
-       /*
-        * This hard disables local interurpts, ensuring we have no lazy
-        * irqs pending.
-        */
-       WARN_ON(irqs_disabled());
-       hard_irq_disable();
-       WARN_ON(lazy_irq_pending());
 
        idle_task_exit();
        current->active_mm = NULL; /* for sanity */
@@ -177,6 +182,27 @@ static void pnv_smp_cpu_kill_self(void)
                wmask = SRR1_WAKEMASK_P8;
 
        /*
+        * This turns the irq soft-disabled state we're called with, into a
+        * hard-disabled state with pending irq_happened interrupts cleared.
+        *
+        * PACA_IRQ_DEC   - Decrementer should be ignored.
+        * PACA_IRQ_HMI   - Can be ignored, processing is done in real mode.
+        * PACA_IRQ_DBELL, EE, PMI - Unexpected.
+        */
+       hard_irq_disable();
+       if (generic_check_cpu_restart(cpu))
+               goto out;
+
+       unexpected_mask = ~(PACA_IRQ_DEC | PACA_IRQ_HMI | PACA_IRQ_HARD_DIS);
+       if (local_paca->irq_happened & unexpected_mask) {
+               if (local_paca->irq_happened & PACA_IRQ_EE)
+                       pnv_flush_interrupts();
+               DBG("CPU%d Unexpected exit while offline irq_happened=%lx!\n",
+                               cpu, local_paca->irq_happened);
+       }
+       local_paca->irq_happened = PACA_IRQ_HARD_DIS;
+
+       /*
         * We don't want to take decrementer interrupts while we are
         * offline, so clear LPCR:PECE1. We keep PECE2 (and
         * LPCR_PECE_HVEE on P9) enabled so as to let IPIs in.
@@ -201,6 +227,7 @@ static void pnv_smp_cpu_kill_self(void)
 
                srr1 = pnv_cpu_offline(cpu);
 
+               WARN_ON_ONCE(!irqs_disabled());
                WARN_ON(lazy_irq_pending());
 
                /*
@@ -216,13 +243,7 @@ static void pnv_smp_cpu_kill_self(void)
                 */
                if (((srr1 & wmask) == SRR1_WAKEEE) ||
                    ((srr1 & wmask) == SRR1_WAKEHVI)) {
-                       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
-                               if (xive_enabled())
-                                       xive_flush_interrupt();
-                               else
-                                       icp_opal_flush_interrupt();
-                       } else
-                               icp_native_flush_interrupt();
+                       pnv_flush_interrupts();
                } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
                        unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
                        asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
@@ -270,7 +291,7 @@ static void pnv_smp_cpu_kill_self(void)
         */
        lpcr_val = mfspr(SPRN_LPCR) | (u64)LPCR_PECE1;
        pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val);
-
+out:
        DBG("CPU%d coming online...\n", cpu);
 }
 
index 5332f62..40194f8 100644 (file)
@@ -84,7 +84,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n);
        __rc;                                                   \
 })
 
-static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
+static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 {
        unsigned long spec = 0x010000UL;
        int rc;
@@ -114,7 +114,7 @@ static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
        return rc;
 }
 
-static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
+static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 {
        unsigned long spec = 0x01UL;
        int rc;
index b9d8fe4..8f84568 100644 (file)
@@ -69,18 +69,26 @@ DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
 static ssize_t show_idle_time(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
+       unsigned long long now, idle_time, idle_enter, idle_exit, in_idle;
        struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long now, idle_time, idle_enter, idle_exit;
        unsigned int seq;
 
        do {
-               now = get_tod_clock();
                seq = read_seqcount_begin(&idle->seqcount);
                idle_time = READ_ONCE(idle->idle_time);
                idle_enter = READ_ONCE(idle->clock_idle_enter);
                idle_exit = READ_ONCE(idle->clock_idle_exit);
        } while (read_seqcount_retry(&idle->seqcount, seq));
-       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+       in_idle = 0;
+       now = get_tod_clock();
+       if (idle_enter) {
+               if (idle_exit) {
+                       in_idle = idle_exit - idle_enter;
+               } else if (now > idle_enter) {
+                       in_idle = now - idle_enter;
+               }
+       }
+       idle_time += in_idle;
        return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -88,17 +96,24 @@ DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
 u64 arch_cpu_idle_time(int cpu)
 {
        struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
-       unsigned long long now, idle_enter, idle_exit;
+       unsigned long long now, idle_enter, idle_exit, in_idle;
        unsigned int seq;
 
        do {
-               now = get_tod_clock();
                seq = read_seqcount_begin(&idle->seqcount);
                idle_enter = READ_ONCE(idle->clock_idle_enter);
                idle_exit = READ_ONCE(idle->clock_idle_exit);
        } while (read_seqcount_retry(&idle->seqcount, seq));
-
-       return cputime_to_nsecs(idle_enter ? ((idle_exit ?: now) - idle_enter) : 0);
+       in_idle = 0;
+       now = get_tod_clock();
+       if (idle_enter) {
+               if (idle_exit) {
+                       in_idle = idle_exit - idle_enter;
+               } else if (now > idle_enter) {
+                       in_idle = now - idle_enter;
+               }
+       }
+       return cputime_to_nsecs(in_idle);
 }
 
 void arch_cpu_idle_enter(void)
index 510a182..a51c892 100644 (file)
@@ -298,16 +298,16 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
        }
 
        if (write) {
-               len = *lenp;
-               if (copy_from_user(buf, buffer,
-                                  len > sizeof(buf) ? sizeof(buf) : len))
+               len = min(*lenp, sizeof(buf));
+               if (copy_from_user(buf, buffer, len))
                        return -EFAULT;
-               buf[sizeof(buf) - 1] = '\0';
+               buf[len - 1] = '\0';
                cmm_skip_blanks(buf, &p);
                nr = simple_strtoul(p, &p, 0);
                cmm_skip_blanks(p, &p);
                seconds = simple_strtoul(p, &p, 0);
                cmm_set_timeout(nr, seconds);
+               *ppos += *lenp;
        } else {
                len = sprintf(buf, "%ld %ld\n",
                              cmm_timeout_pages, cmm_timeout_seconds);
@@ -315,9 +315,9 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
                        len = *lenp;
                if (copy_to_user(buffer, buf, len))
                        return -EFAULT;
+               *lenp = len;
+               *ppos += len;
        }
-       *lenp = len;
-       *ppos += len;
        return 0;
 }
 
index 27ade3c..defb536 100644 (file)
@@ -4,12 +4,14 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <asm/apicdef.h>
 #include <asm/nmi.h>
 
 #include "../perf_event.h"
 
-static DEFINE_PER_CPU(unsigned int, perf_nmi_counter);
+static DEFINE_PER_CPU(unsigned long, perf_nmi_tstamp);
+static unsigned long perf_nmi_window;
 
 static __initconst const u64 amd_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
@@ -640,11 +642,12 @@ static void amd_pmu_disable_event(struct perf_event *event)
  * handler when multiple PMCs are active or PMC overflow while handling some
  * other source of an NMI.
  *
- * Attempt to mitigate this by using the number of active PMCs to determine
- * whether to return NMI_HANDLED if the perf NMI handler did not handle/reset
- * any PMCs. The per-CPU perf_nmi_counter variable is set to a minimum of the
- * number of active PMCs or 2. The value of 2 is used in case an NMI does not
- * arrive at the LAPIC in time to be collapsed into an already pending NMI.
+ * Attempt to mitigate this by creating an NMI window in which un-handled NMIs
+ * received during this window will be claimed. This prevents extending the
+ * window past when it is possible that latent NMIs should be received. The
+ * per-CPU perf_nmi_tstamp will be set to the window end time whenever perf has
+ * handled a counter. When an un-handled NMI is received, it will be claimed
+ * only if arriving within that window.
  */
 static int amd_pmu_handle_irq(struct pt_regs *regs)
 {
@@ -662,21 +665,19 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
        handled = x86_pmu_handle_irq(regs);
 
        /*
-        * If a counter was handled, record the number of possible remaining
-        * NMIs that can occur.
+        * If a counter was handled, record a timestamp such that un-handled
+        * NMIs will be claimed if arriving within that window.
         */
        if (handled) {
-               this_cpu_write(perf_nmi_counter,
-                              min_t(unsigned int, 2, active));
+               this_cpu_write(perf_nmi_tstamp,
+                              jiffies + perf_nmi_window);
 
                return handled;
        }
 
-       if (!this_cpu_read(perf_nmi_counter))
+       if (time_after(jiffies, this_cpu_read(perf_nmi_tstamp)))
                return NMI_DONE;
 
-       this_cpu_dec(perf_nmi_counter);
-
        return NMI_HANDLED;
 }
 
@@ -908,6 +909,9 @@ static int __init amd_core_pmu_init(void)
        if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
                return 0;
 
+       /* Avoid calulating the value each time in the NMI handler */
+       perf_nmi_window = msecs_to_jiffies(100);
+
        switch (boot_cpu_data.x86) {
        case 0x15:
                pr_cont("Fam15h ");
index 5d0b72f..2a8e5f7 100644 (file)
@@ -6,7 +6,7 @@
  * "Big Core" Processors (Branded as Core, Xeon, etc...)
  *
  * The "_X" parts are generally the EP and EX Xeons, or the
- * "Extreme" ones, like Broadwell-E.
+ * "Extreme" ones, like Broadwell-E, or Atom microserver.
  *
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
@@ -61,6 +61,9 @@
 #define INTEL_FAM6_TIGERLAKE_L         0x8C
 #define INTEL_FAM6_TIGERLAKE           0x8D
 
+#define INTEL_FAM6_COMETLAKE           0xA5
+#define INTEL_FAM6_COMETLAKE_L         0xA6
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
@@ -80,6 +83,7 @@
 #define INTEL_FAM6_ATOM_GOLDMONT       0x5C /* Apollo Lake */
 #define INTEL_FAM6_ATOM_GOLDMONT_X     0x5F /* Denverton */
 #define INTEL_FAM6_ATOM_GOLDMONT_PLUS  0x7A /* Gemini Lake */
+#define INTEL_FAM6_ATOM_TREMONT_X      0x86 /* Jacobsville */
 
 /* Xeon Phi */
 
index 9061bab..335a62e 100644 (file)
@@ -893,9 +893,6 @@ static void __init kexec_enter_virtual_mode(void)
 
        if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
                runtime_code_page_mkexec();
-
-       /* clean DUMMY object */
-       efi_delete_dummy_variable();
 #endif
 }
 
index c6c7c9b..2483ff3 100644 (file)
@@ -266,19 +266,41 @@ void xen_reboot(int reason)
                BUG();
 }
 
+static int reboot_reason = SHUTDOWN_reboot;
+static bool xen_legacy_crash;
 void xen_emergency_restart(void)
 {
-       xen_reboot(SHUTDOWN_reboot);
+       xen_reboot(reboot_reason);
 }
 
 static int
 xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       if (!kexec_crash_loaded())
-               xen_reboot(SHUTDOWN_crash);
+       if (!kexec_crash_loaded()) {
+               if (xen_legacy_crash)
+                       xen_reboot(SHUTDOWN_crash);
+
+               reboot_reason = SHUTDOWN_crash;
+
+               /*
+                * If panic_timeout==0 then we are supposed to wait forever.
+                * However, to preserve original dom0 behavior we have to drop
+                * into hypervisor. (domU behavior is controlled by its
+                * config file)
+                */
+               if (panic_timeout == 0)
+                       panic_timeout = -1;
+       }
        return NOTIFY_DONE;
 }
 
+static int __init parse_xen_legacy_crash(char *arg)
+{
+       xen_legacy_crash = true;
+       return 0;
+}
+early_param("xen_legacy_crash", parse_xen_legacy_crash);
+
 static struct notifier_block xen_panic_block = {
        .notifier_call = xen_panic_event,
        .priority = INT_MIN
index bc2fa4e..867841c 100644 (file)
@@ -228,8 +228,8 @@ static void nbd_put(struct nbd_device *nbd)
        if (refcount_dec_and_mutex_lock(&nbd->refs,
                                        &nbd_index_mutex)) {
                idr_remove(&nbd_index_idr, nbd->index);
-               mutex_unlock(&nbd_index_mutex);
                nbd_dev_remove(nbd);
+               mutex_unlock(&nbd_index_mutex);
        }
 }
 
@@ -349,17 +349,16 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
        struct nbd_device *nbd = cmd->nbd;
        struct nbd_config *config;
 
+       if (!mutex_trylock(&cmd->lock))
+               return BLK_EH_RESET_TIMER;
+
        if (!refcount_inc_not_zero(&nbd->config_refs)) {
                cmd->status = BLK_STS_TIMEOUT;
+               mutex_unlock(&cmd->lock);
                goto done;
        }
        config = nbd->config;
 
-       if (!mutex_trylock(&cmd->lock)) {
-               nbd_config_put(nbd);
-               return BLK_EH_RESET_TIMER;
-       }
-
        if (config->num_connections > 1) {
                dev_err_ratelimited(nbd_to_dev(nbd),
                                    "Connection timed out, retrying (%d/%d alive)\n",
@@ -664,6 +663,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
                ret = -ENOENT;
                goto out;
        }
+       if (cmd->status != BLK_STS_OK) {
+               dev_err(disk_to_dev(nbd->disk), "Command already handled %p\n",
+                       req);
+               ret = -ENOENT;
+               goto out;
+       }
        if (test_bit(NBD_CMD_REQUEUED, &cmd->flags)) {
                dev_err(disk_to_dev(nbd->disk), "Raced with timeout on req %p\n",
                        req);
@@ -745,7 +750,10 @@ static void nbd_clear_req(struct request *req, void *data, bool reserved)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 
+       mutex_lock(&cmd->lock);
        cmd->status = BLK_STS_IOERR;
+       mutex_unlock(&cmd->lock);
+
        blk_mq_complete_request(req);
 }
 
@@ -924,6 +932,25 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
        return ret;
 }
 
+static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd,
+                                    int *err)
+{
+       struct socket *sock;
+
+       *err = 0;
+       sock = sockfd_lookup(fd, err);
+       if (!sock)
+               return NULL;
+
+       if (sock->ops->shutdown == sock_no_shutdown) {
+               dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n");
+               *err = -EINVAL;
+               return NULL;
+       }
+
+       return sock;
+}
+
 static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
                          bool netlink)
 {
@@ -933,7 +960,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
        struct nbd_sock *nsock;
        int err;
 
-       sock = sockfd_lookup(arg, &err);
+       sock = nbd_get_socket(nbd, arg, &err);
        if (!sock)
                return err;
 
@@ -985,7 +1012,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
        int i;
        int err;
 
-       sock = sockfd_lookup(arg, &err);
+       sock = nbd_get_socket(nbd, arg, &err);
        if (!sock)
                return err;
 
index 70cbd0e..76abe40 100644 (file)
@@ -312,13 +312,14 @@ static void reset_bdev(struct zram *zram)
 static ssize_t backing_dev_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
+       struct file *file;
        struct zram *zram = dev_to_zram(dev);
-       struct file *file = zram->backing_dev;
        char *p;
        ssize_t ret;
 
        down_read(&zram->init_lock);
-       if (!zram_wb_enabled(zram)) {
+       file = zram->backing_dev;
+       if (!file) {
                memcpy(buf, "none\n", 5);
                up_read(&zram->init_lock);
                return 5;
index f5d54a6..dddda45 100644 (file)
@@ -73,31 +73,39 @@ static void __init clk_boston_setup(struct device_node *np)
        hw = clk_hw_register_fixed_rate(NULL, "input", NULL, 0, in_freq);
        if (IS_ERR(hw)) {
                pr_err("failed to register input clock: %ld\n", PTR_ERR(hw));
-               goto error;
+               goto fail_input;
        }
        onecell->hws[BOSTON_CLK_INPUT] = hw;
 
        hw = clk_hw_register_fixed_rate(NULL, "sys", "input", 0, sys_freq);
        if (IS_ERR(hw)) {
                pr_err("failed to register sys clock: %ld\n", PTR_ERR(hw));
-               goto error;
+               goto fail_sys;
        }
        onecell->hws[BOSTON_CLK_SYS] = hw;
 
        hw = clk_hw_register_fixed_rate(NULL, "cpu", "input", 0, cpu_freq);
        if (IS_ERR(hw)) {
                pr_err("failed to register cpu clock: %ld\n", PTR_ERR(hw));
-               goto error;
+               goto fail_cpu;
        }
        onecell->hws[BOSTON_CLK_CPU] = hw;
 
        err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
-       if (err)
+       if (err) {
                pr_err("failed to add DT provider: %d\n", err);
+               goto fail_clk_add;
+       }
 
        return;
 
-error:
+fail_clk_add:
+       clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_CPU]);
+fail_cpu:
+       clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_SYS]);
+fail_sys:
+       clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_INPUT]);
+fail_input:
        kfree(onecell);
 }
 
index 0997e16..8b749c7 100644 (file)
@@ -1276,7 +1276,7 @@ static void make_established(struct sock *sk, u32 snd_isn, unsigned int opt)
        tp->write_seq = snd_isn;
        tp->snd_nxt = snd_isn;
        tp->snd_una = snd_isn;
-       inet_sk(sk)->inet_id = tp->write_seq ^ jiffies;
+       inet_sk(sk)->inet_id = prandom_u32();
        assign_rxopt(sk, opt);
 
        if (tp->rcv_wnd > (RCV_BUFSIZ_M << 10))
index afebbd8..1587f4a 100644 (file)
@@ -1716,7 +1716,7 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
                return peekmsg(sk, msg, len, nonblock, flags);
 
        if (sk_can_busy_loop(sk) &&
-           skb_queue_empty(&sk->sk_receive_queue) &&
+           skb_queue_empty_lockless(&sk->sk_receive_queue) &&
            sk->sk_state == TCP_ESTABLISHED)
                sk_busy_loop(sk, nonblock);
 
index 489c8fa..4451ccf 100644 (file)
@@ -703,6 +703,25 @@ static int bam_dma_terminate_all(struct dma_chan *chan)
 
        /* remove all transactions, including active transaction */
        spin_lock_irqsave(&bchan->vc.lock, flag);
+       /*
+        * If we have transactions queued, then some might be committed to the
+        * hardware in the desc fifo.  The only way to reset the desc fifo is
+        * to do a hardware reset (either by pipe or the entire block).
+        * bam_chan_init_hw() will trigger a pipe reset, and also reinit the
+        * pipe.  If the pipe is left disabled (default state after pipe reset)
+        * and is accessed by a connected hardware engine, a fatal error in
+        * the BAM will occur.  There is a small window where this could happen
+        * with bam_chan_init_hw(), but it is assumed that the caller has
+        * stopped activity on any attached hardware engine.  Make sure to do
+        * this first so that the BAM hardware doesn't cause memory corruption
+        * by accessing freed resources.
+        */
+       if (!list_empty(&bchan->desc_list)) {
+               async_desc = list_first_entry(&bchan->desc_list,
+                                             struct bam_async_desc, desc_node);
+               bam_chan_init_hw(bchan, async_desc->dir);
+       }
+
        list_for_each_entry_safe(async_desc, tmp,
                                 &bchan->desc_list, desc_node) {
                list_add(&async_desc->vd.node, &bchan->vc.desc_issued);
index e507ec3..f8fa994 100644 (file)
@@ -585,9 +585,22 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg(
        enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
 {
        struct cppi41_channel *c = to_cpp41_chan(chan);
+       struct dma_async_tx_descriptor *txd = NULL;
+       struct cppi41_dd *cdd = c->cdd;
        struct cppi41_desc *d;
        struct scatterlist *sg;
        unsigned int i;
+       int error;
+
+       error = pm_runtime_get(cdd->ddev.dev);
+       if (error < 0) {
+               pm_runtime_put_noidle(cdd->ddev.dev);
+
+               return NULL;
+       }
+
+       if (cdd->is_suspended)
+               goto err_out_not_ready;
 
        d = c->desc;
        for_each_sg(sgl, sg, sg_len, i) {
@@ -610,7 +623,13 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg(
                d++;
        }
 
-       return &c->txd;
+       txd = &c->txd;
+
+err_out_not_ready:
+       pm_runtime_mark_last_busy(cdd->ddev.dev);
+       pm_runtime_put_autosuspend(cdd->ddev.dev);
+
+       return txd;
 }
 
 static void cppi41_compute_td_desc(struct cppi41_desc *d)
index 4045098..116989c 100644 (file)
@@ -393,7 +393,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
                printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx,
                       pcie->device_id.vendor_id, pcie->device_id.device_id);
                p = pcie->device_id.class_code;
-               printk("%s""class_code: %02x%02x%02x\n", pfx, p[0], p[1], p[2]);
+               printk("%s""class_code: %02x%02x%02x\n", pfx, p[2], p[1], p[0]);
        }
        if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER)
                printk("%s""serial number: 0x%04x, 0x%04x\n", pfx,
index 538bce4..ac6c1c0 100644 (file)
@@ -163,13 +163,13 @@ static int max77620_gpio_set_debounce(struct max77620_gpio *mgpio,
        case 0:
                val = MAX77620_CNFG_GPIO_DBNC_None;
                break;
-       case 1 ... 8:
+       case 1000 ... 8000:
                val = MAX77620_CNFG_GPIO_DBNC_8ms;
                break;
-       case 9 ... 16:
+       case 9000 ... 16000:
                val = MAX77620_CNFG_GPIO_DBNC_16ms;
                break;
-       case 17 ... 32:
+       case 17000 ... 32000:
                val = MAX77620_CNFG_GPIO_DBNC_32ms;
                break;
        default:
index b80243d..ce7f18c 100644 (file)
@@ -264,7 +264,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
 
        r = amdgpu_bo_create_list_entry_array(&args->in, &info);
        if (r)
-               goto error_free;
+               return r;
 
        switch (args->in.operation) {
        case AMDGPU_BO_LIST_OP_CREATE:
@@ -277,8 +277,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
                r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL);
                mutex_unlock(&fpriv->bo_list_lock);
                if (r < 0) {
-                       amdgpu_bo_list_put(list);
-                       return r;
+                       goto error_put_list;
                }
 
                handle = r;
@@ -300,9 +299,8 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
                mutex_unlock(&fpriv->bo_list_lock);
 
                if (IS_ERR(old)) {
-                       amdgpu_bo_list_put(list);
                        r = PTR_ERR(old);
-                       goto error_free;
+                       goto error_put_list;
                }
 
                amdgpu_bo_list_put(old);
@@ -319,8 +317,10 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
 
        return 0;
 
+error_put_list:
+       amdgpu_bo_list_put(list);
+
 error_free:
-       if (info)
-               kvfree(info);
+       kvfree(info);
        return r;
 }
index b0e14a3..b14ce11 100644 (file)
@@ -428,7 +428,8 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
                .interruptible = (bp->type != ttm_bo_type_kernel),
                .no_wait_gpu = false,
                .resv = bp->resv,
-               .flags = TTM_OPT_FLAG_ALLOW_RES_EVICT
+               .flags = bp->type != ttm_bo_type_kernel ?
+                       TTM_OPT_FLAG_ALLOW_RES_EVICT : 0
        };
        struct amdgpu_bo *bo;
        unsigned long page_align, size = bp->size;
index d440b28..6896d69 100644 (file)
@@ -1399,9 +1399,9 @@ bool dc_remove_plane_from_context(
                         * For head pipe detach surfaces from pipe for tail
                         * pipe just zero it out
                         */
-                       if (!pipe_ctx->top_pipe ||
-                               (!pipe_ctx->top_pipe->top_pipe &&
+                       if (!pipe_ctx->top_pipe || (!pipe_ctx->top_pipe->top_pipe &&
                                        pipe_ctx->top_pipe->stream_res.opp != pipe_ctx->stream_res.opp)) {
+                               pipe_ctx->top_pipe = NULL;
                                pipe_ctx->plane_state = NULL;
                                pipe_ctx->bottom_pipe = NULL;
                        } else {
@@ -1803,8 +1803,6 @@ enum dc_status dc_remove_stream_from_ctx(
                                dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
 
                        memset(del_pipe, 0, sizeof(*del_pipe));
-
-                       break;
                }
        }
 
index fb86c24..ce459ea 100644 (file)
@@ -4751,9 +4751,7 @@ static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr,
 
        if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
                podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
-               for (i = 0; i < podn_vdd_dep->count - 1; i++)
-                       od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
-               if (od_vddc_lookup_table->entries[i].us_vdd < podn_vdd_dep->entries[i].vddc)
+               for (i = 0; i < podn_vdd_dep->count; i++)
                        od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
        } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
                podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
index 74cc204..2d9b7b5 100644 (file)
@@ -442,35 +442,38 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms *kms,
        }
 }
 
-static void _dpu_kms_initialize_dsi(struct drm_device *dev,
+static int _dpu_kms_initialize_dsi(struct drm_device *dev,
                                    struct msm_drm_private *priv,
                                    struct dpu_kms *dpu_kms)
 {
        struct drm_encoder *encoder = NULL;
-       int i, rc;
+       int i, rc = 0;
+
+       if (!(priv->dsi[0] || priv->dsi[1]))
+               return rc;
 
        /*TODO: Support two independent DSI connectors */
        encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
-       if (IS_ERR_OR_NULL(encoder)) {
+       if (IS_ERR(encoder)) {
                DPU_ERROR("encoder init failed for dsi display\n");
-               return;
+               return PTR_ERR(encoder);
        }
 
        priv->encoders[priv->num_encoders++] = encoder;
 
        for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-               if (!priv->dsi[i]) {
-                       DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
-                       return;
-               }
+               if (!priv->dsi[i])
+                       continue;
 
                rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
                if (rc) {
                        DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
                                i, rc);
-                       continue;
+                       break;
                }
        }
+
+       return rc;
 }
 
 /**
@@ -481,16 +484,16 @@ static void _dpu_kms_initialize_dsi(struct drm_device *dev,
  * @dpu_kms:    Pointer to dpu kms structure
  * Returns:     Zero on success
  */
-static void _dpu_kms_setup_displays(struct drm_device *dev,
+static int _dpu_kms_setup_displays(struct drm_device *dev,
                                    struct msm_drm_private *priv,
                                    struct dpu_kms *dpu_kms)
 {
-       _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
-
        /**
         * Extend this function to initialize other
         * types of displays
         */
+
+       return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
 }
 
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -552,7 +555,9 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
         * Create encoder and query display drivers to create
         * bridges and connectors
         */
-       _dpu_kms_setup_displays(dev, priv, dpu_kms);
+       ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+       if (ret)
+               goto fail;
 
        max_crtc_count = min(catalog->mixer_count, priv->num_encoders);
 
index a594e47..843aed4 100644 (file)
@@ -75,13 +75,20 @@ static int axff_init(struct hid_device *hid)
 {
        struct axff_device *axff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int field_count = 0;
        int i, j;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 8613755..63a1628 100644 (file)
@@ -975,6 +975,7 @@ int hid_open_report(struct hid_device *device)
        __u8 *start;
        __u8 *buf;
        __u8 *end;
+       __u8 *next;
        int ret;
        static int (*dispatch_type[])(struct hid_parser *parser,
                                      struct hid_item *item) = {
@@ -1028,7 +1029,8 @@ int hid_open_report(struct hid_device *device)
        device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 
        ret = -EINVAL;
-       while ((start = fetch_item(start, end, &item)) != NULL) {
+       while ((next = fetch_item(start, end, &item)) != NULL) {
+               start = next;
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        hid_err(device, "unexpected long global item\n");
@@ -1058,7 +1060,8 @@ int hid_open_report(struct hid_device *device)
                }
        }
 
-       hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
+       hid_err(device, "item fetching failed at offset %u/%u\n",
+               size - (unsigned int)(end - start), size);
 err:
        kfree(parser->collection_stack);
 alloc_err:
index 818ea7d..309969b 100644 (file)
@@ -87,13 +87,19 @@ static int drff_init(struct hid_device *hid)
 {
        struct drff_device *drff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index d82d75b..80f9a02 100644 (file)
@@ -59,13 +59,19 @@ static int emsff_init(struct hid_device *hid)
 {
        struct emsff_device *emsff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 2d8cead..5a02c50 100644 (file)
@@ -77,14 +77,20 @@ static int gaff_init(struct hid_device *hid)
 {
        struct gaff_device *gaff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct list_head *report_ptr = report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index edc0f64..c68486e 100644 (file)
@@ -136,13 +136,19 @@ static int holtekff_init(struct hid_device *hid)
 {
        struct holtekff_device *holtekff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output report found\n");
                return -ENODEV;
index 704049e..4d1496f 100644 (file)
@@ -322,60 +322,24 @@ static void mousevsc_on_receive(struct hv_device *device,
 
 static void mousevsc_on_channel_callback(void *context)
 {
-       const int packet_size = 0x100;
-       int ret;
        struct hv_device *device = context;
-       u32 bytes_recvd;
-       u64 req_id;
        struct vmpacket_descriptor *desc;
-       unsigned char   *buffer;
-       int     bufferlen = packet_size;
-
-       buffer = kmalloc(bufferlen, GFP_ATOMIC);
-       if (!buffer)
-               return;
-
-       do {
-               ret = vmbus_recvpacket_raw(device->channel, buffer,
-                                       bufferlen, &bytes_recvd, &req_id);
-
-               switch (ret) {
-               case 0:
-                       if (bytes_recvd <= 0) {
-                               kfree(buffer);
-                               return;
-                       }
-                       desc = (struct vmpacket_descriptor *)buffer;
-
-                       switch (desc->type) {
-                       case VM_PKT_COMP:
-                               break;
-
-                       case VM_PKT_DATA_INBAND:
-                               mousevsc_on_receive(device, desc);
-                               break;
-
-                       default:
-                               pr_err("unhandled packet type %d, tid %llx len %d\n",
-                                       desc->type, req_id, bytes_recvd);
-                               break;
-                       }
 
+       foreach_vmbus_pkt(desc, device->channel) {
+               switch (desc->type) {
+               case VM_PKT_COMP:
                        break;
 
-               case -ENOBUFS:
-                       kfree(buffer);
-                       /* Handle large packet */
-                       bufferlen = bytes_recvd;
-                       buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
-
-                       if (!buffer)
-                               return;
+               case VM_PKT_DATA_INBAND:
+                       mousevsc_on_receive(device, desc);
+                       break;
 
+               default:
+                       pr_err("Unhandled packet type %d, tid %llx len %d\n",
+                              desc->type, desc->trans_id, desc->len8 * 8);
                        break;
                }
-       } while (1);
-
+       }
 }
 
 static int mousevsc_connect_to_vsp(struct hv_device *device)
index 2d60360..5471ed7 100644 (file)
 #define USB_VENDOR_ID_LG               0x1fd2
 #define USB_DEVICE_ID_LG_MULTITOUCH    0x0064
 #define USB_DEVICE_ID_LG_MELFAS_MT     0x6007
+#define I2C_DEVICE_ID_LG_8001          0x8001
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
index d988b92..01bed2f 100644 (file)
@@ -328,6 +328,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL,
                USB_DEVICE_ID_SYMBOL_SCANNER_3),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
+               USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
index 0e3fb1a..6909d9c 100644 (file)
@@ -62,11 +62,17 @@ int lg2ff_init(struct hid_device *hid)
 {
        struct lg2ff_device *lg2ff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
        if (!report)
index 8c2da18..acf739f 100644 (file)
@@ -129,12 +129,19 @@ static const signed short ff3_joystick_ac[] = {
 
 int lg3ff_init(struct hid_device *hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const signed short *ff_bits = ff3_joystick_ac;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
                return -ENODEV;
index 4b26928..ef80c59 100644 (file)
@@ -1259,8 +1259,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc
 
 int lg4ff_init(struct hid_device *hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
        const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
@@ -1272,6 +1272,13 @@ int lg4ff_init(struct hid_device *hid)
        int mmode_ret, mmode_idx = -1;
        u16 real_product_id;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -1;
index e1394af..1871cdc 100644 (file)
@@ -127,12 +127,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
 
 int lgff_init(struct hid_device* hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const signed short *ff_bits = ff_joystick;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -ENODEV;
index e642cfa..034c883 100644 (file)
@@ -1867,8 +1867,8 @@ static void hidpp_ff_destroy(struct ff_device *ff)
 static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
 {
        struct hid_device *hid = hidpp->hid_dev;
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
        const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
        struct ff_device *ff;
@@ -1877,6 +1877,13 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
        int error, j, num_slots;
        u8 version;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (!dev) {
                hid_err(hid, "Struct input_dev not set!\n");
                return -EINVAL;
index 09f2c61..d05c387 100644 (file)
@@ -2249,9 +2249,15 @@ static int sony_play_effect(struct input_dev *dev, void *data,
 
 static int sony_init_ff(struct sony_sc *sc)
 {
-       struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *input_dev;
+
+       if (list_empty(&sc->hdev->inputs)) {
+               hid_err(sc->hdev, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list);
+       input_dev = hidinput->input;
 
        input_set_capability(input_dev, EV_FF, FF_RUMBLE);
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
index dc4128b..8dae0f9 100644 (file)
@@ -283,11 +283,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
 static int steam_input_open(struct input_dev *dev)
 {
        struct steam_device *steam = input_get_drvdata(dev);
-       int ret;
-
-       ret = hid_hw_open(steam->hdev);
-       if (ret)
-               return ret;
 
        mutex_lock(&steam->mutex);
        if (!steam->client_opened && lizard_mode)
@@ -304,8 +299,6 @@ static void steam_input_close(struct input_dev *dev)
        if (!steam->client_opened && lizard_mode)
                steam_set_lizard_mode(steam, true);
        mutex_unlock(&steam->mutex);
-
-       hid_hw_close(steam->hdev);
 }
 
 static enum power_supply_property steam_battery_props[] = {
@@ -506,6 +499,7 @@ static void steam_battery_unregister(struct steam_device *steam)
 static int steam_register(struct steam_device *steam)
 {
        int ret;
+       bool client_opened;
 
        /*
         * This function can be called several times in a row with the
@@ -518,9 +512,11 @@ static int steam_register(struct steam_device *steam)
                 * Unlikely, but getting the serial could fail, and it is not so
                 * important, so make up a serial number and go on.
                 */
+               mutex_lock(&steam->mutex);
                if (steam_get_serial(steam) < 0)
                        strlcpy(steam->serial_no, "XXXXXXXXXX",
                                        sizeof(steam->serial_no));
+               mutex_unlock(&steam->mutex);
 
                hid_info(steam->hdev, "Steam Controller '%s' connected",
                                steam->serial_no);
@@ -535,13 +531,15 @@ static int steam_register(struct steam_device *steam)
        }
 
        mutex_lock(&steam->mutex);
-       if (!steam->client_opened) {
+       client_opened = steam->client_opened;
+       if (!client_opened)
                steam_set_lizard_mode(steam, lizard_mode);
+       mutex_unlock(&steam->mutex);
+
+       if (!client_opened)
                ret = steam_input_register(steam);
-       } else {
+       else
                ret = 0;
-       }
-       mutex_unlock(&steam->mutex);
 
        return ret;
 }
@@ -623,11 +621,6 @@ static void steam_client_ll_stop(struct hid_device *hdev)
 static int steam_client_ll_open(struct hid_device *hdev)
 {
        struct steam_device *steam = hdev->driver_data;
-       int ret;
-
-       ret = hid_hw_open(steam->hdev);
-       if (ret)
-               return ret;
 
        mutex_lock(&steam->mutex);
        steam->client_opened = true;
@@ -635,22 +628,28 @@ static int steam_client_ll_open(struct hid_device *hdev)
 
        steam_input_unregister(steam);
 
-       return ret;
+       return 0;
 }
 
 static void steam_client_ll_close(struct hid_device *hdev)
 {
        struct steam_device *steam = hdev->driver_data;
 
+       unsigned long flags;
+       bool connected;
+
+       spin_lock_irqsave(&steam->lock, flags);
+       connected = steam->connected;
+       spin_unlock_irqrestore(&steam->lock, flags);
+
        mutex_lock(&steam->mutex);
        steam->client_opened = false;
+       if (connected)
+               steam_set_lizard_mode(steam, lizard_mode);
        mutex_unlock(&steam->mutex);
 
-       hid_hw_close(steam->hdev);
-       if (steam->connected) {
-               steam_set_lizard_mode(steam, lizard_mode);
+       if (connected)
                steam_input_register(steam);
-       }
 }
 
 static int steam_client_ll_raw_request(struct hid_device *hdev,
@@ -759,14 +758,15 @@ static int steam_probe(struct hid_device *hdev,
        if (ret)
                goto client_hdev_add_fail;
 
+       ret = hid_hw_open(hdev);
+       if (ret) {
+               hid_err(hdev,
+                       "%s:hid_hw_open\n",
+                       __func__);
+               goto hid_hw_open_fail;
+       }
+
        if (steam->quirks & STEAM_QUIRK_WIRELESS) {
-               ret = hid_hw_open(hdev);
-               if (ret) {
-                       hid_err(hdev,
-                               "%s:hid_hw_open for wireless\n",
-                               __func__);
-                       goto hid_hw_open_fail;
-               }
                hid_info(hdev, "Steam wireless receiver connected");
                steam_request_conn_status(steam);
        } else {
@@ -781,8 +781,8 @@ static int steam_probe(struct hid_device *hdev,
 
        return 0;
 
-hid_hw_open_fail:
 input_register_fail:
+hid_hw_open_fail:
 client_hdev_add_fail:
        hid_hw_stop(hdev);
 hid_hw_start_fail:
@@ -809,8 +809,8 @@ static void steam_remove(struct hid_device *hdev)
        cancel_work_sync(&steam->work_connect);
        if (steam->quirks & STEAM_QUIRK_WIRELESS) {
                hid_info(hdev, "Steam wireless receiver disconnected");
-               hid_hw_close(hdev);
        }
+       hid_hw_close(hdev);
        hid_hw_stop(hdev);
        steam_unregister(steam);
 }
index 30b8c32..efe8c2a 100644 (file)
@@ -136,12 +136,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
        struct tmff_device *tmff;
        struct hid_report *report;
        struct list_head *report_list;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                                       struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *input_dev;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       input_dev = hidinput->input;
+
        tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
        if (!tmff)
                return -ENOMEM;
index a29756c..4e7e01b 100644 (file)
@@ -66,11 +66,17 @@ static int zpff_init(struct hid_device *hid)
 {
        struct zpff_device *zpff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        int i, error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        for (i = 0; i < 4; i++) {
                report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
                if (!report)
index 3cde7c1..2f940c1 100644 (file)
@@ -50,6 +50,7 @@
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
 #define I2C_HID_QUIRK_NO_RUNTIME_PM            BIT(2)
 #define I2C_HID_QUIRK_DELAY_AFTER_SLEEP                BIT(3)
+#define I2C_HID_QUIRK_BOGUS_IRQ                        BIT(4)
 
 /* flags */
 #define I2C_HID_STARTED                0
@@ -177,6 +178,10 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_NO_RUNTIME_PM },
        { I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,
                I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
+       { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
+               I2C_HID_QUIRK_NO_RUNTIME_PM },
+       { USB_VENDOR_ID_ELAN, HID_ANY_ID,
+                I2C_HID_QUIRK_BOGUS_IRQ },
        { 0, 0 }
 };
 
@@ -501,6 +506,12 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
                return;
        }
 
+       if (ihid->quirks & I2C_HID_QUIRK_BOGUS_IRQ && ret_size == 0xffff) {
+               dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but "
+                             "there's no data\n", __func__);
+               return;
+       }
+
        if ((ret_size > size) || (ret_size < 2)) {
                dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
                        __func__, size, ret_size);
index cac262a..10af858 100644 (file)
@@ -323,6 +323,25 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                .driver_data = (void *)&sipodev_desc
        },
        {
+               /*
+                * There are at least 2 Primebook C11B versions, the older
+                * version has a product-name of "Primebook C11B", and a
+                * bios version / release / firmware revision of:
+                * V2.1.2 / 05/03/2018 / 18.2
+                * The new version has "PRIMEBOOK C11B" as product-name and a
+                * bios version / release / firmware revision of:
+                * CFALKSW05_BIOS_V1.1.2 / 11/19/2018 / 19.2
+                * Only the older version needs this quirk, note the newer
+                * version will not match as it has a different product-name.
+                */
+               .ident = "Trekstor Primebook C11B",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11B"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
+       {
                .ident = "Direkt-Tek DTLAPY116-2",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
@@ -331,6 +350,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                .driver_data = (void *)&sipodev_desc
        },
        {
+               .ident = "Direkt-Tek DTLAPY133-1",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY133-1"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
+       {
                .ident = "Mediacom Flexbook Edge 11",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
@@ -338,6 +365,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                },
                .driver_data = (void *)&sipodev_desc
        },
+       {
+               .ident = "Odys Winbook 13",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AXDIA International GmbH"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WINBOOK 13"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
        { }     /* Terminate list */
 };
 
index ac9c948..f4e3613 100644 (file)
@@ -297,7 +297,7 @@ struct stm32f7_i2c_dev {
        bool use_dma;
 };
 
-/**
+/*
  * All these values are coming from I2C Specification, Version 6.0, 4th of
  * April 2014.
  *
@@ -1177,6 +1177,8 @@ static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
                        STM32F7_I2C_CR1_TXIE;
                stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
 
+               /* Write 1st data byte */
+               writel_relaxed(value, base + STM32F7_I2C_TXDR);
        } else {
                /* Notify i2c slave that new write transfer is starting */
                i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
@@ -1486,7 +1488,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
        void __iomem *base = i2c_dev->base;
        struct device *dev = i2c_dev->dev;
        struct stm32_i2c_dma *dma = i2c_dev->dma;
-       u32 mask, status;
+       u32 status;
 
        status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
 
@@ -1511,12 +1513,15 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
                f7_msg->result = -EINVAL;
        }
 
-       /* Disable interrupts */
-       if (stm32f7_i2c_is_slave_registered(i2c_dev))
-               mask = STM32F7_I2C_XFER_IRQ_MASK;
-       else
-               mask = STM32F7_I2C_ALL_IRQ_MASK;
-       stm32f7_i2c_disable_irq(i2c_dev, mask);
+       if (!i2c_dev->slave_running) {
+               u32 mask;
+               /* Disable interrupts */
+               if (stm32f7_i2c_is_slave_registered(i2c_dev))
+                       mask = STM32F7_I2C_XFER_IRQ_MASK;
+               else
+                       mask = STM32F7_I2C_ALL_IRQ_MASK;
+               stm32f7_i2c_disable_irq(i2c_dev, mask);
+       }
 
        /* Disable dma */
        if (i2c_dev->use_dma) {
index 383c802..cb8c98a 100644 (file)
 #define BMC150_ACCEL_SLEEP_1_SEC               0x0F
 
 #define BMC150_ACCEL_REG_TEMP                  0x08
-#define BMC150_ACCEL_TEMP_CENTER_VAL           24
+#define BMC150_ACCEL_TEMP_CENTER_VAL           23
 
 #define BMC150_ACCEL_AXIS_TO_REG(axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))
 #define BMC150_AUTO_SUSPEND_DELAY_MS           2000
index 5dd104c..6e0ef9b 100644 (file)
@@ -1023,6 +1023,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
+       priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                            priv->data->param->regmap_config);
+       if (IS_ERR(priv->regmap))
+               return PTR_ERR(priv->regmap);
+
        irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
        if (!irq)
                return -EINVAL;
@@ -1032,11 +1037,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
-                                            priv->data->param->regmap_config);
-       if (IS_ERR(priv->regmap))
-               return PTR_ERR(priv->regmap);
-
        priv->clkin = devm_clk_get(&pdev->dev, "clkin");
        if (IS_ERR(priv->clkin)) {
                dev_err(&pdev->dev, "failed to get clkin\n");
index 76643c5..e59d043 100644 (file)
@@ -39,8 +39,11 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
                return -ENOMEM;
 
        adis->buffer = kcalloc(indio_dev->scan_bytes, 2, GFP_KERNEL);
-       if (!adis->buffer)
+       if (!adis->buffer) {
+               kfree(adis->xfer);
+               adis->xfer = NULL;
                return -ENOMEM;
+       }
 
        rx = adis->buffer;
        tx = rx + scan_count;
index 6257be2..1f373ba 100644 (file)
@@ -2270,9 +2270,10 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
                conn_id->cm_id.iw = NULL;
                cma_exch(conn_id, RDMA_CM_DESTROYING);
                mutex_unlock(&conn_id->handler_mutex);
+               mutex_unlock(&listen_id->handler_mutex);
                cma_deref_id(conn_id);
                rdma_destroy_id(&conn_id->id);
-               goto out;
+               return ret;
        }
 
        mutex_unlock(&conn_id->handler_mutex);
index d648a41..64ab92f 100644 (file)
@@ -1518,8 +1518,11 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
        }
 
        ret = rhashtable_init(tmp_sdma_rht, &sdma_rht_params);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(tmp_sdma_rht);
                goto bail;
+       }
+
        dd->sdma_rht = tmp_sdma_rht;
 
        dd_dev_info(dd, "SDMA num_sdma: %u\n", dd->num_sdma);
index e7549a2..050d6e0 100644 (file)
@@ -182,6 +182,22 @@ static DEFINE_IDA(its_vpeid_ida);
 #define gic_data_rdist_rd_base()       (gic_data_rdist()->rd_base)
 #define gic_data_rdist_vlpi_base()     (gic_data_rdist_rd_base() + SZ_128K)
 
+static u16 get_its_list(struct its_vm *vm)
+{
+       struct its_node *its;
+       unsigned long its_list = 0;
+
+       list_for_each_entry(its, &its_nodes, entry) {
+               if (!its->is_v4)
+                       continue;
+
+               if (vm->vlpi_count[its->list_nr])
+                       __set_bit(its->list_nr, &its_list);
+       }
+
+       return (u16)its_list;
+}
+
 static struct its_collection *dev_event_to_col(struct its_device *its_dev,
                                               u32 event)
 {
@@ -983,17 +999,15 @@ static void its_send_vmapp(struct its_node *its,
 
 static void its_send_vmovp(struct its_vpe *vpe)
 {
-       struct its_cmd_desc desc;
+       struct its_cmd_desc desc = {};
        struct its_node *its;
        unsigned long flags;
        int col_id = vpe->col_idx;
 
        desc.its_vmovp_cmd.vpe = vpe;
-       desc.its_vmovp_cmd.its_list = (u16)its_list_map;
 
        if (!its_list_map) {
                its = list_first_entry(&its_nodes, struct its_node, entry);
-               desc.its_vmovp_cmd.seq_num = 0;
                desc.its_vmovp_cmd.col = &its->collections[col_id];
                its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
                return;
@@ -1010,6 +1024,7 @@ static void its_send_vmovp(struct its_vpe *vpe)
        raw_spin_lock_irqsave(&vmovp_lock, flags);
 
        desc.its_vmovp_cmd.seq_num = vmovp_seq_num++;
+       desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm);
 
        /* Emit VMOVPs */
        list_for_each_entry(its, &its_nodes, entry) {
index 21786a4..c67fd2f 100644 (file)
@@ -744,7 +744,7 @@ capi_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &(cdev->recvwait), wait);
        mask = EPOLLOUT | EPOLLWRNORM;
-       if (!skb_queue_empty(&cdev->recvqueue))
+       if (!skb_queue_empty_lockless(&cdev->recvqueue))
                mask |= EPOLLIN | EPOLLRDNORM;
        return mask;
 }
index 5bb81e5..3e8d1f1 100644 (file)
@@ -289,7 +289,9 @@ STORE(__cached_dev)
        sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
                            dc->writeback_rate_p_term_inverse,
                            1, UINT_MAX);
-       d_strtoul_nonzero(writeback_rate_minimum);
+       sysfs_strtoul_clamp(writeback_rate_minimum,
+                           dc->writeback_rate_minimum,
+                           1, UINT_MAX);
 
        sysfs_strtoul_clamp(io_error_limit, dc->error_limit, 0, INT_MAX);
 
index 36805b1..d3f28a9 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/vmalloc.h>
 #include <linux/log2.h>
 #include <linux/dm-kcopyd.h>
-#include <linux/semaphore.h>
 
 #include "dm.h"
 
@@ -106,8 +105,8 @@ struct dm_snapshot {
        /* The on disk metadata handler */
        struct dm_exception_store *store;
 
-       /* Maximum number of in-flight COW jobs. */
-       struct semaphore cow_count;
+       unsigned in_progress;
+       struct wait_queue_head in_progress_wait;
 
        struct dm_kcopyd_client *kcopyd_client;
 
@@ -158,8 +157,8 @@ struct dm_snapshot {
  */
 #define DEFAULT_COW_THRESHOLD 2048
 
-static int cow_threshold = DEFAULT_COW_THRESHOLD;
-module_param_named(snapshot_cow_threshold, cow_threshold, int, 0644);
+static unsigned cow_threshold = DEFAULT_COW_THRESHOLD;
+module_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644);
 MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
 
 DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
@@ -1207,7 +1206,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad_hash_tables;
        }
 
-       sema_init(&s->cow_count, (cow_threshold > 0) ? cow_threshold : INT_MAX);
+       init_waitqueue_head(&s->in_progress_wait);
 
        s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle);
        if (IS_ERR(s->kcopyd_client)) {
@@ -1396,9 +1395,56 @@ static void snapshot_dtr(struct dm_target *ti)
 
        dm_put_device(ti, s->origin);
 
+       WARN_ON(s->in_progress);
+
        kfree(s);
 }
 
+static void account_start_copy(struct dm_snapshot *s)
+{
+       spin_lock(&s->in_progress_wait.lock);
+       s->in_progress++;
+       spin_unlock(&s->in_progress_wait.lock);
+}
+
+static void account_end_copy(struct dm_snapshot *s)
+{
+       spin_lock(&s->in_progress_wait.lock);
+       BUG_ON(!s->in_progress);
+       s->in_progress--;
+       if (likely(s->in_progress <= cow_threshold) &&
+           unlikely(waitqueue_active(&s->in_progress_wait)))
+               wake_up_locked(&s->in_progress_wait);
+       spin_unlock(&s->in_progress_wait.lock);
+}
+
+static bool wait_for_in_progress(struct dm_snapshot *s, bool unlock_origins)
+{
+       if (unlikely(s->in_progress > cow_threshold)) {
+               spin_lock(&s->in_progress_wait.lock);
+               if (likely(s->in_progress > cow_threshold)) {
+                       /*
+                        * NOTE: this throttle doesn't account for whether
+                        * the caller is servicing an IO that will trigger a COW
+                        * so excess throttling may result for chunks not required
+                        * to be COW'd.  But if cow_threshold was reached, extra
+                        * throttling is unlikely to negatively impact performance.
+                        */
+                       DECLARE_WAITQUEUE(wait, current);
+                       __add_wait_queue(&s->in_progress_wait, &wait);
+                       __set_current_state(TASK_UNINTERRUPTIBLE);
+                       spin_unlock(&s->in_progress_wait.lock);
+                       if (unlock_origins)
+                               up_read(&_origins_lock);
+                       io_schedule();
+                       remove_wait_queue(&s->in_progress_wait, &wait);
+                       return false;
+               }
+               spin_unlock(&s->in_progress_wait.lock);
+       }
+       return true;
+}
+
 /*
  * Flush a list of buffers.
  */
@@ -1414,7 +1460,7 @@ static void flush_bios(struct bio *bio)
        }
 }
 
-static int do_origin(struct dm_dev *origin, struct bio *bio);
+static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit);
 
 /*
  * Flush a list of buffers.
@@ -1427,7 +1473,7 @@ static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio)
        while (bio) {
                n = bio->bi_next;
                bio->bi_next = NULL;
-               r = do_origin(s->origin, bio);
+               r = do_origin(s->origin, bio, false);
                if (r == DM_MAPIO_REMAPPED)
                        generic_make_request(bio);
                bio = n;
@@ -1594,7 +1640,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
                rb_link_node(&pe->out_of_order_node, parent, p);
                rb_insert_color(&pe->out_of_order_node, &s->out_of_order_tree);
        }
-       up(&s->cow_count);
+       account_end_copy(s);
 }
 
 /*
@@ -1618,7 +1664,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
        dest.count = src.count;
 
        /* Hand over to kcopyd */
-       down(&s->cow_count);
+       account_start_copy(s);
        dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
 }
 
@@ -1638,7 +1684,7 @@ static void start_full_bio(struct dm_snap_pending_exception *pe,
        pe->full_bio = bio;
        pe->full_bio_end_io = bio->bi_end_io;
 
-       down(&s->cow_count);
+       account_start_copy(s);
        callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client,
                                                   copy_callback, pe);
 
@@ -1729,6 +1775,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
        if (!s->valid)
                return DM_MAPIO_KILL;
 
+       if (bio_data_dir(bio) == WRITE) {
+               while (unlikely(!wait_for_in_progress(s, false)))
+                       ; /* wait_for_in_progress() has slept */
+       }
+
        mutex_lock(&s->lock);
 
        if (!s->valid || (unlikely(s->snapshot_overflowed) &&
@@ -1877,7 +1928,7 @@ redirect_to_origin:
 
        if (bio_data_dir(bio) == WRITE) {
                mutex_unlock(&s->lock);
-               return do_origin(s->origin, bio);
+               return do_origin(s->origin, bio, false);
        }
 
 out_unlock:
@@ -2214,15 +2265,24 @@ next_snapshot:
 /*
  * Called on a write from the origin driver.
  */
-static int do_origin(struct dm_dev *origin, struct bio *bio)
+static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit)
 {
        struct origin *o;
        int r = DM_MAPIO_REMAPPED;
 
+again:
        down_read(&_origins_lock);
        o = __lookup_origin(origin->bdev);
-       if (o)
+       if (o) {
+               if (limit) {
+                       struct dm_snapshot *s;
+                       list_for_each_entry(s, &o->snapshots, list)
+                               if (unlikely(!wait_for_in_progress(s, true)))
+                                       goto again;
+               }
+
                r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio);
+       }
        up_read(&_origins_lock);
 
        return r;
@@ -2335,7 +2395,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
                dm_accept_partial_bio(bio, available_sectors);
 
        /* Only tell snapshots if this is a write */
-       return do_origin(o->dev, bio);
+       return do_origin(o->dev, bio, true);
 }
 
 static long origin_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
index 9e0d70e..3f0ffd4 100644 (file)
@@ -204,13 +204,6 @@ static void *vimc_sen_process_frame(struct vimc_ent_device *ved,
 {
        struct vimc_sen_device *vsen = container_of(ved, struct vimc_sen_device,
                                                    ved);
-       const struct vimc_pix_map *vpix;
-       unsigned int frame_size;
-
-       /* Calculate the frame size */
-       vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
-       frame_size = vsen->mbus_format.width * vpix->bpp *
-                    vsen->mbus_format.height;
 
        tpg_fill_plane_buffer(&vsen->tpg, 0, 0, vsen->frame);
        return vsen->frame;
index 0d2392c..2804e2d 100644 (file)
@@ -4033,7 +4033,7 @@ out:
                 * this to-be-skipped slave to send a packet out.
                 */
                old_arr = rtnl_dereference(bond->slave_arr);
-               for (idx = 0; idx < old_arr->count; idx++) {
+               for (idx = 0; old_arr != NULL && idx < old_arr->count; idx++) {
                        if (skipslave == old_arr->arr[idx]) {
                                old_arr->arr[idx] =
                                    old_arr->arr[old_arr->count-1];
index ad534b9..2d3a2cb 100644 (file)
@@ -1584,7 +1584,6 @@ int b53_mirror_add(struct dsa_switch *ds, int port,
                loc = B53_EG_MIR_CTL;
 
        b53_read16(dev, B53_MGMT_PAGE, loc, &reg);
-       reg &= ~MIRROR_MASK;
        reg |= BIT(port);
        b53_write16(dev, B53_MGMT_PAGE, loc, reg);
 
index 2fa2caf..ca3655d 100644 (file)
@@ -41,22 +41,11 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
        unsigned int i;
        u32 reg, offset;
 
-       if (priv->type == BCM7445_DEVICE_ID)
-               offset = CORE_STS_OVERRIDE_IMP;
-       else
-               offset = CORE_STS_OVERRIDE_IMP2;
-
        /* Enable the port memories */
        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
        reg &= ~P_TXQ_PSM_VDD(port);
        core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 
-       /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
-       reg = core_readl(priv, CORE_IMP_CTL);
-       reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
-       reg &= ~(RX_DIS | TX_DIS);
-       core_writel(priv, reg, CORE_IMP_CTL);
-
        /* Enable forwarding */
        core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
 
@@ -75,10 +64,27 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 
        b53_brcm_hdr_setup(ds, port);
 
-       /* Force link status for IMP port */
-       reg = core_readl(priv, offset);
-       reg |= (MII_SW_OR | LINK_STS);
-       core_writel(priv, reg, offset);
+       if (port == 8) {
+               if (priv->type == BCM7445_DEVICE_ID)
+                       offset = CORE_STS_OVERRIDE_IMP;
+               else
+                       offset = CORE_STS_OVERRIDE_IMP2;
+
+               /* Force link status for IMP port */
+               reg = core_readl(priv, offset);
+               reg |= (MII_SW_OR | LINK_STS);
+               core_writel(priv, reg, offset);
+
+               /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
+               reg = core_readl(priv, CORE_IMP_CTL);
+               reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
+               reg &= ~(RX_DIS | TX_DIS);
+               core_writel(priv, reg, CORE_IMP_CTL);
+       } else {
+               reg = core_readl(priv, CORE_G_PCTL_PORT(port));
+               reg &= ~(RX_DIS | TX_DIS);
+               core_writel(priv, reg, CORE_G_PCTL_PORT(port));
+       }
 }
 
 static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
index 703e6bd..d075f0f 100644 (file)
@@ -456,10 +456,12 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
         */
        irq_set_lockdep_class(chip->irq, &lock_key, &request_key);
 
+       mutex_unlock(&chip->reg_lock);
        err = request_threaded_irq(chip->irq, NULL,
                                   mv88e6xxx_g1_irq_thread_fn,
                                   IRQF_ONESHOT,
                                   dev_name(chip->dev), chip);
+       mutex_lock(&chip->reg_lock);
        if (err)
                mv88e6xxx_g1_irq_free_common(chip);
 
index 251166d..2bd0b3d 100644 (file)
@@ -2029,6 +2029,8 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
         */
        if (priv->internal_phy) {
                int0_enable |= UMAC_IRQ_LINK_EVENT;
+               if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
+                       int0_enable |= UMAC_IRQ_PHY_DET_R;
        } else if (priv->ext_phy) {
                int0_enable |= UMAC_IRQ_LINK_EVENT;
        } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
@@ -2627,11 +2629,14 @@ static void bcmgenet_irq_task(struct work_struct *work)
        priv->irq0_stat = 0;
        spin_unlock_irq(&priv->lock);
 
+       if (status & UMAC_IRQ_PHY_DET_R &&
+           priv->dev->phydev->autoneg != AUTONEG_ENABLE)
+               phy_init_hw(priv->dev->phydev);
+
        /* Link UP/DOWN event */
-       if (status & UMAC_IRQ_LINK_EVENT) {
-               priv->dev->phydev->link = !!(status & UMAC_IRQ_LINK_UP);
+       if (status & UMAC_IRQ_LINK_EVENT)
                phy_mac_interrupt(priv->dev->phydev);
-       }
+
 }
 
 /* bcmgenet_isr1: handle Rx and Tx priority queues */
@@ -2726,7 +2731,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
        }
 
        /* all other interested interrupts handled in bottom half */
-       status &= UMAC_IRQ_LINK_EVENT;
+       status &= (UMAC_IRQ_LINK_EVENT | UMAC_IRQ_PHY_DET_R);
        if (status) {
                /* Save irq status for bottom-half processing. */
                spin_lock_irqsave(&priv->lock, flags);
index dba8a0c..3d834d4 100644 (file)
@@ -673,10 +673,10 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
        lld->write_cmpl_support = adap->params.write_cmpl_support;
 }
 
-static void uld_attach(struct adapter *adap, unsigned int uld)
+static int uld_attach(struct adapter *adap, unsigned int uld)
 {
-       void *handle;
        struct cxgb4_lld_info lli;
+       void *handle;
 
        uld_init(adap, &lli);
        uld_queue_init(adap, uld, &lli);
@@ -686,7 +686,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
                dev_warn(adap->pdev_dev,
                         "could not attach to the %s driver, error %ld\n",
                         adap->uld[uld].name, PTR_ERR(handle));
-               return;
+               return PTR_ERR(handle);
        }
 
        adap->uld[uld].handle = handle;
@@ -694,23 +694,24 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
 
        if (adap->flags & FULL_INIT_DONE)
                adap->uld[uld].state_change(handle, CXGB4_STATE_UP);
+
+       return 0;
 }
 
-/**
- *     cxgb4_register_uld - register an upper-layer driver
- *     @type: the ULD type
- *     @p: the ULD methods
+/* cxgb4_register_uld - register an upper-layer driver
+ * @type: the ULD type
+ * @p: the ULD methods
  *
- *     Registers an upper-layer driver with this driver and notifies the ULD
- *     about any presently available devices that support its type.  Returns
- *     %-EBUSY if a ULD of the same type is already registered.
+ * Registers an upper-layer driver with this driver and notifies the ULD
+ * about any presently available devices that support its type.  Returns
+ * %-EBUSY if a ULD of the same type is already registered.
  */
 int cxgb4_register_uld(enum cxgb4_uld type,
                       const struct cxgb4_uld_info *p)
 {
-       int ret = 0;
        unsigned int adap_idx = 0;
        struct adapter *adap;
+       int ret = 0;
 
        if (type >= CXGB4_ULD_MAX)
                return -EINVAL;
@@ -744,12 +745,16 @@ int cxgb4_register_uld(enum cxgb4_uld type,
                if (ret)
                        goto free_irq;
                adap->uld[type] = *p;
-               uld_attach(adap, type);
+               ret = uld_attach(adap, type);
+               if (ret)
+                       goto free_txq;
                adap_idx++;
        }
        mutex_unlock(&uld_mutex);
        return 0;
 
+free_txq:
+       release_sge_txq_uld(adap, type);
 free_irq:
        if (adap->flags & FULL_INIT_DONE)
                quiesce_rx_uld(adap, type);
index ed6c76d..f6ed889 100644 (file)
@@ -739,6 +739,18 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
         */
        nfrags = skb_shinfo(skb)->nr_frags;
 
+       /* Setup HW checksumming */
+       csum_vlan = 0;
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           !ftgmac100_prep_tx_csum(skb, &csum_vlan))
+               goto drop;
+
+       /* Add VLAN tag */
+       if (skb_vlan_tag_present(skb)) {
+               csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG;
+               csum_vlan |= skb_vlan_tag_get(skb) & 0xffff;
+       }
+
        /* Get header len */
        len = skb_headlen(skb);
 
@@ -765,19 +777,6 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
        if (nfrags == 0)
                f_ctl_stat |= FTGMAC100_TXDES0_LTS;
        txdes->txdes3 = cpu_to_le32(map);
-
-       /* Setup HW checksumming */
-       csum_vlan = 0;
-       if (skb->ip_summed == CHECKSUM_PARTIAL &&
-           !ftgmac100_prep_tx_csum(skb, &csum_vlan))
-               goto drop;
-
-       /* Add VLAN tag */
-       if (skb_vlan_tag_present(skb)) {
-               csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG;
-               csum_vlan |= skb_vlan_tag_get(skb) & 0xffff;
-       }
-
        txdes->txdes1 = cpu_to_le32(csum_vlan);
 
        /* Next descriptor */
index a91d49d..2f8f03e 100644 (file)
@@ -174,6 +174,7 @@ struct hip04_priv {
        dma_addr_t rx_phys[RX_DESC_NUM];
        unsigned int rx_head;
        unsigned int rx_buf_size;
+       unsigned int rx_cnt_remaining;
 
        struct device_node *phy_node;
        struct phy_device *phy;
@@ -487,7 +488,6 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
        struct hip04_priv *priv = container_of(napi, struct hip04_priv, napi);
        struct net_device *ndev = priv->ndev;
        struct net_device_stats *stats = &ndev->stats;
-       unsigned int cnt = hip04_recv_cnt(priv);
        struct rx_desc *desc;
        struct sk_buff *skb;
        unsigned char *buf;
@@ -500,8 +500,8 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
 
        /* clean up tx descriptors */
        tx_remaining = hip04_tx_reclaim(ndev, false);
-
-       while (cnt && !last) {
+       priv->rx_cnt_remaining += hip04_recv_cnt(priv);
+       while (priv->rx_cnt_remaining && !last) {
                buf = priv->rx_buf[priv->rx_head];
                skb = build_skb(buf, priv->rx_buf_size);
                if (unlikely(!skb)) {
@@ -547,11 +547,13 @@ refill:
                hip04_set_recv_desc(priv, phys);
 
                priv->rx_head = RX_NEXT(priv->rx_head);
-               if (rx >= budget)
+               if (rx >= budget) {
+                       --priv->rx_cnt_remaining;
                        goto done;
+               }
 
-               if (--cnt == 0)
-                       cnt = hip04_recv_cnt(priv);
+               if (--priv->rx_cnt_remaining == 0)
+                       priv->rx_cnt_remaining += hip04_recv_cnt(priv);
        }
 
        if (!(priv->reg_inten & RCV_INT)) {
@@ -636,6 +638,7 @@ static int hip04_mac_open(struct net_device *ndev)
        int i;
 
        priv->rx_head = 0;
+       priv->rx_cnt_remaining = 0;
        priv->tx_head = 0;
        priv->tx_tail = 0;
        hip04_reset_ppe(priv);
index 676428a..a4c1ed6 100644 (file)
@@ -471,12 +471,31 @@ void mlx4_init_quotas(struct mlx4_dev *dev)
                priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];
 }
 
-static int get_max_gauranteed_vfs_counter(struct mlx4_dev *dev)
+static int
+mlx4_calc_res_counter_guaranteed(struct mlx4_dev *dev,
+                                struct resource_allocator *res_alloc,
+                                int vf)
 {
-       /* reduce the sink counter */
-       return (dev->caps.max_counters - 1 -
-               (MLX4_PF_COUNTERS_PER_PORT * MLX4_MAX_PORTS))
-               / MLX4_MAX_PORTS;
+       struct mlx4_active_ports actv_ports;
+       int ports, counters_guaranteed;
+
+       /* For master, only allocate according to the number of phys ports */
+       if (vf == mlx4_master_func_num(dev))
+               return MLX4_PF_COUNTERS_PER_PORT * dev->caps.num_ports;
+
+       /* calculate real number of ports for the VF */
+       actv_ports = mlx4_get_active_ports(dev, vf);
+       ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports);
+       counters_guaranteed = ports * MLX4_VF_COUNTERS_PER_PORT;
+
+       /* If we do not have enough counters for this VF, do not
+        * allocate any for it. '-1' to reduce the sink counter.
+        */
+       if ((res_alloc->res_reserved + counters_guaranteed) >
+           (dev->caps.max_counters - 1))
+               return 0;
+
+       return counters_guaranteed;
 }
 
 int mlx4_init_resource_tracker(struct mlx4_dev *dev)
@@ -484,7 +503,6 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
        struct mlx4_priv *priv = mlx4_priv(dev);
        int i, j;
        int t;
-       int max_vfs_guarantee_counter = get_max_gauranteed_vfs_counter(dev);
 
        priv->mfunc.master.res_tracker.slave_list =
                kcalloc(dev->num_slaves, sizeof(struct slave_list),
@@ -603,16 +621,8 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
                                break;
                        case RES_COUNTER:
                                res_alloc->quota[t] = dev->caps.max_counters;
-                               if (t == mlx4_master_func_num(dev))
-                                       res_alloc->guaranteed[t] =
-                                               MLX4_PF_COUNTERS_PER_PORT *
-                                               MLX4_MAX_PORTS;
-                               else if (t <= max_vfs_guarantee_counter)
-                                       res_alloc->guaranteed[t] =
-                                               MLX4_VF_COUNTERS_PER_PORT *
-                                               MLX4_MAX_PORTS;
-                               else
-                                       res_alloc->guaranteed[t] = 0;
+                               res_alloc->guaranteed[t] =
+                                       mlx4_calc_res_counter_guaranteed(dev, res_alloc, t);
                                break;
                        default:
                                break;
index df49dc1..9cbc417 100644 (file)
@@ -1267,8 +1267,11 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
        if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
                return 0;
 
-       if (cq->decmprs_left)
+       if (cq->decmprs_left) {
                work_done += mlx5e_decompress_cqes_cont(rq, cq, 0, budget);
+               if (cq->decmprs_left || work_done >= budget)
+                       goto out;
+       }
 
        cqe = mlx5_cqwq_get_cqe(&cq->wq);
        if (!cqe) {
index 4382ef8..5fb088b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/udp.h>
 #include <net/udp.h>
 #include "en.h"
+#include "en/port.h"
 
 enum {
        MLX5E_ST_LINK_STATE,
@@ -80,22 +81,12 @@ static int mlx5e_test_link_state(struct mlx5e_priv *priv)
 
 static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
 {
-       u32 out[MLX5_ST_SZ_DW(ptys_reg)];
-       u32 eth_proto_oper;
-       int i;
+       u32 speed;
 
        if (!netif_carrier_ok(priv->netdev))
                return 1;
 
-       if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1))
-               return 1;
-
-       eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
-       for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) {
-               if (eth_proto_oper & MLX5E_PROT_MASK(i))
-                       return 0;
-       }
-       return 1;
+       return mlx5e_port_linkspeed(priv->mdev, &speed);
 }
 
 struct mlx5ehdr {
index ee126bc..ccd9aca 100644 (file)
@@ -4410,9 +4410,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
        err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
        if (err)
                goto err_col_port_add;
-       err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port, lag_id);
-       if (err)
-               goto err_col_port_enable;
 
        mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index,
                                   mlxsw_sp_port->local_port);
@@ -4427,8 +4424,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
 
        return 0;
 
-err_col_port_enable:
-       mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 err_col_port_add:
        if (!lag->ref_count)
                mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -4447,7 +4442,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
        WARN_ON(lag->ref_count == 0);
 
-       mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id);
        mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 
        /* Any VLANs configured on the port are no longer valid */
@@ -4492,21 +4486,56 @@ static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
 }
 
-static int mlxsw_sp_port_lag_tx_en_set(struct mlxsw_sp_port *mlxsw_sp_port,
-                                      bool lag_tx_enabled)
+static int
+mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port)
 {
-       if (lag_tx_enabled)
-               return mlxsw_sp_lag_dist_port_add(mlxsw_sp_port,
-                                                 mlxsw_sp_port->lag_id);
-       else
-               return mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
-                                                    mlxsw_sp_port->lag_id);
+       int err;
+
+       err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port,
+                                          mlxsw_sp_port->lag_id);
+       if (err)
+               return err;
+
+       err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       if (err)
+               goto err_dist_port_add;
+
+       return 0;
+
+err_dist_port_add:
+       mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       return err;
+}
+
+static int
+mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+       int err;
+
+       err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port,
+                                           mlxsw_sp_port->lag_id);
+       if (err)
+               return err;
+
+       err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port,
+                                           mlxsw_sp_port->lag_id);
+       if (err)
+               goto err_col_port_disable;
+
+       return 0;
+
+err_col_port_disable:
+       mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id);
+       return err;
 }
 
 static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
                                     struct netdev_lag_lower_state_info *info)
 {
-       return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
+       if (info->tx_enabled)
+               return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port);
+       else
+               return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
 }
 
 static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -4668,8 +4697,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
                                                             upper_dev);
                        } else {
-                               mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
-                                                           false);
+                               mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
                                                        upper_dev);
                        }
index 0c8b714..4ab87fe 100644 (file)
@@ -1010,6 +1010,10 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
 {
        int value;
 
+       /* Work around issue with chip reporting wrong PHY ID */
+       if (reg == MII_PHYSID2)
+               return 0xc912;
+
        r8168dp_2_mdio_start(tp);
 
        value = r8169_mdio_read(tp, reg);
index b2b6307..acaf072 100644 (file)
@@ -643,6 +643,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
        .name           = _name,                                        \
        .features       = PHY_BASIC_FEATURES,                           \
        .flags          = PHY_IS_INTERNAL,                              \
+       .soft_reset     = genphy_soft_reset,                            \
        .config_init    = bcm7xxx_config_init,                          \
        .suspend        = bcm7xxx_suspend,                              \
        .resume         = bcm7xxx_config_init,                          \
index 85fba64..c3cf9ae 100644 (file)
@@ -800,6 +800,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
index 949308a..41464ad 100644 (file)
@@ -1292,8 +1292,11 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb)
                netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata);
                lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
 
-               if (dev->domain_data.phyirq > 0)
+               if (dev->domain_data.phyirq > 0) {
+                       local_irq_disable();
                        generic_handle_irq(dev->domain_data.phyirq);
+                       local_irq_enable();
+               }
        } else
                netdev_warn(dev->net,
                            "unexpected interrupt: 0x%08x\n", intdata);
@@ -3848,10 +3851,14 @@ static int lan78xx_probe(struct usb_interface *intf,
        /* driver requires remote-wakeup capability during autosuspend. */
        intf->needs_remote_wakeup = 1;
 
+       ret = lan78xx_phy_init(dev);
+       if (ret < 0)
+               goto out4;
+
        ret = register_netdev(netdev);
        if (ret != 0) {
                netif_err(dev, probe, netdev, "couldn't register the device\n");
-               goto out4;
+               goto out5;
        }
 
        usb_set_intfdata(intf, dev);
@@ -3864,14 +3871,10 @@ static int lan78xx_probe(struct usb_interface *intf,
        pm_runtime_set_autosuspend_delay(&udev->dev,
                                         DEFAULT_AUTOSUSPEND_DELAY);
 
-       ret = lan78xx_phy_init(dev);
-       if (ret < 0)
-               goto out5;
-
        return 0;
 
 out5:
-       unregister_netdev(netdev);
+       phy_disconnect(netdev->phydev);
 out4:
        usb_free_urb(dev->urb_intr);
 out3:
index a291e5f..91d47a7 100644 (file)
@@ -5339,6 +5339,7 @@ static const struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0xa387)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
        {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK,  0x0601)},
index 35f39f2..8f8c9ed 100644 (file)
@@ -336,7 +336,7 @@ static void sr_set_multicast(struct net_device *net)
 static int sr_mdio_read(struct net_device *net, int phy_id, int loc)
 {
        struct usbnet *dev = netdev_priv(net);
-       __le16 res;
+       __le16 res = 0;
 
        mutex_lock(&dev->phy_mutex);
        sr_set_sw_mii(dev);
index 0b1ec44..2a536f8 100644 (file)
@@ -2174,9 +2174,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                vni = tunnel_id_to_key32(info->key.tun_id);
                ifindex = 0;
                dst_cache = &info->dst_cache;
-               if (info->options_len &&
-                   info->key.tun_flags & TUNNEL_VXLAN_OPT)
+               if (info->key.tun_flags & TUNNEL_VXLAN_OPT) {
+                       if (info->options_len < sizeof(*md))
+                               goto drop;
                        md = ip_tunnel_info_opts(info);
+               }
                ttl = info->key.ttl;
                tos = info->key.tos;
                label = info->key.label;
index 5210cff..2791ef2 100644 (file)
@@ -532,7 +532,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .hw_ops = &wcn3990_ops,
                .decap_align_bytes = 1,
                .num_peers = TARGET_HL_10_TLV_NUM_PEERS,
-               .n_cipher_suites = 8,
+               .n_cipher_suites = 11,
                .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT,
                .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES,
                .target_64bit = true,
index 4defb7a..53b66e9 100644 (file)
@@ -132,6 +132,10 @@ ath6kl_usb_alloc_urb_from_pipe(struct ath6kl_usb_pipe *pipe)
        struct ath6kl_urb_context *urb_context = NULL;
        unsigned long flags;
 
+       /* bail if this pipe is not initialized */
+       if (!pipe->ar_usb)
+               return NULL;
+
        spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
        if (!list_empty(&pipe->urb_list_head)) {
                urb_context =
@@ -150,6 +154,10 @@ static void ath6kl_usb_free_urb_to_pipe(struct ath6kl_usb_pipe *pipe,
 {
        unsigned long flags;
 
+       /* bail if this pipe is not initialized */
+       if (!pipe->ar_usb)
+               return;
+
        spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
        pipe->urb_cnt++;
 
index 3e7fc29..409a6fa 100644 (file)
@@ -234,9 +234,10 @@ static int wil_rx_refill_edma(struct wil6210_priv *wil)
        struct wil_ring *ring = &wil->ring_rx;
        u32 next_head;
        int rc = 0;
-       u32 swtail = *ring->edma_rx_swtail.va;
+       ring->swtail = *ring->edma_rx_swtail.va;
 
-       for (; next_head = wil_ring_next_head(ring), (next_head != swtail);
+       for (; next_head = wil_ring_next_head(ring),
+            (next_head != ring->swtail);
             ring->swhead = next_head) {
                rc = wil_ring_alloc_skb_edma(wil, ring, ring->swhead);
                if (unlikely(rc)) {
@@ -264,43 +265,26 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil,
                                              struct wil_ring *ring)
 {
        struct device *dev = wil_to_dev(wil);
-       u32 next_tail;
-       u32 swhead = (ring->swhead + 1) % ring->size;
+       struct list_head *active = &wil->rx_buff_mgmt.active;
        dma_addr_t pa;
-       u16 dmalen;
 
-       for (; next_tail = wil_ring_next_tail(ring), (next_tail != swhead);
-            ring->swtail = next_tail) {
-               struct wil_rx_enhanced_desc dd, *d = &dd;
-               struct wil_rx_enhanced_desc *_d =
-                       (struct wil_rx_enhanced_desc *)
-                       &ring->va[ring->swtail].rx.enhanced;
-               struct sk_buff *skb;
-               u16 buff_id;
+       while (!list_empty(active)) {
+               struct wil_rx_buff *rx_buff =
+                       list_first_entry(active, struct wil_rx_buff, list);
+               struct sk_buff *skb = rx_buff->skb;
 
-               *d = *_d;
-
-               /* Extract the SKB from the rx_buff management array */
-               buff_id = __le16_to_cpu(d->mac.buff_id);
-               if (buff_id >= wil->rx_buff_mgmt.size) {
-                       wil_err(wil, "invalid buff_id %d\n", buff_id);
-                       continue;
-               }
-               skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
-               wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL;
                if (unlikely(!skb)) {
-                       wil_err(wil, "No Rx skb at buff_id %d\n", buff_id);
+                       wil_err(wil, "No Rx skb at buff_id %d\n", rx_buff->id);
                } else {
-                       pa = wil_rx_desc_get_addr_edma(&d->dma);
-                       dmalen = le16_to_cpu(d->dma.length);
-                       dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);
-
+                       rx_buff->skb = NULL;
+                       memcpy(&pa, skb->cb, sizeof(pa));
+                       dma_unmap_single(dev, pa, wil->rx_buf_len,
+                                        DMA_FROM_DEVICE);
                        kfree_skb(skb);
                }
 
                /* Move the buffer from the active to the free list */
-               list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list,
-                         &wil->rx_buff_mgmt.free);
+               list_move(&rx_buff->list, &wil->rx_buff_mgmt.free);
        }
 }
 
index 9cb9f05..2eba6d6 100644 (file)
@@ -843,15 +843,17 @@ static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
         * firmware versions.  Unfortunately, we don't have a TLV API
         * flag to rely on, so rely on the major version which is in
         * the first byte of ucode_ver.  This was implemented
-        * initially on version 38 and then backported to29 and 17.
-        * The intention was to have it in 36 as well, but not all
-        * 8000 family got this feature enabled.  The 8000 family is
-        * the only one using version 36, so skip this version
-        * entirely.
+        * initially on version 38 and then backported to 17.  It was
+        * also backported to 29, but only for 7265D devices.  The
+        * intention was to have it in 36 as well, but not all 8000
+        * family got this feature enabled.  The 8000 family is the
+        * only one using version 36, so skip this version entirely.
         */
        return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
-              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 ||
-              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17;
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 ||
+              (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 &&
+               ((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
+                CSR_HW_REV_TYPE_7265D));
 }
 
 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
index 479a4cf..5f998ea 100644 (file)
@@ -775,6 +775,9 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data,
                                return;
                        } else {
                                noa_num = (noa_len - 2) / 13;
+                               if (noa_num > P2P_MAX_NOA_NUM)
+                                       noa_num = P2P_MAX_NOA_NUM;
+
                        }
                        noa_index = ie[3];
                        if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
@@ -869,6 +872,9 @@ static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data,
                                return;
                        } else {
                                noa_num = (noa_len - 2) / 13;
+                               if (noa_num > P2P_MAX_NOA_NUM)
+                                       noa_num = P2P_MAX_NOA_NUM;
+
                        }
                        noa_index = ie[3];
                        if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
index 5d823e9..fcb57d6 100644 (file)
@@ -559,18 +559,25 @@ static int pn533_usb_probe(struct usb_interface *interface,
 
        rc = pn533_finalize_setup(priv);
        if (rc)
-               goto error;
+               goto err_deregister;
 
        usb_set_intfdata(interface, phy);
 
        return 0;
 
+err_deregister:
+       pn533_unregister_device(phy->priv);
 error:
+       usb_kill_urb(phy->in_urb);
+       usb_kill_urb(phy->out_urb);
+       usb_kill_urb(phy->ack_urb);
+
        usb_free_urb(phy->in_urb);
        usb_free_urb(phy->out_urb);
        usb_free_urb(phy->ack_urb);
        usb_put_dev(phy->udev);
        kfree(in_buf);
+       kfree(phy->ack_buffer);
 
        return rc;
 }
index 7f42314..bac4b4b 100644 (file)
@@ -1159,6 +1159,7 @@ static int __init unittest_data_add(void)
        of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node);
        if (!unittest_data_node) {
                pr_warn("%s: No tree to attach; not running tests\n", __func__);
+               kfree(unittest_data);
                return -ENODATA;
        }
 
index e85c5a8..6ac17f0 100644 (file)
@@ -437,6 +437,7 @@ static void pcie_pme_remove(struct pcie_device *srv)
 
        pcie_pme_disable_interrupt(srv->port, data);
        free_irq(srv->irq, srv);
+       cancel_work_sync(&data->work);
        kfree(data);
 }
 
index 06be529..6493399 100644 (file)
@@ -5083,8 +5083,8 @@ static void quirk_switchtec_ntb_dma_alias(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 #define SWITCHTEC_QUIRK(vid) \
-       DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, vid, \
-                               quirk_switchtec_ntb_dma_alias)
+       DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_MICROSEMI, vid, \
+               PCI_CLASS_BRIDGE_OTHER, 8, quirk_switchtec_ntb_dma_alias)
 
 SWITCHTEC_QUIRK(0x8531);  /* PFX 24xG3 */
 SWITCHTEC_QUIRK(0x8532);  /* PFX 32xG3 */
index 4b5cf0e..951090f 100644 (file)
@@ -640,8 +640,8 @@ static int ns2_pinmux_enable(struct pinctrl_dev *pctrl_dev,
        const struct ns2_pin_function *func;
        const struct ns2_pin_group *grp;
 
-       if (grp_select > pinctrl->num_groups ||
-               func_select > pinctrl->num_functions)
+       if (grp_select >= pinctrl->num_groups ||
+               func_select >= pinctrl->num_functions)
                return -EINVAL;
 
        func = &pinctrl->functions[func_select];
index 9371603..b0f421f 100644 (file)
 #define ISPSSPM0_IUNIT_POWER_ON                0x0
 #define ISPSSPM0_IUNIT_POWER_OFF       0x3
 
-static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int isp_set_power(struct pci_dev *dev, bool enable)
 {
        unsigned long timeout;
-       u32 val;
-
-       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, 0);
-
-       /*
-        * MRFLD IUNIT DPHY is located in an always-power-on island
-        * MRFLD HW design need all CSI ports are disabled before
-        * powering down the IUNIT.
-        */
-       pci_read_config_dword(dev, PCI_CSI_CONTROL, &val);
-       val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
-       pci_write_config_dword(dev, PCI_CSI_CONTROL, val);
+       u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON :
+               ISPSSPM0_IUNIT_POWER_OFF;
 
-       /* Write 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */
+       /* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */
        iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0,
-                       ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK);
+                       val, ISPSSPM0_ISPSSC_MASK);
 
        /*
         * There should be no IUNIT access while power-down is
         * in progress HW sighting: 4567865
         * Wait up to 50 ms for the IUNIT to shut down.
+        * And we do the same for power on.
         */
        timeout = jiffies + msecs_to_jiffies(50);
        while (1) {
-               /* Wait until ISPSSPM0 bit[25:24] shows 0x3 */
-               iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val);
-               val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
-               if (val == ISPSSPM0_IUNIT_POWER_OFF)
+               u32 tmp;
+
+               /* Wait until ISPSSPM0 bit[25:24] shows the right value */
+               iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &tmp);
+               tmp = (tmp & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
+               if (tmp == val)
                        break;
 
                if (time_after(jiffies, timeout)) {
-                       dev_err(&dev->dev, "IUNIT power-off timeout.\n");
+                       dev_err(&dev->dev, "IUNIT power-%s timeout.\n",
+                               enable ? "on" : "off");
                        return -EBUSY;
                }
                usleep_range(1000, 2000);
        }
 
+       return 0;
+}
+
+static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
        pm_runtime_allow(&dev->dev);
        pm_runtime_put_sync_suspend(&dev->dev);
 
@@ -87,11 +86,40 @@ static void isp_remove(struct pci_dev *dev)
 
 static int isp_pci_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       u32 val;
+
+       pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, 0);
+
+       /*
+        * MRFLD IUNIT DPHY is located in an always-power-on island
+        * MRFLD HW design need all CSI ports are disabled before
+        * powering down the IUNIT.
+        */
+       pci_read_config_dword(pdev, PCI_CSI_CONTROL, &val);
+       val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
+       pci_write_config_dword(pdev, PCI_CSI_CONTROL, val);
+
+       /*
+        * We lose config space access when punit power gates
+        * the ISP. Can't use pci_set_power_state() because
+        * pmcsr won't actually change when we write to it.
+        */
+       pci_save_state(pdev);
+       pdev->current_state = PCI_D3cold;
+       isp_set_power(pdev, false);
+
        return 0;
 }
 
 static int isp_pci_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       isp_set_power(pdev, true);
+       pdev->current_state = PCI_D0;
+       pci_restore_state(pdev);
+
        return 0;
 }
 
@@ -99,6 +127,7 @@ static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend,
                            isp_pci_resume, NULL);
 
 static const struct pci_device_id isp_id_table[] = {
+       { PCI_VDEVICE(INTEL, 0x0f38), },
        { PCI_VDEVICE(INTEL, 0x22b8), },
        { 0, }
 };
index 6a61028..429166e 100644 (file)
@@ -445,6 +445,13 @@ static const struct dmi_system_id critclk_systems[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "CB6363"),
                },
        },
+       {
+               .ident = "SIMATIC IPC227E",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "6ES7647-8B"),
+               },
+       },
        { /*sentinel*/ }
 };
 
index d19307f..9e64728 100644 (file)
@@ -240,6 +240,14 @@ static enum power_supply_property max14656_battery_props[] = {
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+static void stop_irq_work(void *data)
+{
+       struct max14656_chip *chip = data;
+
+       cancel_delayed_work_sync(&chip->irq_work);
+}
+
+
 static int max14656_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -278,8 +286,6 @@ static int max14656_probe(struct i2c_client *client,
        if (ret)
                return -ENODEV;
 
-       INIT_DELAYED_WORK(&chip->irq_work, max14656_irq_worker);
-
        chip->detect_psy = devm_power_supply_register(dev,
                       &chip->psy_desc, &psy_cfg);
        if (IS_ERR(chip->detect_psy)) {
@@ -287,6 +293,13 @@ static int max14656_probe(struct i2c_client *client,
                return -EINVAL;
        }
 
+       INIT_DELAYED_WORK(&chip->irq_work, max14656_irq_worker);
+       ret = devm_add_action(dev, stop_irq_work, chip);
+       if (ret) {
+               dev_err(dev, "devm_add_action %d failed\n", ret);
+               return ret;
+       }
+
        ret = devm_request_irq(dev, chip->irq, max14656_irq,
                               IRQF_TRIGGER_FALLING,
                               MAX14656_NAME, chip);
index 210fc20..b255590 100644 (file)
@@ -214,12 +214,12 @@ static void of_get_regulation_constraints(struct device_node *np,
                                        "regulator-off-in-suspend"))
                        suspend_state->enabled = DISABLE_IN_SUSPEND;
 
-               if (!of_property_read_u32(np, "regulator-suspend-min-microvolt",
-                                         &pval))
+               if (!of_property_read_u32(suspend_np,
+                               "regulator-suspend-min-microvolt", &pval))
                        suspend_state->min_uV = pval;
 
-               if (!of_property_read_u32(np, "regulator-suspend-max-microvolt",
-                                         &pval))
+               if (!of_property_read_u32(suspend_np,
+                               "regulator-suspend-max-microvolt", &pval))
                        suspend_state->max_uV = pval;
 
                if (!of_property_read_u32(suspend_np,
index 31c3a23..69a377a 100644 (file)
@@ -710,7 +710,13 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
 
                /* SW2~SW4 high bit check and modify the voltage value table */
                if (i >= sw_check_start && i <= sw_check_end) {
-                       regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
+                       ret = regmap_read(pfuze_chip->regmap,
+                                               desc->vsel_reg, &val);
+                       if (ret) {
+                               dev_err(&client->dev, "Fails to read from the register.\n");
+                               return ret;
+                       }
+
                        if (val & sw_hi) {
                                if (pfuze_chip->chip_id == PFUZE3000 ||
                                        pfuze_chip->chip_id == PFUZE3001) {
index cced1ff..89b9314 100644 (file)
@@ -173,19 +173,14 @@ static int ti_abb_wait_txdone(struct device *dev, struct ti_abb *abb)
        while (timeout++ <= abb->settling_time) {
                status = ti_abb_check_txdone(abb);
                if (status)
-                       break;
+                       return 0;
 
                udelay(1);
        }
 
-       if (timeout > abb->settling_time) {
-               dev_warn_ratelimited(dev,
-                                    "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
-                                    __func__, timeout, readl(abb->int_base));
-               return -ETIMEDOUT;
-       }
-
-       return 0;
+       dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
+                            __func__, timeout, readl(abb->int_base));
+       return -ETIMEDOUT;
 }
 
 /**
@@ -205,19 +200,14 @@ static int ti_abb_clear_all_txdone(struct device *dev, const struct ti_abb *abb)
 
                status = ti_abb_check_txdone(abb);
                if (!status)
-                       break;
+                       return 0;
 
                udelay(1);
        }
 
-       if (timeout > abb->settling_time) {
-               dev_warn_ratelimited(dev,
-                                    "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
-                                    __func__, timeout, readl(abb->int_base));
-               return -ETIMEDOUT;
-       }
-
-       return 0;
+       dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
+                            __func__, timeout, readl(abb->int_base));
+       return -ETIMEDOUT;
 }
 
 /**
index 5abfcaf..ef7ee33 100644 (file)
@@ -97,8 +97,9 @@ static int pcf8523_voltage_low(struct i2c_client *client)
        return !!(value & REG_CONTROL3_BLF);
 }
 
-static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
+static int pcf8523_load_capacitance(struct i2c_client *client)
 {
+       u32 load;
        u8 value;
        int err;
 
@@ -106,14 +107,24 @@ static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
        if (err < 0)
                return err;
 
-       if (!high)
-               value &= ~REG_CONTROL1_CAP_SEL;
-       else
+       load = 12500;
+       of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads",
+                            &load);
+
+       switch (load) {
+       default:
+               dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500",
+                        load);
+               /* fall through */
+       case 12500:
                value |= REG_CONTROL1_CAP_SEL;
+               break;
+       case 7000:
+               value &= ~REG_CONTROL1_CAP_SEL;
+               break;
+       }
 
        err = pcf8523_write(client, REG_CONTROL1, value);
-       if (err < 0)
-               return err;
 
        return err;
 }
@@ -366,9 +377,10 @@ static int pcf8523_probe(struct i2c_client *client,
        if (!pcf)
                return -ENOMEM;
 
-       err = pcf8523_select_capacitance(client, true);
+       err = pcf8523_load_capacitance(client);
        if (err < 0)
-               return err;
+               dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
+                        err);
 
        err = pcf8523_set_pm(client, 0);
        if (err < 0)
index 7c09700..a8ac480 100644 (file)
@@ -862,7 +862,7 @@ config SCSI_SNI_53C710
 
 config 53C700_LE_ON_BE
        bool
-       depends on SCSI_LASI700
+       depends on SCSI_LASI700 || SCSI_SNI_53C710
        default y
 
 config SCSI_STEX
index 9c21938..c95c782 100644 (file)
@@ -526,6 +526,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
        unsigned int tpg_desc_tbl_off;
        unsigned char orig_transition_tmo;
        unsigned long flags;
+       bool transitioning_sense = false;
 
        if (!pg->expiry) {
                unsigned long transition_tmo = ALUA_FAILOVER_TIMEOUT * HZ;
@@ -586,13 +587,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                        goto retry;
                }
                /*
-                * Retry on ALUA state transition or if any
-                * UNIT ATTENTION occurred.
+                * If the array returns with 'ALUA state transition'
+                * sense code here it cannot return RTPG data during
+                * transition. So set the state to 'transitioning' directly.
                 */
                if (sense_hdr.sense_key == NOT_READY &&
-                   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
-                       err = SCSI_DH_RETRY;
-               else if (sense_hdr.sense_key == UNIT_ATTENTION)
+                   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) {
+                       transitioning_sense = true;
+                       goto skip_rtpg;
+               }
+               /*
+                * Retry on any other UNIT ATTENTION occurred.
+                */
+               if (sense_hdr.sense_key == UNIT_ATTENTION)
                        err = SCSI_DH_RETRY;
                if (err == SCSI_DH_RETRY &&
                    pg->expiry != 0 && time_before(jiffies, pg->expiry)) {
@@ -680,7 +687,11 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                off = 8 + (desc[7] * 4);
        }
 
+ skip_rtpg:
        spin_lock_irqsave(&pg->lock, flags);
+       if (transitioning_sense)
+               pg->state = SCSI_ACCESS_STATE_TRANSITIONING;
+
        sdev_printk(KERN_INFO, sdev,
                    "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
                    ALUA_DH_NAME, pg->group_id, print_alua_state(pg->state),
index e2575c8..22efefc 100644 (file)
@@ -1713,7 +1713,11 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                }
                tgtp->tport_unreg_cmp = &tport_unreg_cmp;
                nvmet_fc_unregister_targetport(phba->targetport);
-               wait_for_completion_timeout(&tport_unreg_cmp, 5);
+               if (!wait_for_completion_timeout(tgtp->tport_unreg_cmp,
+                                       msecs_to_jiffies(LPFC_NVMET_WAIT_TMO)))
+                       lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+                                       "6179 Unreg targetport %p timeout "
+                                       "reached.\n", phba->targetport);
                lpfc_nvmet_cleanup_io_context(phba);
        }
        phba->targetport = NULL;
index 0ec1082..3b17028 100644 (file)
@@ -31,6 +31,8 @@
 #define LPFC_NVMET_MRQ_AUTO            0
 #define LPFC_NVMET_MRQ_MAX             16
 
+#define LPFC_NVMET_WAIT_TMO            (5 * MSEC_PER_SEC)
+
 /* Used for NVME Target */
 struct lpfc_nvmet_tgtport {
        struct lpfc_hba *phba;
index 200b5bc..666495f 100644 (file)
@@ -4161,7 +4161,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        /* If pCmd was set to NULL from abort path, do not call scsi_done */
        if (xchg(&lpfc_cmd->pCmd, NULL) == NULL) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
-                                "0711 FCP cmd already NULL, sid: 0x%06x, "
+                                "5688 FCP cmd already NULL, sid: 0x%06x, "
                                 "did: 0x%06x, oxid: 0x%04x\n",
                                 vport->fc_myDID,
                                 (pnode) ? pnode->nlp_DID : 0,
index 60b6019..856a7ce 100644 (file)
@@ -3186,6 +3186,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
 
        ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0);
+       if (unlikely(!ha->wq)) {
+               ret = -ENOMEM;
+               goto probe_failed;
+       }
 
        if (ha->isp_ops->initialize_adapter(base_vha)) {
                ql_log(ql_log_fatal, base_vha, 0x00d6,
index 1f9a087..3102a75 100644 (file)
@@ -78,10 +78,8 @@ static int snirm710_probe(struct platform_device *dev)
 
        base = res->start;
        hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
-       if (!hostdata) {
-               dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
+       if (!hostdata)
                return -ENOMEM;
-       }
 
        hostdata->dev = &dev->dev;
        dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
index 37cf9c3..fc36127 100644 (file)
@@ -2,3 +2,4 @@ config PINCTRL_RT2880
        bool "RT2800 pinctrl driver for RALINK/Mediatek SOCs"
        depends on RALINK
        select PINMUX
+       select GENERIC_PINCONF
index aa98fbb..80e7067 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
@@ -73,48 +74,12 @@ static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev,
        return 0;
 }
 
-static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
-                                        struct device_node *np_config,
-                                        struct pinctrl_map **map,
-                                        unsigned int *num_maps)
-{
-       struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
-       struct property *prop;
-       const char *function_name, *group_name;
-       int ret;
-       int ngroups = 0;
-       unsigned int reserved_maps = 0;
-
-       for_each_node_with_property(np_config, "group")
-               ngroups++;
-
-       *map = NULL;
-       ret = pinctrl_utils_reserve_map(pctrldev, map, &reserved_maps,
-                                       num_maps, ngroups);
-       if (ret) {
-               dev_err(p->dev, "can't reserve map: %d\n", ret);
-               return ret;
-       }
-
-       of_property_for_each_string(np_config, "group", prop, group_name) {
-               ret = pinctrl_utils_add_map_mux(pctrldev, map, &reserved_maps,
-                                               num_maps, group_name,
-                                               function_name);
-               if (ret) {
-                       dev_err(p->dev, "can't add map: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
 static const struct pinctrl_ops rt2880_pctrl_ops = {
        .get_groups_count       = rt2880_get_group_count,
        .get_group_name         = rt2880_get_group_name,
        .get_group_pins         = rt2880_get_group_pins,
-       .dt_node_to_map         = rt2880_pinctrl_dt_node_to_map,
-       .dt_free_map            = pinctrl_utils_free_map,
+       .dt_node_to_map         = pinconf_generic_dt_node_to_map_all,
+       .dt_free_map            = pinconf_generic_dt_free_map,
 };
 
 static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev)
index dfee698..8ef7b44 100644 (file)
@@ -348,8 +348,10 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
        }
 
        padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
-       if (!padapter->HalData)
-               DBG_88E("cant not alloc memory for HAL DATA\n");
+       if (!padapter->HalData) {
+               DBG_88E("Failed to allocate memory for HAL data\n");
+               goto free_adapter;
+       }
 
        /* step read_chip_version */
        rtw_hal_read_chip_version(padapter);
index b19c960..d46eee3 100644 (file)
@@ -1832,7 +1832,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
 
        while (credits) {
                struct sk_buff *p = cxgbit_sock_peek_wr(csk);
-               const u32 csum = (__force u32)p->csum;
+               u32 csum;
 
                if (unlikely(!p)) {
                        pr_err("csk 0x%p,%u, cr %u,%u+%u, empty.\n",
@@ -1841,6 +1841,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
                        break;
                }
 
+               csum = (__force u32)p->csum;
                if (unlikely(credits < csum)) {
                        pr_warn("csk 0x%p,%u, cr %u,%u+%u, < %u.\n",
                                csk,  csk->tid,
index 47b5ef1..e9ff2a7 100644 (file)
@@ -1129,27 +1129,6 @@ passthrough_parse_cdb(struct se_cmd *cmd,
        unsigned int size;
 
        /*
-        * Clear a lun set in the cdb if the initiator talking to use spoke
-        * and old standards version, as we can't assume the underlying device
-        * won't choke up on it.
-        */
-       switch (cdb[0]) {
-       case READ_10: /* SBC - RDProtect */
-       case READ_12: /* SBC - RDProtect */
-       case READ_16: /* SBC - RDProtect */
-       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
-       case VERIFY: /* SBC - VRProtect */
-       case VERIFY_16: /* SBC - VRProtect */
-       case WRITE_VERIFY: /* SBC - VRProtect */
-       case WRITE_VERIFY_12: /* SBC - VRProtect */
-       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
-               break;
-       default:
-               cdb[1] &= 0x1f; /* clear logical unit number */
-               break;
-       }
-
-       /*
         * For REPORT LUNS we always need to emulate the response, for everything
         * else, pass it up.
         */
index 5cd6bdf..d436a15 100644 (file)
@@ -142,9 +142,20 @@ static void __iomem *ring_options_base(struct tb_ring *ring)
        return io;
 }
 
-static void ring_iowrite16desc(struct tb_ring *ring, u32 value, u32 offset)
+static void ring_iowrite_cons(struct tb_ring *ring, u16 cons)
 {
-       iowrite16(value, ring_desc_base(ring) + offset);
+       /*
+        * The other 16-bits in the register is read-only and writes to it
+        * are ignored by the hardware so we can save one ioread32() by
+        * filling the read-only bits with zeroes.
+        */
+       iowrite32(cons, ring_desc_base(ring) + 8);
+}
+
+static void ring_iowrite_prod(struct tb_ring *ring, u16 prod)
+{
+       /* See ring_iowrite_cons() above for explanation */
+       iowrite32(prod << 16, ring_desc_base(ring) + 8);
 }
 
 static void ring_iowrite32desc(struct tb_ring *ring, u32 value, u32 offset)
@@ -196,7 +207,10 @@ static void ring_write_descriptors(struct tb_ring *ring)
                        descriptor->sof = frame->sof;
                }
                ring->head = (ring->head + 1) % ring->size;
-               ring_iowrite16desc(ring, ring->head, ring->is_tx ? 10 : 8);
+               if (ring->is_tx)
+                       ring_iowrite_prod(ring, ring->head);
+               else
+                       ring_iowrite_cons(ring, ring->head);
        }
 }
 
@@ -660,7 +674,7 @@ void tb_ring_stop(struct tb_ring *ring)
 
        ring_iowrite32options(ring, 0, 0);
        ring_iowrite64desc(ring, 0, 0);
-       ring_iowrite16desc(ring, 0, ring->is_tx ? 10 : 8);
+       ring_iowrite32desc(ring, 0, 8);
        ring_iowrite32desc(ring, 0, 12);
        ring->head = 0;
        ring->tail = 0;
index bb63519..c943716 100644 (file)
@@ -968,6 +968,11 @@ static int __init n_hdlc_init(void)
        
 }      /* end of init_module() */
 
+#ifdef CONFIG_SPARC
+#undef __exitdata
+#define __exitdata
+#endif
+
 static const char hdlc_unregister_ok[] __exitdata =
        KERN_INFO "N_HDLC: line discipline unregistered\n";
 static const char hdlc_unregister_fail[] __exitdata =
index 127017c..057b1ea 100644 (file)
@@ -71,8 +71,8 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
 {
        struct serial_8250_men_mcb_data *data;
        struct resource *mem;
-       unsigned int num_ports;
-       unsigned int i;
+       int num_ports;
+       int i;
        void __iomem *membase;
 
        mem = mcb_get_resource(mdev, IORESOURCE_MEM);
@@ -87,7 +87,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
        dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
                mdev->id, num_ports);
 
-       if (num_ports == 0 || num_ports > 4) {
+       if (num_ports <= 0 || num_ports > 4) {
                dev_err(&mdev->dev, "unexpected number of ports: %u\n",
                        num_ports);
                return -ENODEV;
@@ -132,7 +132,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
 
 static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
 {
-       unsigned int num_ports, i;
+       int num_ports, i;
        struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
 
        if (!data)
index 29a6dc6..73fcc6b 100644 (file)
@@ -742,7 +742,7 @@ static int __init owl_uart_init(void)
        return ret;
 }
 
-static void __init owl_uart_exit(void)
+static void __exit owl_uart_exit(void)
 {
        platform_driver_unregister(&owl_uart_platform_driver);
        uart_unregister_driver(&owl_uart_driver);
index 07f3186..af0412a 100644 (file)
@@ -60,6 +60,9 @@ EXPORT_SYMBOL_GPL(mctrl_gpio_set);
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
                                      enum mctrl_gpio_idx gidx)
 {
+       if (gpios == NULL)
+               return NULL;
+
        return gpios->gpio[gidx];
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
index ae0caac..0efe1fa 100644 (file)
@@ -107,6 +107,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
 static void hub_release(struct kref *kref);
 static int usb_reset_and_verify_device(struct usb_device *udev);
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
+static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+               u16 portstatus);
 
 static inline char *portspeed(struct usb_hub *hub, int portstatus)
 {
@@ -1111,6 +1113,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                                                   USB_PORT_FEAT_ENABLE);
                }
 
+               /* Make sure a warm-reset request is handled by port_event */
+               if (type == HUB_RESUME &&
+                   hub_port_warm_reset_required(hub, port1, portstatus))
+                       set_bit(port1, hub->event_bits);
+
                /*
                 * Add debounce if USB3 link is in polling/link training state.
                 * Link will automatically transition to Enabled state after
index aad7edc..a5c8329 100644 (file)
@@ -3568,6 +3568,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
        u32 port_status;
        u32 speed;
        u32 pcgctl;
+       u32 pwr;
 
        switch (typereq) {
        case ClearHubFeature:
@@ -3616,8 +3617,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        dev_dbg(hsotg->dev,
                                "ClearPortFeature USB_PORT_FEAT_POWER\n");
                        hprt0 = dwc2_read_hprt0(hsotg);
+                       pwr = hprt0 & HPRT0_PWR;
                        hprt0 &= ~HPRT0_PWR;
                        dwc2_writel(hsotg, hprt0, HPRT0);
+                       if (pwr)
+                               dwc2_vbus_supply_exit(hsotg);
                        break;
 
                case USB_PORT_FEAT_INDICATOR:
@@ -3827,8 +3831,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        dev_dbg(hsotg->dev,
                                "SetPortFeature - USB_PORT_FEAT_POWER\n");
                        hprt0 = dwc2_read_hprt0(hsotg);
+                       pwr = hprt0 & HPRT0_PWR;
                        hprt0 |= HPRT0_PWR;
                        dwc2_writel(hsotg, hprt0, HPRT0);
+                       if (!pwr)
+                               dwc2_vbus_supply_init(hsotg);
                        break;
 
                case USB_PORT_FEAT_RESET:
@@ -3845,6 +3852,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        dwc2_writel(hsotg, 0, PCGCTL);
 
                        hprt0 = dwc2_read_hprt0(hsotg);
+                       pwr = hprt0 & HPRT0_PWR;
                        /* Clear suspend bit if resetting from suspend state */
                        hprt0 &= ~HPRT0_SUSP;
 
@@ -3858,6 +3866,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                dev_dbg(hsotg->dev,
                                        "In host mode, hprt0=%08x\n", hprt0);
                                dwc2_writel(hsotg, hprt0, HPRT0);
+                               if (!pwr)
+                                       dwc2_vbus_supply_init(hsotg);
                        }
 
                        /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
@@ -4400,6 +4410,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
        struct usb_bus *bus = hcd_to_bus(hcd);
        unsigned long flags;
+       u32 hprt0;
        int ret;
 
        dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
@@ -4416,12 +4427,16 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
 
        dwc2_hcd_reinit(hsotg);
 
-       /* enable external vbus supply before resuming root hub */
-       spin_unlock_irqrestore(&hsotg->lock, flags);
-       ret = dwc2_vbus_supply_init(hsotg);
-       if (ret)
-               return ret;
-       spin_lock_irqsave(&hsotg->lock, flags);
+       hprt0 = dwc2_read_hprt0(hsotg);
+       /* Has vbus power been turned on in dwc2_core_host_init ? */
+       if (hprt0 & HPRT0_PWR) {
+               /* Enable external vbus supply before resuming root hub */
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               ret = dwc2_vbus_supply_init(hsotg);
+               if (ret)
+                       return ret;
+               spin_lock_irqsave(&hsotg->lock, flags);
+       }
 
        /* Initialize and connect root hub if one is not already attached */
        if (bus->root_hub) {
@@ -4443,6 +4458,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 {
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
        unsigned long flags;
+       u32 hprt0;
 
        /* Turn off all host-specific interrupts */
        dwc2_disable_host_interrupts(hsotg);
@@ -4451,6 +4467,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
        synchronize_irq(hcd->irq);
 
        spin_lock_irqsave(&hsotg->lock, flags);
+       hprt0 = dwc2_read_hprt0(hsotg);
        /* Ensure hcd is disconnected */
        dwc2_hcd_disconnect(hsotg, true);
        dwc2_hcd_stop(hsotg);
@@ -4459,7 +4476,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
-       dwc2_vbus_supply_exit(hsotg);
+       /* keep balanced supply init/exit by checking HPRT0_PWR */
+       if (hprt0 & HPRT0_PWR)
+               dwc2_vbus_supply_exit(hsotg);
 
        usleep_range(1000, 3000);
 }
index e7461c9..54de732 100644 (file)
@@ -375,19 +375,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
 
        trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
 
-       if (ret == 0) {
-               switch (DWC3_DEPCMD_CMD(cmd)) {
-               case DWC3_DEPCMD_STARTTRANSFER:
-                       dep->flags |= DWC3_EP_TRANSFER_STARTED;
-                       dwc3_gadget_ep_get_transfer_index(dep);
-                       break;
-               case DWC3_DEPCMD_ENDTRANSFER:
-                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-                       break;
-               default:
-                       /* nothing */
-                       break;
-               }
+       if (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
+               dep->flags |= DWC3_EP_TRANSFER_STARTED;
+               dwc3_gadget_ep_get_transfer_index(dep);
        }
 
        if (unlikely(susphy)) {
@@ -1410,7 +1400,10 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
                                goto out0;
 
                        dwc3_gadget_move_cancelled_request(req);
-                       goto out0;
+                       if (dep->flags & DWC3_EP_TRANSFER_STARTED)
+                               goto out0;
+                       else
+                               goto out1;
                }
                dev_err(dwc->dev, "request %pK was not queued to %s\n",
                                request, ep->name);
@@ -1418,6 +1411,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
                goto out0;
        }
 
+out1:
        dwc3_gadget_giveback(dep, req, -ECONNRESET);
 
 out0:
@@ -2413,7 +2407,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
                if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
-                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
+                       dep->flags &= ~(DWC3_EP_END_TRANSFER_PENDING |
+                                       DWC3_EP_TRANSFER_STARTED);
                        dwc3_gadget_ep_cleanup_cancelled_requests(dep);
                }
                break;
index af88b48..1a79a99 100644 (file)
@@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep)
        if (ep->enabled)
                goto out;
 
+       /* UDC drivers can't handle endpoints with maxpacket size 0 */
+       if (usb_endpoint_maxp(ep->desc) == 0) {
+               /*
+                * We should log an error message here, but we can't call
+                * dev_err() because there's no way to find the gadget
+                * given only ep.
+                */
+               ret = -EINVAL;
+               goto out;
+       }
+
        ret = ep->ops->enable(ep, ep->desc);
        if (ret)
                goto out;
@@ -1138,7 +1149,7 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
                                                dev_name(&udc->dev)) == 0) {
                        ret = udc_bind_to_driver(udc, driver);
                        if (ret != -EPROBE_DEFER)
-                               list_del(&driver->pending);
+                               list_del_init(&driver->pending);
                        break;
                }
 
index 7ba6afc..76c3f29 100644 (file)
@@ -202,10 +202,10 @@ static void xhci_ring_dump_segment(struct seq_file *s,
                trb = &seg->trbs[i];
                dma = seg->dma + i * sizeof(*trb);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_trb(trb->generic.field[0],
-                                          trb->generic.field[1],
-                                          trb->generic.field[2],
-                                          trb->generic.field[3]));
+                          xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
+                                          le32_to_cpu(trb->generic.field[1]),
+                                          le32_to_cpu(trb->generic.field[2]),
+                                          le32_to_cpu(trb->generic.field[3])));
        }
 }
 
@@ -263,10 +263,10 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused)
        xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
        slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
        seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
-                  xhci_decode_slot_context(slot_ctx->dev_info,
-                                           slot_ctx->dev_info2,
-                                           slot_ctx->tt_info,
-                                           slot_ctx->dev_state));
+                  xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
+                                           le32_to_cpu(slot_ctx->dev_info2),
+                                           le32_to_cpu(slot_ctx->tt_info),
+                                           le32_to_cpu(slot_ctx->dev_state)));
 
        return 0;
 }
@@ -286,10 +286,10 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
                ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci);
                dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_ep_context(ep_ctx->ep_info,
-                                                 ep_ctx->ep_info2,
-                                                 ep_ctx->deq,
-                                                 ep_ctx->tx_info));
+                          xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info),
+                                                 le32_to_cpu(ep_ctx->ep_info2),
+                                                 le64_to_cpu(ep_ctx->deq),
+                                                 le32_to_cpu(ep_ctx->tx_info)));
        }
 
        return 0;
index 6b3a6fd..320b06e 100644 (file)
@@ -495,11 +495,11 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
                retval = -EFAULT;
                goto unlock_exit;
        }
-       dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
-
        retval = bytes_to_read;
 
        spin_lock_irq(&dev->rbsl);
+       dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
+
        if (dev->buffer_overflow) {
                dev->buffer_overflow = 0;
                spin_unlock_irq(&dev->rbsl);
@@ -580,7 +580,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
                                         1 << 8, 0,
                                         dev->interrupt_out_buffer,
                                         bytes_to_write,
-                                        USB_CTRL_SET_TIMEOUT * HZ);
+                                        USB_CTRL_SET_TIMEOUT);
                if (retval < 0)
                        dev_err(&dev->intf->dev,
                                "Couldn't submit HID_REQ_SET_REPORT %d\n",
index 62dab24..23061f1 100644 (file)
@@ -878,7 +878,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
                                  get_version_reply,
                                  sizeof(*get_version_reply),
                                  1000);
-       if (result < sizeof(*get_version_reply)) {
+       if (result != sizeof(*get_version_reply)) {
                if (result >= 0)
                        result = -EIO;
                dev_err(idev, "get version request failed: %d\n", result);
index 1c7b46a..16b2751 100644 (file)
@@ -571,6 +571,10 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
 
        command_port = port->serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
+
+       if (command_port->bulk_out_size < datasize + 1)
+               return -EIO;
+
        mutex_lock(&command_info->mutex);
        command_info->command_finished = false;
 
@@ -644,6 +648,7 @@ static void firm_setup_port(struct tty_struct *tty)
        struct device *dev = &port->dev;
        struct whiteheat_port_settings port_settings;
        unsigned int cflag = tty->termios.c_cflag;
+       speed_t baud;
 
        port_settings.port = port->port_number + 1;
 
@@ -704,11 +709,13 @@ static void firm_setup_port(struct tty_struct *tty)
        dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff);
 
        /* get the baud rate wanted */
-       port_settings.baud = tty_get_baud_rate(tty);
-       dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud);
+       baud = tty_get_baud_rate(tty);
+       port_settings.baud = cpu_to_le32(baud);
+       dev_dbg(dev, "%s - baud rate = %u\n", __func__, baud);
 
        /* fixme: should set validated settings */
-       tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
+       tty_encode_baud_rate(tty, baud, baud);
+
        /* handle any settings that aren't specified in the tty structure */
        port_settings.lloop = 0;
 
index 72c1b0c..56a3e83 100644 (file)
@@ -87,7 +87,7 @@ struct whiteheat_simple {
 
 struct whiteheat_port_settings {
        __u8    port;           /* port number (1 to N) */
-       __u32   baud;           /* any value 7 - 460800, firmware calculates
+       __le32  baud;           /* any value 7 - 460800, firmware calculates
                                   best fit; arrives little endian */
        __u8    bits;           /* 5, 6, 7, or 8 */
        __u8    stop;           /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
index 59d82b4..f287ee8 100644 (file)
@@ -65,7 +65,6 @@ static const char* host_info(struct Scsi_Host *host)
 static int slave_alloc (struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
-       int maxp;
 
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
@@ -75,15 +74,6 @@ static int slave_alloc (struct scsi_device *sdev)
        sdev->inquiry_len = 36;
 
        /*
-        * USB has unusual scatter-gather requirements: the length of each
-        * scatterlist element except the last must be divisible by the
-        * Bulk maxpacket value.  Fortunately this value is always a
-        * power of 2.  Inform the block layer about this requirement.
-        */
-       maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
-       blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
-
-       /*
         * Some host controllers may have alignment requirements.
         * We'll play it safe by requiring 512-byte alignment always.
         */
index 5b1d093..bad391d 100644 (file)
@@ -796,30 +796,10 @@ static int uas_slave_alloc(struct scsi_device *sdev)
 {
        struct uas_dev_info *devinfo =
                (struct uas_dev_info *)sdev->host->hostdata;
-       int maxp;
 
        sdev->hostdata = devinfo;
 
        /*
-        * We have two requirements here. We must satisfy the requirements
-        * of the physical HC and the demands of the protocol, as we
-        * definitely want no additional memory allocation in this path
-        * ruling out using bounce buffers.
-        *
-        * For a transmission on USB to continue we must never send
-        * a package that is smaller than maxpacket. Hence the length of each
-         * scatterlist element except the last must be divisible by the
-         * Bulk maxpacket value.
-        * If the HC does not ensure that through SG,
-        * the upper layer must do that. We must assume nothing
-        * about the capabilities off the HC, so we use the most
-        * pessimistic requirement.
-        */
-
-       maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0);
-       blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
-
-       /*
         * The protocol has no requirements on alignment in the strict sense.
         * Controllers may or may not have alignment restrictions.
         * As this is not exported, we use an extremely conservative guess.
index bf44742..9209100 100644 (file)
@@ -217,6 +217,8 @@ static int hgcm_call_preprocess_linaddr(
        if (!bounce_buf)
                return -ENOMEM;
 
+       *bounce_buf_ret = bounce_buf;
+
        if (copy_in) {
                ret = copy_from_user(bounce_buf, (void __user *)buf, len);
                if (ret)
@@ -225,7 +227,6 @@ static int hgcm_call_preprocess_linaddr(
                memset(bounce_buf, 0, len);
        }
 
-       *bounce_buf_ret = bounce_buf;
        hgcm_call_add_pagelist_size(bounce_buf, len, extra);
        return 0;
 }
index 7cde3f4..e996174 100644 (file)
 #include <linux/err.h>
 #include <linux/fs.h>
 
+static inline bool spacetab(char c) { return c == ' ' || c == '\t'; }
+static inline char *next_non_spacetab(char *first, const char *last)
+{
+       for (; first <= last; first++)
+               if (!spacetab(*first))
+                       return first;
+       return NULL;
+}
+static inline char *next_terminator(char *first, const char *last)
+{
+       for (; first <= last; first++)
+               if (spacetab(*first) || !*first)
+                       return first;
+       return NULL;
+}
+
 static int load_script(struct linux_binprm *bprm)
 {
        const char *i_arg, *i_name;
-       char *cp;
+       char *cp, *buf_end;
        struct file *file;
        int retval;
 
+       /* Not ours to exec if we don't start with "#!". */
        if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
                return -ENOEXEC;
 
@@ -33,18 +50,40 @@ static int load_script(struct linux_binprm *bprm)
        if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
                return -ENOENT;
 
-       /*
-        * This section does the #! interpretation.
-        * Sorta complicated, but hopefully it will work.  -TYT
-        */
-
+       /* Release since we are not mapping a binary into memory. */
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
 
-       bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
-       if ((cp = strchr(bprm->buf, '\n')) == NULL)
-               cp = bprm->buf+BINPRM_BUF_SIZE-1;
+       /*
+        * This section handles parsing the #! line into separate
+        * interpreter path and argument strings. We must be careful
+        * because bprm->buf is not yet guaranteed to be NUL-terminated
+        * (though the buffer will have trailing NUL padding when the
+        * file size was smaller than the buffer size).
+        *
+        * We do not want to exec a truncated interpreter path, so either
+        * we find a newline (which indicates nothing is truncated), or
+        * we find a space/tab/NUL after the interpreter path (which
+        * itself may be preceded by spaces/tabs). Truncating the
+        * arguments is fine: the interpreter can re-read the script to
+        * parse them on its own.
+        */
+       buf_end = bprm->buf + sizeof(bprm->buf) - 1;
+       cp = strnchr(bprm->buf, sizeof(bprm->buf), '\n');
+       if (!cp) {
+               cp = next_non_spacetab(bprm->buf + 2, buf_end);
+               if (!cp)
+                       return -ENOEXEC; /* Entire buf is spaces/tabs */
+               /*
+                * If there is no later space/tab/NUL we must assume the
+                * interpreter path is truncated.
+                */
+               if (!next_terminator(cp, buf_end))
+                       return -ENOEXEC;
+               cp = buf_end;
+       }
+       /* NUL-terminate the buffer and any trailing spaces/tabs. */
        *cp = '\0';
        while (cp > bprm->buf) {
                cp--;
index faca485..cc2d268 100644 (file)
@@ -2747,8 +2747,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
                                     int nitems, bool use_global_rsv);
 void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info,
                                      struct btrfs_block_rsv *rsv);
-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
-                                   bool qgroup_free);
+void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
 
 int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes);
 void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
@@ -3178,6 +3177,9 @@ void btrfs_destroy_inode(struct inode *inode);
 int btrfs_drop_inode(struct inode *inode);
 int __init btrfs_init_cachep(void);
 void __cold btrfs_destroy_cachep(void);
+struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
+                             struct btrfs_root *root, int *new,
+                             struct btrfs_path *path);
 struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                         struct btrfs_root *root, int *was_new);
 struct extent_map *btrfs_get_extent(struct btrfs_inode *inode,
index 72c7456..024dd33 100644 (file)
@@ -5980,8 +5980,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
  * temporarily tracked outstanding_extents.  This _must_ be used in conjunction
  * with btrfs_delalloc_reserve_metadata.
  */
-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
-                                   bool qgroup_free)
+void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        unsigned num_extents;
@@ -5995,7 +5994,7 @@ void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
        if (btrfs_is_testing(fs_info))
                return;
 
-       btrfs_inode_rsv_release(inode, qgroup_free);
+       btrfs_inode_rsv_release(inode, true);
 }
 
 /**
index 4870440..a456801 100644 (file)
@@ -1591,7 +1591,6 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct page **pages = NULL;
-       struct extent_state *cached_state = NULL;
        struct extent_changeset *data_reserved = NULL;
        u64 release_bytes = 0;
        u64 lockstart;
@@ -1612,6 +1611,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 
        while (iov_iter_count(i) > 0) {
                size_t offset = pos & (PAGE_SIZE - 1);
+               struct extent_state *cached_state = NULL;
                size_t sector_offset;
                size_t write_bytes = min(iov_iter_count(i),
                                         nrptrs * (size_t)PAGE_SIZE -
@@ -1692,7 +1692,7 @@ again:
                                    force_page_uptodate);
                if (ret) {
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      reserve_bytes, true);
+                                                      reserve_bytes);
                        break;
                }
 
@@ -1704,7 +1704,7 @@ again:
                        if (extents_locked == -EAGAIN)
                                goto again;
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      reserve_bytes, true);
+                                                      reserve_bytes);
                        ret = extents_locked;
                        break;
                }
@@ -1758,11 +1758,21 @@ again:
                if (copied > 0)
                        ret = btrfs_dirty_pages(inode, pages, dirty_pages,
                                                pos, copied, &cached_state);
+
+               /*
+                * If we have not locked the extent range, because the range's
+                * start offset is >= i_size, we might still have a non-NULL
+                * cached extent state, acquired while marking the extent range
+                * as delalloc through btrfs_dirty_pages(). Therefore free any
+                * possible cached extent state to avoid a memory leak.
+                */
                if (extents_locked)
                        unlock_extent_cached(&BTRFS_I(inode)->io_tree,
                                             lockstart, lockend, &cached_state);
-               btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
-                                              true);
+               else
+                       free_extent_state(cached_state);
+
+               btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes);
                if (ret) {
                        btrfs_drop_pages(pages, num_pages);
                        break;
index 4381e0a..ec01bd3 100644 (file)
@@ -75,7 +75,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
         * sure NOFS is set to keep us from deadlocking.
         */
        nofs_flag = memalloc_nofs_save();
-       inode = btrfs_iget(fs_info->sb, &location, root, NULL);
+       inode = btrfs_iget_path(fs_info->sb, &location, root, NULL, path);
+       btrfs_release_path(path);
        memalloc_nofs_restore(nofs_flag);
        if (IS_ERR(inode))
                return inode;
@@ -839,6 +840,25 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
        path->search_commit_root = 1;
        path->skip_locking = 1;
 
+       /*
+        * We must pass a path with search_commit_root set to btrfs_iget in
+        * order to avoid a deadlock when allocating extents for the tree root.
+        *
+        * When we are COWing an extent buffer from the tree root, when looking
+        * for a free extent, at extent-tree.c:find_free_extent(), we can find
+        * block group without its free space cache loaded. When we find one
+        * we must load its space cache which requires reading its free space
+        * cache's inode item from the root tree. If this inode item is located
+        * in the same leaf that we started COWing before, then we end up in
+        * deadlock on the extent buffer (trying to read lock it when we
+        * previously write locked it).
+        *
+        * It's safe to read the inode item using the commit root because
+        * block groups, once loaded, stay in memory forever (until they are
+        * removed) as well as their space caches once loaded. New block groups
+        * once created get their ->cached field set to BTRFS_CACHE_FINISHED so
+        * we will never try to read their inode item while the fs is mounted.
+        */
        inode = lookup_free_space_inode(fs_info, block_group, path);
        if (IS_ERR(inode)) {
                btrfs_free_path(path);
index ffca2ab..e1b50c6 100644 (file)
@@ -483,12 +483,13 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc,
                                              prealloc, prealloc, &alloc_hint);
        if (ret) {
-               btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
+               btrfs_delalloc_release_metadata(BTRFS_I(inode), prealloc, true);
                goto out_put;
        }
 
        ret = btrfs_write_out_ino_cache(root, trans, path, inode);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
 out_put:
        iput(inode);
 out_release:
index 37332f8..f0f7bc5 100644 (file)
@@ -2166,7 +2166,7 @@ again:
 
        ClearPageChecked(page);
        set_page_dirty(page);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
 out:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
                             &cached_state);
@@ -3607,10 +3607,11 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
 /*
  * read an inode from the btree into the in-memory inode
  */
-static int btrfs_read_locked_inode(struct inode *inode)
+static int btrfs_read_locked_inode(struct inode *inode,
+                                  struct btrfs_path *in_path)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
-       struct btrfs_path *path;
+       struct btrfs_path *path = in_path;
        struct extent_buffer *leaf;
        struct btrfs_inode_item *inode_item;
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -3626,15 +3627,18 @@ static int btrfs_read_locked_inode(struct inode *inode)
        if (!ret)
                filled = true;
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               path = btrfs_alloc_path();
+               if (!path)
+                       return -ENOMEM;
+       }
 
        memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
 
        ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
        if (ret) {
-               btrfs_free_path(path);
+               if (path != in_path)
+                       btrfs_free_path(path);
                return ret;
        }
 
@@ -3774,7 +3778,8 @@ cache_acl:
                                  btrfs_ino(BTRFS_I(inode)),
                                  root->root_key.objectid, ret);
        }
-       btrfs_free_path(path);
+       if (path != in_path)
+               btrfs_free_path(path);
 
        if (!maybe_acls)
                cache_no_acl(inode);
@@ -4918,7 +4923,7 @@ again:
        if (!page) {
                btrfs_delalloc_release_space(inode, data_reserved,
                                             block_start, blocksize, true);
-               btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
                ret = -ENOMEM;
                goto out;
        }
@@ -4986,7 +4991,7 @@ out_unlock:
        if (ret)
                btrfs_delalloc_release_space(inode, data_reserved, block_start,
                                             blocksize, true);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, (ret != 0));
+       btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
        unlock_page(page);
        put_page(page);
 out:
@@ -5716,8 +5721,9 @@ static struct inode *btrfs_iget_locked(struct super_block *s,
 /* Get an inode object given its location and corresponding root.
  * Returns in *is_new if the inode was read from disk
  */
-struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
-                        struct btrfs_root *root, int *new)
+struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
+                             struct btrfs_root *root, int *new,
+                             struct btrfs_path *path)
 {
        struct inode *inode;
 
@@ -5728,7 +5734,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
        if (inode->i_state & I_NEW) {
                int ret;
 
-               ret = btrfs_read_locked_inode(inode);
+               ret = btrfs_read_locked_inode(inode, path);
                if (!ret) {
                        inode_tree_add(inode);
                        unlock_new_inode(inode);
@@ -5750,6 +5756,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
        return inode;
 }
 
+struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
+                        struct btrfs_root *root, int *new)
+{
+       return btrfs_iget_path(s, location, root, new, NULL);
+}
+
 static struct inode *new_simple_dir(struct super_block *s,
                                    struct btrfs_key *key,
                                    struct btrfs_root *root)
@@ -8660,7 +8672,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                } else if (ret >= 0 && (size_t)ret < count)
                        btrfs_delalloc_release_space(inode, data_reserved,
                                        offset, count - (size_t)ret, true);
-               btrfs_delalloc_release_extents(BTRFS_I(inode), count, false);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), count);
        }
 out:
        if (wakeup)
@@ -9013,7 +9025,7 @@ again:
        unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
 
        if (!ret2) {
-               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
                sb_end_pagefault(inode->i_sb);
                extent_changeset_free(data_reserved);
                return VM_FAULT_LOCKED;
@@ -9022,7 +9034,7 @@ again:
 out_unlock:
        unlock_page(page);
 out:
-       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, (ret != 0));
+       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
        btrfs_delalloc_release_space(inode, data_reserved, page_start,
                                     reserved_space, (ret != 0));
 out_noreserve:
index 0eb333c..7592beb 100644 (file)
@@ -1359,8 +1359,7 @@ again:
                unlock_page(pages[i]);
                put_page(pages[i]);
        }
-       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
-                                      false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
        extent_changeset_free(data_reserved);
        return i_done;
 out:
@@ -1371,8 +1370,7 @@ out:
        btrfs_delalloc_release_space(inode, data_reserved,
                        start_index << PAGE_SHIFT,
                        page_cnt << PAGE_SHIFT, true);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
-                                      true);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
        extent_changeset_free(data_reserved);
        return ret;
 
index 3ea2008..cdd6d50 100644 (file)
@@ -3259,7 +3259,7 @@ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
                return 0;
 
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
-       trace_qgroup_meta_reserve(root, type, (s64)num_bytes);
+       trace_qgroup_meta_reserve(root, (s64)num_bytes, type);
        ret = qgroup_reserve(root, num_bytes, enforce, type);
        if (ret < 0)
                return ret;
@@ -3306,7 +3306,7 @@ void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
         */
        num_bytes = sub_root_meta_rsv(root, num_bytes, type);
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
-       trace_qgroup_meta_reserve(root, type, -(s64)num_bytes);
+       trace_qgroup_meta_reserve(root, -(s64)num_bytes, type);
        btrfs_qgroup_free_refroot(fs_info, root->objectid, num_bytes, type);
 }
 
index bccd9de..b4958f7 100644 (file)
@@ -3188,7 +3188,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                                btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                        PAGE_SIZE, true);
                                btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                       PAGE_SIZE, true);
+                                                       PAGE_SIZE);
                                ret = -ENOMEM;
                                goto out;
                        }
@@ -3209,7 +3209,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                                btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                        PAGE_SIZE, true);
                                btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                              PAGE_SIZE, true);
+                                                              PAGE_SIZE);
                                ret = -EIO;
                                goto out;
                        }
@@ -3238,7 +3238,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                        btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                         PAGE_SIZE, true);
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      PAGE_SIZE, true);
+                                                      PAGE_SIZE);
 
                        clear_extent_bits(&BTRFS_I(inode)->io_tree,
                                          page_start, page_end,
@@ -3254,8 +3254,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                put_page(page);
 
                index++;
-               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE,
-                                              false);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
                balance_dirty_pages_ratelimited(inode->i_mapping);
                btrfs_throttle(fs_info);
        }
index 4dbae6e..71c2dd0 100644 (file)
@@ -1286,6 +1286,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 struct cifsInodeInfo {
        bool can_cache_brlcks;
        struct list_head llist; /* locks helb by this inode */
+       /*
+        * NOTE: Some code paths call down_read(lock_sem) twice, so
+        * we must always use use cifs_down_write() instead of down_write()
+        * for this semaphore to avoid deadlocks.
+        */
        struct rw_semaphore lock_sem;   /* protect the fields above */
        /* BB add in lists for dirty pages i.e. write caching info for oplock */
        struct list_head openFileList;
index 20adda4..d7ac75e 100644 (file)
@@ -159,6 +159,7 @@ extern int cifs_unlock_range(struct cifsFileInfo *cfile,
                             struct file_lock *flock, const unsigned int xid);
 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
 
+extern void cifs_down_write(struct rw_semaphore *sem);
 extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid,
                                              struct file *file,
                                              struct tcon_link *tlink,
index 86a54b8..8b94719 100644 (file)
@@ -1521,9 +1521,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* set up first two iov for signature check and to get credits */
        rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->total_read - 4;
+       rdata->iov[0].iov_len = server->vals->header_preamble_size;
+       rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
+       rdata->iov[1].iov_len =
+               server->total_read - server->vals->header_preamble_size;
        cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
        cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
index 966e493..7e85070 100644 (file)
@@ -930,6 +930,26 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        return 0;
 }
 
+static void
+smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
+{
+       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
+
+       /*
+        * SMB1 does not use credits.
+        */
+       if (server->vals->header_preamble_size)
+               return;
+
+       if (shdr->CreditRequest) {
+               spin_lock(&server->req_lock);
+               server->credits += le16_to_cpu(shdr->CreditRequest);
+               spin_unlock(&server->req_lock);
+               wake_up(&server->request_q);
+       }
+}
+
+
 static int
 cifs_demultiplex_thread(void *p)
 {
@@ -1059,6 +1079,7 @@ next_pdu:
                        } else if (server->ops->is_oplock_break &&
                                   server->ops->is_oplock_break(bufs[i],
                                                                server)) {
+                               smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dbg(FYI, "Received oplock break\n");
                        } else {
                                cifs_dbg(VFS, "No task to wake, unknown frame "
@@ -1070,6 +1091,7 @@ next_pdu:
                                if (server->ops->dump_detail)
                                        server->ops->dump_detail(bufs[i],
                                                                 server);
+                               smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dump_mids(server);
 #endif /* CIFS_DEBUG2 */
                        }
index b4e33ef..a8e2bc4 100644 (file)
@@ -280,6 +280,13 @@ cifs_has_mand_locks(struct cifsInodeInfo *cinode)
        return has_locks;
 }
 
+void
+cifs_down_write(struct rw_semaphore *sem)
+{
+       while (!down_write_trylock(sem))
+               msleep(10);
+}
+
 struct cifsFileInfo *
 cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
                  struct tcon_link *tlink, __u32 oplock)
@@ -305,7 +312,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        INIT_LIST_HEAD(&fdlocks->locks);
        fdlocks->cfile = cfile;
        cfile->llist = fdlocks;
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_add(&fdlocks->llist, &cinode->llist);
        up_write(&cinode->lock_sem);
 
@@ -461,7 +468,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
         * Delete any outstanding lock records. We'll lose them when the file
         * is closed anyway.
         */
-       down_write(&cifsi->lock_sem);
+       cifs_down_write(&cifsi->lock_sem);
        list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
                list_del(&li->llist);
                cifs_del_lock_waiters(li);
@@ -1016,7 +1023,7 @@ static void
 cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
 {
        struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_add_tail(&lock->llist, &cfile->llist->locks);
        up_write(&cinode->lock_sem);
 }
@@ -1038,7 +1045,7 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
 
 try_again:
        exist = false;
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
 
        exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
                                        lock->type, &conf_lock, CIFS_LOCK_OP);
@@ -1060,7 +1067,7 @@ try_again:
                                        (lock->blist.next == &lock->blist));
                if (!rc)
                        goto try_again;
-               down_write(&cinode->lock_sem);
+               cifs_down_write(&cinode->lock_sem);
                list_del_init(&lock->blist);
        }
 
@@ -1113,7 +1120,7 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
                return rc;
 
 try_again:
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        if (!cinode->can_cache_brlcks) {
                up_write(&cinode->lock_sem);
                return rc;
@@ -1319,7 +1326,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
        int rc = 0;
 
        /* we are going to update can_cache_brlcks here - need a write access */
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        if (!cinode->can_cache_brlcks) {
                up_write(&cinode->lock_sem);
                return rc;
@@ -1510,7 +1517,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
        if (!buf)
                return -ENOMEM;
 
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        for (i = 0; i < 2; i++) {
                cur = buf;
                num = 0;
index fdd908e..66c1012 100644 (file)
@@ -130,10 +130,6 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
        {0, 0}
 };
 
-static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
-       {0, 0}
-};
-
 /*
  * Convert a string containing text IPv4 or IPv6 address to binary form.
  *
index b204e84..9168b22 100644 (file)
@@ -137,7 +137,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        cur = buf;
 
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
                if (flock->fl_start > li->offset ||
                    (flock->fl_start + length) <
index 0a7ed2e..e311f58 100644 (file)
@@ -659,13 +659,6 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
                return false;
 
-       if (rsp->sync_hdr.CreditRequest) {
-               spin_lock(&server->req_lock);
-               server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
-               spin_unlock(&server->req_lock);
-               wake_up(&server->request_q);
-       }
-
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
index f0d966d..6fc1632 100644 (file)
@@ -3000,10 +3000,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 
        /* set up first two iov to get credits */
        rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[0].iov_len = 0;
+       rdata->iov[1].iov_base = buf;
        rdata->iov[1].iov_len =
-               min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
+               min_t(unsigned int, buf_len, server->vals->read_rsp_size);
        cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
        cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
index abb6fcf..783c54b 100644 (file)
@@ -132,6 +132,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
 
        if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode) ||
            IS_SWAPFILE(inode) || IS_ENCRYPTED(inode) ||
+           (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL) ||
            ext4_has_inline_data(inode)) {
                err = -EINVAL;
                goto journal_err_out;
index 0b224f4..2c3be4c 100644 (file)
@@ -226,6 +226,9 @@ static void recover_inode(struct inode *inode, struct page *page)
 
        F2FS_I(inode)->i_advise = raw->i_advise;
        F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
+       f2fs_set_inode_flags(inode);
+       F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] =
+                               le16_to_cpu(raw->i_gc_failures);
 
        recover_inline_flags(inode, raw);
 
index 6851afc..d9106bb 100644 (file)
@@ -1886,6 +1886,12 @@ void f2fs_quota_off_umount(struct super_block *sb)
                        set_sbi_flag(F2FS_SB(sb), SBI_NEED_FSCK);
                }
        }
+       /*
+        * In case of checkpoint=disable, we must flush quota blocks.
+        * This can cause NULL exception for node_inode in end_io, since
+        * put_super already dropped it.
+        */
+       sync_filesystem(sb);
 }
 
 static void f2fs_truncate_quota_inode_pages(struct super_block *sb)
index 82a1322..e7a2a98 100644 (file)
@@ -1665,6 +1665,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
        if (attr->ia_valid & ATTR_SIZE)
                is_truncate = true;
 
+       /* Flush dirty data/metadata before non-truncate SETATTR */
+       if (is_wb && S_ISREG(inode->i_mode) &&
+           attr->ia_valid &
+                       (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
+                        ATTR_TIMES_SET)) {
+               err = write_inode_now(inode, true);
+               if (err)
+                       return err;
+
+               fuse_set_nowrite(inode);
+               fuse_release_nowrite(inode);
+       }
+
        if (is_truncate) {
                fuse_set_nowrite(inode);
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
index 96d46b3..3964325 100644 (file)
@@ -202,7 +202,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
-       bool lock_inode = (file->f_flags & O_TRUNC) &&
+       bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
                          fc->atomic_o_trunc &&
                          fc->writeback_cache;
 
@@ -210,16 +210,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
        if (err)
                return err;
 
-       if (lock_inode)
+       if (is_wb_truncate) {
                inode_lock(inode);
+               fuse_set_nowrite(inode);
+       }
 
        err = fuse_do_open(fc, get_node_id(inode), file, isdir);
 
        if (!err)
                fuse_finish_open(inode, file);
 
-       if (lock_inode)
+       if (is_wb_truncate) {
+               fuse_release_nowrite(inode);
                inode_unlock(inode);
+       }
 
        return err;
 }
index 1624618..825a8c5 100644 (file)
@@ -1154,7 +1154,7 @@ bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
        if (delegation != NULL &&
            nfs4_stateid_match_other(dst, &delegation->stateid)) {
                dst->seqid = delegation->stateid.seqid;
-               return ret;
+               ret = true;
        }
        rcu_read_unlock();
 out:
index 621e3cf..75faef7 100644 (file)
@@ -5943,6 +5943,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
        }
        status = task->tk_status;
        if (setclientid.sc_cred) {
+               kfree(clp->cl_acceptor);
                clp->cl_acceptor = rpcauth_stringify_acceptor(setclientid.sc_cred);
                put_rpccred(setclientid.sc_cred);
        }
index c36ef75..b3086e9 100644 (file)
@@ -2613,7 +2613,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                        return;
                if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
                        return;
-       } while (refcount_read(&clp->cl_count) > 1);
+       } while (refcount_read(&clp->cl_count) > 1 && !signalled());
        goto out_drain;
 
 out_error:
index 5ab9979..117ffd9 100644 (file)
@@ -783,7 +783,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page *head;
 
-       atomic_long_dec(&nfsi->nrequests);
        if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) {
                head = req->wb_head;
 
@@ -796,8 +795,10 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                spin_unlock(&mapping->private_lock);
        }
 
-       if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags))
+       if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
                nfs_release_request(req);
+               atomic_long_dec(&nfsi->nrequests);
+       }
 }
 
 static void
index 7578bd5..543efa3 100644 (file)
@@ -2056,7 +2056,8 @@ out_write_size:
                inode->i_mtime = inode->i_ctime = current_time(inode);
                di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
                di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
-               ocfs2_update_inode_fsync_trans(handle, inode, 1);
+               if (handle)
+                       ocfs2_update_inode_fsync_trans(handle, inode, 1);
        }
        if (handle)
                ocfs2_journal_dirty(handle, wc->w_di_bh);
@@ -2153,13 +2154,30 @@ static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock,
        struct ocfs2_dio_write_ctxt *dwc = NULL;
        struct buffer_head *di_bh = NULL;
        u64 p_blkno;
-       loff_t pos = iblock << inode->i_sb->s_blocksize_bits;
+       unsigned int i_blkbits = inode->i_sb->s_blocksize_bits;
+       loff_t pos = iblock << i_blkbits;
+       sector_t endblk = (i_size_read(inode) - 1) >> i_blkbits;
        unsigned len, total_len = bh_result->b_size;
        int ret = 0, first_get_block = 0;
 
        len = osb->s_clustersize - (pos & (osb->s_clustersize - 1));
        len = min(total_len, len);
 
+       /*
+        * bh_result->b_size is count in get_more_blocks according to write
+        * "pos" and "end", we need map twice to return different buffer state:
+        * 1. area in file size, not set NEW;
+        * 2. area out file size, set  NEW.
+        *
+        *                 iblock    endblk
+        * |--------|---------|---------|---------
+        * |<-------area in file------->|
+        */
+
+       if ((iblock <= endblk) &&
+           ((iblock + ((len - 1) >> i_blkbits)) > endblk))
+               len = (endblk - iblock + 1) << i_blkbits;
+
        mlog(0, "get block of %lu at %llu:%u req %u\n",
                        inode->i_ino, pos, len, total_len);
 
@@ -2243,6 +2261,9 @@ static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock,
        if (desc->c_needs_zero)
                set_buffer_new(bh_result);
 
+       if (iblock > endblk)
+               set_buffer_new(bh_result);
+
        /* May sleep in end_io. It should not happen in a irq context. So defer
         * it to dio work queue. */
        set_buffer_defer_completion(bh_result);
index 994726a..a6c3282 100644 (file)
@@ -290,7 +290,7 @@ static int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb,
        if (inode_alloc)
                inode_lock(inode_alloc);
 
-       if (o2info_coherent(&fi->ifi_req)) {
+       if (inode_alloc && o2info_coherent(&fi->ifi_req)) {
                status = ocfs2_inode_lock(inode_alloc, &bh, 0);
                if (status < 0) {
                        mlog_errno(status);
index c146e12..0d80e0d 100644 (file)
@@ -1498,18 +1498,6 @@ static int ocfs2_xa_check_space(struct ocfs2_xa_loc *loc,
        return loc->xl_ops->xlo_check_space(loc, xi);
 }
 
-static void ocfs2_xa_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash)
-{
-       loc->xl_ops->xlo_add_entry(loc, name_hash);
-       loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash);
-       /*
-        * We can't leave the new entry's xe_name_offset at zero or
-        * add_namevalue() will go nuts.  We set it to the size of our
-        * storage so that it can never be less than any other entry.
-        */
-       loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size);
-}
-
 static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc,
                                   struct ocfs2_xattr_info *xi)
 {
@@ -2141,29 +2129,31 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
        if (rc)
                goto out;
 
-       if (loc->xl_entry) {
-               if (ocfs2_xa_can_reuse_entry(loc, xi)) {
-                       orig_value_size = loc->xl_entry->xe_value_size;
-                       rc = ocfs2_xa_reuse_entry(loc, xi, ctxt);
-                       if (rc)
-                               goto out;
-                       goto alloc_value;
-               }
+       if (!loc->xl_entry) {
+               rc = -EINVAL;
+               goto out;
+       }
 
-               if (!ocfs2_xattr_is_local(loc->xl_entry)) {
-                       orig_clusters = ocfs2_xa_value_clusters(loc);
-                       rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
-                       if (rc) {
-                               mlog_errno(rc);
-                               ocfs2_xa_cleanup_value_truncate(loc,
-                                                               "overwriting",
-                                                               orig_clusters);
-                               goto out;
-                       }
+       if (ocfs2_xa_can_reuse_entry(loc, xi)) {
+               orig_value_size = loc->xl_entry->xe_value_size;
+               rc = ocfs2_xa_reuse_entry(loc, xi, ctxt);
+               if (rc)
+                       goto out;
+               goto alloc_value;
+       }
+
+       if (!ocfs2_xattr_is_local(loc->xl_entry)) {
+               orig_clusters = ocfs2_xa_value_clusters(loc);
+               rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
+               if (rc) {
+                       mlog_errno(rc);
+                       ocfs2_xa_cleanup_value_truncate(loc,
+                                                       "overwriting",
+                                                       orig_clusters);
+                       goto out;
                }
-               ocfs2_xa_wipe_namevalue(loc);
-       } else
-               ocfs2_xa_add_entry(loc, name_hash);
+       }
+       ocfs2_xa_wipe_namevalue(loc);
 
        /*
         * If we get here, we have a blank entry.  Fill it.  We grow our
index 24bcc5e..f78d1e8 100644 (file)
@@ -325,6 +325,29 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
        return !!(gfp_flags & __GFP_DIRECT_RECLAIM);
 }
 
+/**
+ * gfpflags_normal_context - is gfp_flags a normal sleepable context?
+ * @gfp_flags: gfp_flags to test
+ *
+ * Test whether @gfp_flags indicates that the allocation is from the
+ * %current context and allowed to sleep.
+ *
+ * An allocation being allowed to block doesn't mean it owns the %current
+ * context.  When direct reclaim path tries to allocate memory, the
+ * allocation context is nested inside whatever %current was doing at the
+ * time of the original allocation.  The nested allocation may be allowed
+ * to block but modifying anything %current owns can corrupt the outer
+ * context's expectations.
+ *
+ * %true result from this function indicates that the allocation context
+ * can sleep and use anything that's associated with %current.
+ */
+static inline bool gfpflags_normal_context(const gfp_t gfp_flags)
+{
+       return (gfp_flags & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC)) ==
+               __GFP_DIRECT_RECLAIM;
+}
+
 #ifdef CONFIG_HIGHMEM
 #define OPT_ZONE_HIGHMEM ZONE_HIGHMEM
 #else
index 28baccb..80c3da1 100644 (file)
@@ -1251,7 +1251,8 @@ static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6
        return skb->hash;
 }
 
-__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb);
+__u32 skb_get_hash_perturb(const struct sk_buff *skb,
+                          const siphash_key_t *perturb);
 
 static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
 {
@@ -1380,6 +1381,19 @@ static inline int skb_queue_empty(const struct sk_buff_head *list)
 }
 
 /**
+ *     skb_queue_empty_lockless - check if a queue is empty
+ *     @list: queue head
+ *
+ *     Returns true if the queue is empty, false otherwise.
+ *     This variant can be used in lockless contexts.
+ */
+static inline bool skb_queue_empty_lockless(const struct sk_buff_head *list)
+{
+       return READ_ONCE(list->next) == (const struct sk_buff *) list;
+}
+
+
+/**
  *     skb_queue_is_last - check if skb is the last entry in the queue
  *     @list: queue head
  *     @skb: buffer
@@ -1723,9 +1737,11 @@ static inline void __skb_insert(struct sk_buff *newsk,
                                struct sk_buff *prev, struct sk_buff *next,
                                struct sk_buff_head *list)
 {
-       newsk->next = next;
-       newsk->prev = prev;
-       next->prev  = prev->next = newsk;
+       /* see skb_queue_empty_lockless() for the opposite READ_ONCE() */
+       WRITE_ONCE(newsk->next, next);
+       WRITE_ONCE(newsk->prev, prev);
+       WRITE_ONCE(next->prev, newsk);
+       WRITE_ONCE(prev->next, newsk);
        list->qlen++;
 }
 
@@ -1736,11 +1752,11 @@ static inline void __skb_queue_splice(const struct sk_buff_head *list,
        struct sk_buff *first = list->next;
        struct sk_buff *last = list->prev;
 
-       first->prev = prev;
-       prev->next = first;
+       WRITE_ONCE(first->prev, prev);
+       WRITE_ONCE(prev->next, first);
 
-       last->next = next;
-       next->prev = last;
+       WRITE_ONCE(last->next, next);
+       WRITE_ONCE(next->prev, last);
 }
 
 /**
@@ -1881,8 +1897,8 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
        next       = skb->next;
        prev       = skb->prev;
        skb->next  = skb->prev = NULL;
-       next->prev = prev;
-       prev->next = next;
+       WRITE_ONCE(next->prev, prev);
+       WRITE_ONCE(prev->next, next);
 }
 
 /**
index ba61cdd..cf8f792 100644 (file)
@@ -134,7 +134,7 @@ static inline void skb_mark_napi_id(struct sk_buff *skb,
 static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb)
 {
 #ifdef CONFIG_NET_RX_BUSY_POLL
-       sk->sk_napi_id = skb->napi_id;
+       WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
 #endif
        sk_rx_queue_set(sk, skb);
 }
@@ -144,8 +144,8 @@ static inline void sk_mark_napi_id_once(struct sock *sk,
                                        const struct sk_buff *skb)
 {
 #ifdef CONFIG_NET_RX_BUSY_POLL
-       if (!sk->sk_napi_id)
-               sk->sk_napi_id = skb->napi_id;
+       if (!READ_ONCE(sk->sk_napi_id))
+               WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
 #endif
 }
 
index 6a4586d..4618cbb 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/types.h>
 #include <linux/in6.h>
+#include <linux/siphash.h>
 #include <uapi/linux/if_ether.h>
 
 /**
@@ -252,7 +253,7 @@ struct flow_keys_basic {
 struct flow_keys {
        struct flow_dissector_key_control control;
 #define FLOW_KEYS_HASH_START_FIELD basic
-       struct flow_dissector_key_basic basic;
+       struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
        struct flow_dissector_key_tags tags;
        struct flow_dissector_key_vlan vlan;
        struct flow_dissector_key_vlan cvlan;
index ac944a6..c51be50 100644 (file)
@@ -70,7 +70,7 @@ struct fq {
        struct list_head backlogs;
        spinlock_t lock;
        u32 flows_cnt;
-       u32 perturbation;
+       siphash_key_t   perturbation;
        u32 limit;
        u32 memory_limit;
        u32 memory_usage;
index be7c0fa..89a0129 100644 (file)
@@ -118,7 +118,7 @@ static struct fq_flow *fq_flow_classify(struct fq *fq,
 
        lockdep_assert_held(&fq->lock);
 
-       hash = skb_get_hash_perturb(skb, fq->perturbation);
+       hash = skb_get_hash_perturb(skb, &fq->perturbation);
        idx = reciprocal_scale(hash, fq->flows_cnt);
        flow = &fq->flows[idx];
 
@@ -307,7 +307,7 @@ static int fq_init(struct fq *fq, int flows_cnt)
        INIT_LIST_HEAD(&fq->backlogs);
        spin_lock_init(&fq->lock);
        fq->flows_cnt = max_t(u32, flows_cnt, 1);
-       fq->perturbation = prandom_u32();
+       get_random_bytes(&fq->perturbation, sizeof(fq->perturbation));
        fq->quantum = 300;
        fq->limit = 8192;
        fq->memory_limit = 16 << 20; /* 16 MBytes */
index df528a6..ea985aa 100644 (file)
@@ -104,7 +104,7 @@ void llc_sk_reset(struct sock *sk);
 
 /* Access to a connection */
 int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
-int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
+void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
 void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
 void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit);
 void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit);
index 3f7b166..5007eab 100644 (file)
@@ -322,7 +322,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet)
 #define __net_initconst        __initconst
 #endif
 
-int peernet2id_alloc(struct net *net, struct net *peer);
+int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp);
 int peernet2id(struct net *net, struct net *peer);
 bool peernet_has_id(struct net *net, struct net *peer);
 struct net *get_net_ns_by_id(struct net *net, int id);
index c44da48..c9cd508 100644 (file)
@@ -421,6 +421,11 @@ static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
        return q;
 }
 
+static inline struct Qdisc *qdisc_root_bh(const struct Qdisc *qdisc)
+{
+       return rcu_dereference_bh(qdisc->dev_queue->qdisc);
+}
+
 static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
 {
        return qdisc->dev_queue->qdisc_sleeping;
index 1ece773..05e8faa 100644 (file)
@@ -945,8 +945,8 @@ static inline void sk_incoming_cpu_update(struct sock *sk)
 {
        int cpu = raw_smp_processor_id();
 
-       if (unlikely(sk->sk_incoming_cpu != cpu))
-               sk->sk_incoming_cpu = cpu;
+       if (unlikely(READ_ONCE(sk->sk_incoming_cpu) != cpu))
+               WRITE_ONCE(sk->sk_incoming_cpu, cpu);
 }
 
 static inline void sock_rps_record_flow_hash(__u32 hash)
@@ -2216,12 +2216,17 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
  * sk_page_frag - return an appropriate page_frag
  * @sk: socket
  *
- * If socket allocation mode allows current thread to sleep, it means its
- * safe to use the per task page_frag instead of the per socket one.
+ * Use the per task page_frag instead of the per socket one for
+ * optimization when we know that we're in the normal context and owns
+ * everything that's associated with %current.
+ *
+ * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest
+ * inside other socket operations and end up recursing into sk_page_frag()
+ * while it's already in use.
  */
 static inline struct page_frag *sk_page_frag(struct sock *sk)
 {
-       if (gfpflags_allow_blocking(sk->sk_allocation))
+       if (gfpflags_normal_context(sk->sk_allocation))
                return &current->task_frag;
 
        return &sk->sk_frag;
index 0fe169c..a08916e 100644 (file)
@@ -527,10 +527,10 @@ TRACE_EVENT(rxrpc_local,
            );
 
 TRACE_EVENT(rxrpc_peer,
-           TP_PROTO(struct rxrpc_peer *peer, enum rxrpc_peer_trace op,
+           TP_PROTO(unsigned int peer_debug_id, enum rxrpc_peer_trace op,
                     int usage, const void *where),
 
-           TP_ARGS(peer, op, usage, where),
+           TP_ARGS(peer_debug_id, op, usage, where),
 
            TP_STRUCT__entry(
                    __field(unsigned int,       peer            )
@@ -540,7 +540,7 @@ TRACE_EVENT(rxrpc_peer,
                             ),
 
            TP_fast_assign(
-                   __entry->peer = peer->debug_id;
+                   __entry->peer = peer_debug_id;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->where = where;
index 0796f93..54eb945 100644 (file)
@@ -739,7 +739,7 @@ void vtime_account_system(struct task_struct *tsk)
 
        write_seqcount_begin(&vtime->seqcount);
        /* We might have scheduled out from guest path */
-       if (current->flags & PF_VCPU)
+       if (tsk->flags & PF_VCPU)
                vtime_account_guest(tsk, vtime);
        else
                __vtime_account_system(tsk, vtime);
@@ -782,7 +782,7 @@ void vtime_guest_enter(struct task_struct *tsk)
         */
        write_seqcount_begin(&vtime->seqcount);
        __vtime_account_system(tsk, vtime);
-       current->flags |= PF_VCPU;
+       tsk->flags |= PF_VCPU;
        write_seqcount_end(&vtime->seqcount);
 }
 EXPORT_SYMBOL_GPL(vtime_guest_enter);
@@ -793,7 +793,7 @@ void vtime_guest_exit(struct task_struct *tsk)
 
        write_seqcount_begin(&vtime->seqcount);
        vtime_account_guest(tsk, vtime);
-       current->flags &= ~PF_VCPU;
+       tsk->flags &= ~PF_VCPU;
        write_seqcount_end(&vtime->seqcount);
 }
 EXPORT_SYMBOL_GPL(vtime_guest_exit);
index 27b17ea..bdd7f3d 100644 (file)
@@ -5766,6 +5766,7 @@ waitagain:
               sizeof(struct trace_iterator) -
               offsetof(struct trace_iterator, seq));
        cpumask_clear(iter->started);
+       trace_seq_init(&iter->seq);
        iter->pos = -1;
 
        trace_event_read_lock();
index bdf1045..dac5189 100644 (file)
@@ -448,6 +448,8 @@ static bool synth_field_signed(char *type)
 {
        if (strncmp(type, "u", 1) == 0)
                return false;
+       if (strcmp(type, "gfp_t") == 0)
+               return false;
 
        return true;
 }
index a38c174..6772edd 100644 (file)
@@ -667,7 +667,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* writable? */
index 36f2441..f594183 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/lockdep.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
 #include <linux/pkt_sched.h>
@@ -379,14 +380,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        unsigned char *ogm_buff;
        u32 random_seqno;
 
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        /* randomize initial seqno to avoid collision */
        get_random_bytes(&random_seqno, sizeof(random_seqno));
        atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
 
        hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
        ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
-       if (!ogm_buff)
+       if (!ogm_buff) {
+               mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
                return -ENOMEM;
+       }
 
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
@@ -398,35 +403,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
 
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        return 0;
 }
 
 static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
 {
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        kfree(hard_iface->bat_iv.ogm_buff);
        hard_iface->bat_iv.ogm_buff = NULL;
+
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
-       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
+       void *ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
+       ogm_buff = hard_iface->bat_iv.ogm_buff;
+       if (!ogm_buff)
+               goto unlock;
+
+       batadv_ogm_packet = ogm_buff;
        ether_addr_copy(batadv_ogm_packet->orig,
                        hard_iface->net_dev->dev_addr);
        ether_addr_copy(batadv_ogm_packet->prev_sender,
                        hard_iface->net_dev->dev_addr);
+
+unlock:
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 static void
 batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
-       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
+       void *ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
+       ogm_buff = hard_iface->bat_iv.ogm_buff;
+       if (!ogm_buff)
+               goto unlock;
+
+       batadv_ogm_packet = ogm_buff;
        batadv_ogm_packet->ttl = BATADV_TTL;
+
+unlock:
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -924,7 +953,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
        }
 }
 
-static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
+/**
+ * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
+ * @hard_iface: interface whose ogm buffer should be transmitted
+ */
+static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
        unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
@@ -935,9 +968,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        u16 tvlv_len = 0;
        unsigned long send_time;
 
-       if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
-           hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
-               return;
+       lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
 
        /* the interface gets activated here to avoid race conditions between
         * the moment of activating the interface in
@@ -1005,6 +1036,17 @@ out:
                batadv_hardif_put(primary_if);
 }
 
+static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
+{
+       if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
+           hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
+               return;
+
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+       batadv_iv_ogm_schedule_buff(hard_iface);
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+}
+
 /**
  * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
  *  originator
index 36f0962..c4e0435 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
 #include <linux/rculist.h>
@@ -933,6 +934,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
        INIT_LIST_HEAD(&hard_iface->list);
        INIT_HLIST_HEAD(&hard_iface->neigh_list);
 
+       mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
        spin_lock_init(&hard_iface->neigh_list_lock);
        kref_init(&hard_iface->refcount);
 
index fdba8a1..87e54f8 100644 (file)
@@ -91,6 +91,9 @@ struct batadv_hard_iface_bat_iv {
 
        /** @ogm_seqno: OGM sequence number - used to identify each OGM */
        atomic_t ogm_seqno;
+
+       /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
+       struct mutex ogm_buff_mutex;
 };
 
 /**
index 8d12198..ee60c30 100644 (file)
@@ -460,7 +460,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_state == BT_LISTEN)
                return bt_accept_poll(sk);
 
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -470,7 +470,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_shutdown == SHUTDOWN_MASK)
                mask |= EPOLLHUP;
 
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        if (sk->sk_state == BT_CLOSED)
index 416717c..4b31f0a 100644 (file)
@@ -953,7 +953,7 @@ static __poll_t caif_poll(struct file *file,
                mask |= EPOLLRDHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue) ||
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
                (sk->sk_shutdown & RCV_SHUTDOWN))
                mask |= EPOLLIN | EPOLLRDNORM;
 
index a487df5..865a8cb 100644 (file)
@@ -95,7 +95,7 @@ int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
        if (error)
                goto out_err;
 
-       if (sk->sk_receive_queue.prev != skb)
+       if (READ_ONCE(sk->sk_receive_queue.prev) != skb)
                goto out;
 
        /* Socket shut down? */
@@ -279,7 +279,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
                        break;
 
                sk_busy_loop(sk, flags & MSG_DONTWAIT);
-       } while (sk->sk_receive_queue.prev != *last);
+       } while (READ_ONCE(sk->sk_receive_queue.prev) != *last);
 
        error = -EAGAIN;
 
@@ -842,7 +842,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
        mask = 0;
 
        /* exceptional events? */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -852,7 +852,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
index ddd8aab..4a2ee1c 100644 (file)
@@ -9211,7 +9211,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
        rcu_barrier();
 
-       new_nsid = peernet2id_alloc(dev_net(dev), net);
+       new_nsid = peernet2id_alloc(dev_net(dev), net, GFP_KERNEL);
        /* If there is an ifindex conflict assign a new one */
        if (__dev_get_by_index(net, dev->ifindex))
                new_ifindex = dev_new_index(net);
index 996813f..09d828a 100644 (file)
@@ -1482,11 +1482,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
 
 static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
 {
-       struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+       struct ethtool_wolinfo wol;
 
        if (!dev->ethtool_ops->get_wol)
                return -EOPNOTSUPP;
 
+       memset(&wol, 0, sizeof(struct ethtool_wolinfo));
+       wol.cmd = ETHTOOL_GWOL;
        dev->ethtool_ops->get_wol(dev, &wol);
 
        if (copy_to_user(useraddr, &wol, sizeof(wol)))
index 415b95f..4362ffe 100644 (file)
@@ -1077,30 +1077,21 @@ out_bad:
 }
 EXPORT_SYMBOL(__skb_flow_dissect);
 
-static u32 hashrnd __read_mostly;
+static siphash_key_t hashrnd __read_mostly;
 static __always_inline void __flow_hash_secret_init(void)
 {
        net_get_random_once(&hashrnd, sizeof(hashrnd));
 }
 
-static __always_inline u32 __flow_hash_words(const u32 *words, u32 length,
-                                            u32 keyval)
+static const void *flow_keys_hash_start(const struct flow_keys *flow)
 {
-       return jhash2(words, length, keyval);
-}
-
-static inline const u32 *flow_keys_hash_start(const struct flow_keys *flow)
-{
-       const void *p = flow;
-
-       BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % sizeof(u32));
-       return (const u32 *)(p + FLOW_KEYS_HASH_OFFSET);
+       BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % SIPHASH_ALIGNMENT);
+       return &flow->FLOW_KEYS_HASH_START_FIELD;
 }
 
 static inline size_t flow_keys_hash_length(const struct flow_keys *flow)
 {
        size_t diff = FLOW_KEYS_HASH_OFFSET + sizeof(flow->addrs);
-       BUILD_BUG_ON((sizeof(*flow) - FLOW_KEYS_HASH_OFFSET) % sizeof(u32));
        BUILD_BUG_ON(offsetof(typeof(*flow), addrs) !=
                     sizeof(*flow) - sizeof(flow->addrs));
 
@@ -1115,7 +1106,7 @@ static inline size_t flow_keys_hash_length(const struct flow_keys *flow)
                diff -= sizeof(flow->addrs.tipckey);
                break;
        }
-       return (sizeof(*flow) - diff) / sizeof(u32);
+       return sizeof(*flow) - diff;
 }
 
 __be32 flow_get_u32_src(const struct flow_keys *flow)
@@ -1181,14 +1172,15 @@ static inline void __flow_hash_consistentify(struct flow_keys *keys)
        }
 }
 
-static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval)
+static inline u32 __flow_hash_from_keys(struct flow_keys *keys,
+                                       const siphash_key_t *keyval)
 {
        u32 hash;
 
        __flow_hash_consistentify(keys);
 
-       hash = __flow_hash_words(flow_keys_hash_start(keys),
-                                flow_keys_hash_length(keys), keyval);
+       hash = siphash(flow_keys_hash_start(keys),
+                      flow_keys_hash_length(keys), keyval);
        if (!hash)
                hash = 1;
 
@@ -1198,12 +1190,13 @@ static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval)
 u32 flow_hash_from_keys(struct flow_keys *keys)
 {
        __flow_hash_secret_init();
-       return __flow_hash_from_keys(keys, hashrnd);
+       return __flow_hash_from_keys(keys, &hashrnd);
 }
 EXPORT_SYMBOL(flow_hash_from_keys);
 
 static inline u32 ___skb_get_hash(const struct sk_buff *skb,
-                                 struct flow_keys *keys, u32 keyval)
+                                 struct flow_keys *keys,
+                                 const siphash_key_t *keyval)
 {
        skb_flow_dissect_flow_keys(skb, keys,
                                   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
@@ -1251,7 +1244,7 @@ u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
                           NULL, 0, 0, 0,
                           FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
 
-       return __flow_hash_from_keys(&keys, hashrnd);
+       return __flow_hash_from_keys(&keys, &hashrnd);
 }
 EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric);
 
@@ -1271,13 +1264,14 @@ void __skb_get_hash(struct sk_buff *skb)
 
        __flow_hash_secret_init();
 
-       hash = ___skb_get_hash(skb, &keys, hashrnd);
+       hash = ___skb_get_hash(skb, &keys, &hashrnd);
 
        __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys));
 }
 EXPORT_SYMBOL(__skb_get_hash);
 
-__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb)
+__u32 skb_get_hash_perturb(const struct sk_buff *skb,
+                          const siphash_key_t *perturb)
 {
        struct flow_keys keys;
 
index 7320f08..6dab186 100644 (file)
@@ -226,11 +226,11 @@ static int __peernet2id(struct net *net, struct net *peer)
        return __peernet2id_alloc(net, peer, &no);
 }
 
-static void rtnl_net_notifyid(struct net *net, int cmd, int id);
+static void rtnl_net_notifyid(struct net *net, int cmd, int id, gfp_t gfp);
 /* This function returns the id of a peer netns. If no id is assigned, one will
  * be allocated and returned.
  */
-int peernet2id_alloc(struct net *net, struct net *peer)
+int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp)
 {
        bool alloc = false, alive = false;
        int id;
@@ -249,7 +249,7 @@ int peernet2id_alloc(struct net *net, struct net *peer)
        id = __peernet2id_alloc(net, peer, &alloc);
        spin_unlock_bh(&net->nsid_lock);
        if (alloc && id >= 0)
-               rtnl_net_notifyid(net, RTM_NEWNSID, id);
+               rtnl_net_notifyid(net, RTM_NEWNSID, id, gfp);
        if (alive)
                put_net(peer);
        return id;
@@ -495,7 +495,8 @@ static void unhash_nsid(struct net *net, struct net *last)
                        idr_remove(&tmp->netns_ids, id);
                spin_unlock_bh(&tmp->nsid_lock);
                if (id >= 0)
-                       rtnl_net_notifyid(tmp, RTM_DELNSID, id);
+                       rtnl_net_notifyid(tmp, RTM_DELNSID, id,
+                                         GFP_KERNEL);
                if (tmp == last)
                        break;
        }
@@ -720,7 +721,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
        err = alloc_netid(net, peer, nsid);
        spin_unlock_bh(&net->nsid_lock);
        if (err >= 0) {
-               rtnl_net_notifyid(net, RTM_NEWNSID, err);
+               rtnl_net_notifyid(net, RTM_NEWNSID, err, GFP_KERNEL);
                err = 0;
        } else if (err == -ENOSPC && nsid >= 0) {
                err = -EEXIST;
@@ -862,12 +863,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
-static void rtnl_net_notifyid(struct net *net, int cmd, int id)
+static void rtnl_net_notifyid(struct net *net, int cmd, int id, gfp_t gfp)
 {
        struct sk_buff *msg;
        int err = -ENOMEM;
 
-       msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
+       msg = nlmsg_new(rtnl_net_get_size(), gfp);
        if (!msg)
                goto out;
 
@@ -875,7 +876,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
        if (err < 0)
                goto err_out;
 
-       rtnl_notify(msg, net, 0, RTNLGRP_NSID, NULL, 0);
+       rtnl_notify(msg, net, 0, RTNLGRP_NSID, NULL, gfp);
        return;
 
 err_out:
index 3932eed..95768a9 100644 (file)
@@ -1519,7 +1519,7 @@ static noinline_for_stack int nla_put_ifalias(struct sk_buff *skb,
 
 static int rtnl_fill_link_netnsid(struct sk_buff *skb,
                                  const struct net_device *dev,
-                                 struct net *src_net)
+                                 struct net *src_net, gfp_t gfp)
 {
        bool put_iflink = false;
 
@@ -1527,7 +1527,7 @@ static int rtnl_fill_link_netnsid(struct sk_buff *skb,
                struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);
 
                if (!net_eq(dev_net(dev), link_net)) {
-                       int id = peernet2id_alloc(src_net, link_net);
+                       int id = peernet2id_alloc(src_net, link_net, gfp);
 
                        if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
                                return -EMSGSIZE;
@@ -1585,7 +1585,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask,
                            u32 event, int *new_nsid, int new_ifindex,
-                           int tgt_netnsid)
+                           int tgt_netnsid, gfp_t gfp)
 {
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
@@ -1677,7 +1677,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
        }
 
-       if (rtnl_fill_link_netnsid(skb, dev, src_net))
+       if (rtnl_fill_link_netnsid(skb, dev, src_net, gfp))
                goto nla_put_failure;
 
        if (new_nsid &&
@@ -1933,7 +1933,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
                                               cb->nlh->nlmsg_seq, 0,
                                               flags,
                                               ext_filter_mask, 0, NULL, 0,
-                                              netnsid);
+                                              netnsid, GFP_KERNEL);
 
                        if (err < 0) {
                                if (likely(skb->len))
@@ -3215,7 +3215,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
        err = rtnl_fill_ifinfo(nskb, dev, net,
                               RTM_NEWLINK, NETLINK_CB(skb).portid,
                               nlh->nlmsg_seq, 0, 0, ext_filter_mask,
-                              0, NULL, 0, netnsid);
+                              0, NULL, 0, netnsid, GFP_KERNEL);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in if_nlmsg_size */
                WARN_ON(err == -EMSGSIZE);
@@ -3325,7 +3325,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
 
        err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
                               type, 0, 0, change, 0, 0, event,
-                              new_nsid, new_ifindex, -1);
+                              new_nsid, new_ifindex, -1, flags);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in if_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
index f881eea..6c11078 100644 (file)
@@ -1005,7 +1005,7 @@ set_rcvbuf:
                break;
 
        case SO_INCOMING_CPU:
-               sk->sk_incoming_cpu = val;
+               WRITE_ONCE(sk->sk_incoming_cpu, val);
                break;
 
        case SO_CNX_ADVICE:
@@ -1341,7 +1341,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                break;
 
        case SO_INCOMING_CPU:
-               v.val = sk->sk_incoming_cpu;
+               v.val = READ_ONCE(sk->sk_incoming_cpu);
                break;
 
        case SO_MEMINFO:
@@ -3483,7 +3483,7 @@ bool sk_busy_loop_end(void *p, unsigned long start_time)
 {
        struct sock *sk = p;
 
-       return !skb_queue_empty(&sk->sk_receive_queue) ||
+       return !skb_queue_empty_lockless(&sk->sk_receive_queue) ||
               sk_busy_loop_timeout(sk, start_time);
 }
 EXPORT_SYMBOL(sk_busy_loop_end);
index 8e08cea..176bdda 100644 (file)
@@ -121,7 +121,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                    inet->inet_daddr,
                                                    inet->inet_sport,
                                                    inet->inet_dport);
-       inet->inet_id = dp->dccps_iss ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        err = dccp_connect(sk);
        rt = NULL;
@@ -417,7 +417,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
        RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt));
        newinet->mc_index  = inet_iif(skb);
        newinet->mc_ttl    = ip_hdr(skb)->ttl;
-       newinet->inet_id   = jiffies;
+       newinet->inet_id   = prandom_u32();
 
        if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
                goto put_and_exit;
index 7d6ff98..0e6f32d 100644 (file)
@@ -1213,7 +1213,7 @@ static __poll_t dn_poll(struct file *file, struct socket *sock, poll_table  *wai
        struct dn_scp *scp = DN_SK(sk);
        __poll_t mask = datagram_poll(file, sock, wait);
 
-       if (!skb_queue_empty(&scp->other_receive_queue))
+       if (!skb_queue_empty_lockless(&scp->other_receive_queue))
                mask |= EPOLLRDBAND;
 
        return mask;
index a191702..46ae4de 100644 (file)
@@ -49,7 +49,7 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index)
        dst->index = index;
 
        INIT_LIST_HEAD(&dst->list);
-       list_add_tail(&dsa_tree_list, &dst->list);
+       list_add_tail(&dst->list, &dsa_tree_list);
 
        kref_init(&dst->refcount);
 
index 80107a6..dc8517c 100644 (file)
@@ -77,7 +77,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
        reuseport_has_conns(sk, true);
        sk->sk_state = TCP_ESTABLISHED;
        sk_set_txhash(sk);
-       inet->inet_id = jiffies;
+       inet->inet_id = prandom_u32();
 
        sk_dst_set(sk, &rt->dst);
        err = 0;
index dae743b..7f4ec36 100644 (file)
@@ -946,7 +946,7 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric)
        if (!(dev->flags & IFF_UP) ||
            ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) ||
            ipv4_is_zeronet(prefix) ||
-           prefix == ifa->ifa_local || ifa->ifa_prefixlen == 32)
+           (prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32))
                return;
 
        /* add the new */
index f5c9ef2..7be966a 100644 (file)
@@ -248,7 +248,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                        if (sk->sk_bound_dev_if)
                                score += 4;
                }
-               if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
        return score;
index 0b87558..758a0f8 100644 (file)
@@ -589,9 +589,9 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
        key = &tun_info->key;
        if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
                goto err_free_rt;
+       if (tun_info->options_len < sizeof(*md))
+               goto err_free_rt;
        md = ip_tunnel_info_opts(tun_info);
-       if (!md)
-               goto err_free_rt;
 
        /* ERSPAN has fixed 8 byte GRE header */
        version = md->version;
index 611ba17..647ba44 100644 (file)
@@ -595,7 +595,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        }
        /* This barrier is coupled with smp_wmb() in tcp_reset() */
        smp_rmb();
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR;
 
        return mask;
@@ -1948,7 +1948,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
 
-       if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
+       if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue) &&
            (sk->sk_state == TCP_ESTABLISHED))
                sk_busy_loop(sk, nonblock);
 
index b76cf96..bfec488 100644 (file)
@@ -305,7 +305,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                 inet->inet_daddr);
        }
 
-       inet->inet_id = tp->write_seq ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        if (tcp_fastopen_defer_connect(sk, &err))
                return err;
@@ -1436,7 +1436,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
        if (inet_opt)
                inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
-       newinet->inet_id = newtp->write_seq ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        if (!dst) {
                dst = inet_csk_route_child_sock(sk, newsk, req);
index aa59acc..8877bd1 100644 (file)
@@ -408,7 +408,7 @@ static int compute_score(struct sock *sk, struct net *net,
                        score += 4;
        }
 
-       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+       if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;
        return score;
 }
@@ -1270,6 +1270,20 @@ static void udp_set_dev_scratch(struct sk_buff *skb)
                scratch->_tsize_state |= UDP_SKB_IS_STATELESS;
 }
 
+static void udp_skb_csum_unnecessary_set(struct sk_buff *skb)
+{
+       /* We come here after udp_lib_checksum_complete() returned 0.
+        * This means that __skb_checksum_complete() might have
+        * set skb->csum_valid to 1.
+        * On 64bit platforms, we can set csum_unnecessary
+        * to true, but only if the skb is not shared.
+        */
+#if BITS_PER_LONG == 64
+       if (!skb_shared(skb))
+               udp_skb_scratch(skb)->csum_unnecessary = true;
+#endif
+}
+
 static int udp_skb_truesize(struct sk_buff *skb)
 {
        return udp_skb_scratch(skb)->_tsize_state & ~UDP_SKB_IS_STATELESS;
@@ -1504,10 +1518,7 @@ static struct sk_buff *__first_packet_length(struct sock *sk,
                        *total += skb->truesize;
                        kfree_skb(skb);
                } else {
-                       /* the csum related bits could be changed, refresh
-                        * the scratch area
-                        */
-                       udp_set_dev_scratch(skb);
+                       udp_skb_csum_unnecessary_set(skb);
                        break;
                }
        }
@@ -1531,7 +1542,7 @@ static int first_packet_length(struct sock *sk)
 
        spin_lock_bh(&rcvq->lock);
        skb = __first_packet_length(sk, rcvq, &total);
-       if (!skb && !skb_queue_empty(sk_queue)) {
+       if (!skb && !skb_queue_empty_lockless(sk_queue)) {
                spin_lock(&sk_queue->lock);
                skb_queue_splice_tail_init(sk_queue, rcvq);
                spin_unlock(&sk_queue->lock);
@@ -1606,7 +1617,7 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags,
                                return skb;
                        }
 
-                       if (skb_queue_empty(sk_queue)) {
+                       if (skb_queue_empty_lockless(sk_queue)) {
                                spin_unlock_bh(&queue->lock);
                                goto busy_check;
                        }
@@ -1633,7 +1644,7 @@ busy_check:
                                break;
 
                        sk_busy_loop(sk, flags & MSG_DONTWAIT);
-               } while (!skb_queue_empty(sk_queue));
+               } while (!skb_queue_empty_lockless(sk_queue));
 
                /* sk_queue is empty, reader_queue may contain peeked packets */
        } while (timeo &&
@@ -2640,7 +2651,7 @@ __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait)
        __poll_t mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;
 
-       if (!skb_queue_empty(&udp_sk(sk)->reader_queue))
+       if (!skb_queue_empty_lockless(&udp_sk(sk)->reader_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Check for false positives due to checksum errors */
index 3d7c746..91d6ea9 100644 (file)
@@ -118,7 +118,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                        if (sk->sk_bound_dev_if)
                                score++;
                }
-               if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
        return score;
index a23516e..dee4113 100644 (file)
@@ -1000,9 +1000,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                dsfield = key->tos;
                if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
                        goto tx_err;
-               md = ip_tunnel_info_opts(tun_info);
-               if (!md)
+               if (tun_info->options_len < sizeof(*md))
                        goto tx_err;
+               md = ip_tunnel_info_opts(tun_info);
 
                tun_id = tunnel_id_to_key32(key->tun_id);
                if (md->version == 1) {
index d1c59cb..1979922 100644 (file)
@@ -154,7 +154,7 @@ static int compute_score(struct sock *sk, struct net *net,
                        score++;
        }
 
-       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+       if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;
 
        return score;
index 4d78375..647c055 100644 (file)
@@ -372,6 +372,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
        llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
        if (likely(!rc)) {
+               skb_get(skb);
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -389,7 +390,8 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
        llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
        if (likely(!rc)) {
-               rc = llc_conn_send_pdu(sk, skb);
+               skb_get(skb);
+               llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
        return rc;
@@ -406,6 +408,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
        llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
        if (likely(!rc)) {
+               skb_get(skb);
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -916,7 +919,8 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
        llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
        if (likely(!rc)) {
-               rc = llc_conn_send_pdu(sk, skb);
+               skb_get(skb);
+               llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
        return rc;
index 4ff89cb..ed2aca1 100644 (file)
@@ -30,7 +30,7 @@
 #endif
 
 static int llc_find_offset(int state, int ev_type);
-static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *skb);
+static void llc_conn_send_pdus(struct sock *sk);
 static int llc_conn_service(struct sock *sk, struct sk_buff *skb);
 static int llc_exec_conn_trans_actions(struct sock *sk,
                                       struct llc_conn_state_trans *trans,
@@ -193,11 +193,11 @@ out_skb_put:
        return rc;
 }
 
-int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
+void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
 {
        /* queue PDU to send to MAC layer */
        skb_queue_tail(&sk->sk_write_queue, skb);
-       return llc_conn_send_pdus(sk, skb);
+       llc_conn_send_pdus(sk);
 }
 
 /**
@@ -255,7 +255,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
        if (howmany_resend > 0)
                llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO;
        /* any PDUs to re-send are queued up; start sending to MAC */
-       llc_conn_send_pdus(sk, NULL);
+       llc_conn_send_pdus(sk);
 out:;
 }
 
@@ -296,7 +296,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
        if (howmany_resend > 0)
                llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO;
        /* any PDUs to re-send are queued up; start sending to MAC */
-       llc_conn_send_pdus(sk, NULL);
+       llc_conn_send_pdus(sk);
 out:;
 }
 
@@ -340,16 +340,12 @@ out:
 /**
  *     llc_conn_send_pdus - Sends queued PDUs
  *     @sk: active connection
- *     @hold_skb: the skb held by caller, or NULL if does not care
  *
- *     Sends queued pdus to MAC layer for transmission. When @hold_skb is
- *     NULL, always return 0. Otherwise, return 0 if @hold_skb is sent
- *     successfully, or 1 for failure.
+ *     Sends queued pdus to MAC layer for transmission.
  */
-static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb)
+static void llc_conn_send_pdus(struct sock *sk)
 {
        struct sk_buff *skb;
-       int ret = 0;
 
        while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) {
                struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
@@ -361,20 +357,10 @@ static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb)
                        skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb);
                        if (!skb2)
                                break;
-                       dev_queue_xmit(skb2);
-               } else {
-                       bool is_target = skb == hold_skb;
-                       int rc;
-
-                       if (is_target)
-                               skb_get(skb);
-                       rc = dev_queue_xmit(skb);
-                       if (is_target)
-                               ret = rc;
+                       skb = skb2;
                }
+               dev_queue_xmit(skb);
        }
-
-       return ret;
 }
 
 /**
index a94bd56..7ae4cc6 100644 (file)
@@ -58,8 +58,10 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_ui_cmd(skb);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (likely(!rc))
+       if (likely(!rc)) {
+               skb_get(skb);
                rc = dev_queue_xmit(skb);
+       }
        return rc;
 }
 
@@ -81,8 +83,10 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (likely(!rc))
+       if (likely(!rc)) {
+               skb_get(skb);
                rc = dev_queue_xmit(skb);
+       }
        return rc;
 }
 
@@ -135,8 +139,10 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_test_cmd(skb);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (likely(!rc))
+       if (likely(!rc)) {
+               skb_get(skb);
                rc = dev_queue_xmit(skb);
+       }
        return rc;
 }
 
index a7f7b8f..be41906 100644 (file)
@@ -197,29 +197,22 @@ out:
  *     After executing actions of the event, upper layer will be indicated
  *     if needed(on receiving an UI frame). sk can be null for the
  *     datalink_proto case.
+ *
+ *     This function always consumes a reference to the skb.
  */
 static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
 {
        struct llc_sap_state_ev *ev = llc_sap_ev(skb);
 
-       /*
-        * We have to hold the skb, because llc_sap_next_state
-        * will kfree it in the sending path and we need to
-        * look at the skb->cb, where we encode llc_sap_state_ev.
-        */
-       skb_get(skb);
        ev->ind_cfm_flag = 0;
        llc_sap_next_state(sap, skb);
-       if (ev->ind_cfm_flag == LLC_IND) {
-               if (skb->sk->sk_state == TCP_LISTEN)
-                       kfree_skb(skb);
-               else {
-                       llc_save_primitive(skb->sk, skb, ev->prim);
 
-                       /* queue skb to the user. */
-                       if (sock_queue_rcv_skb(skb->sk, skb))
-                               kfree_skb(skb);
-               }
+       if (ev->ind_cfm_flag == LLC_IND && skb->sk->sk_state != TCP_LISTEN) {
+               llc_save_primitive(skb->sk, skb, ev->prim);
+
+               /* queue skb to the user. */
+               if (sock_queue_rcv_skb(skb->sk, skb) == 0)
+                       return;
        }
        kfree_skb(skb);
 }
index 4f01321..794e033 100644 (file)
@@ -235,6 +235,9 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
 
+       if (is_zero_ether_addr(e.ether))
+               return -EINVAL;
+
        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 }
 
index 16ec822..25560ea 100644 (file)
@@ -36,9 +36,6 @@ MODULE_ALIAS("ip_set_hash:ip,mac");
 /* Type specific function prefix */
 #define HTYPE          hash_ipmac
 
-/* Zero valued element is not supported */
-static const unsigned char invalid_ether[ETH_ALEN] = { 0 };
-
 /* IPv4 variant */
 
 /* Member elements */
@@ -104,7 +101,7 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
 
-       if (ether_addr_equal(e.ether, invalid_ether))
+       if (is_zero_ether_addr(e.ether))
                return -EINVAL;
 
        ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
@@ -140,7 +137,7 @@ hash_ipmac4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (ret)
                return ret;
        memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
-       if (ether_addr_equal(e.ether, invalid_ether))
+       if (is_zero_ether_addr(e.ether))
                return -IPSET_ERR_HASH_ELEM;
 
        return adtfn(set, &e, &ext, &ext, flags);
@@ -220,7 +217,7 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
 
-       if (ether_addr_equal(e.ether, invalid_ether))
+       if (is_zero_ether_addr(e.ether))
                return -EINVAL;
 
        ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
@@ -260,7 +257,7 @@ hash_ipmac6_uadt(struct ip_set *set, struct nlattr *tb[],
                return ret;
 
        memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
-       if (ether_addr_equal(e.ether, invalid_ether))
+       if (is_zero_ether_addr(e.ether))
                return -IPSET_ERR_HASH_ELEM;
 
        return adtfn(set, &e, &ext, &ext, flags);
index e0a2cb8..7d76635 100644 (file)
@@ -566,11 +566,11 @@ static __poll_t llcp_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_state == LLCP_LISTEN)
                return llcp_accept_poll(sk);
 
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        if (sk->sk_state == LLCP_CLOSED)
index 8e396c7..c297fe8 100644 (file)
@@ -1843,7 +1843,7 @@ static struct genl_family dp_datapath_genl_family __ro_after_init = {
 /* Called with ovs_mutex or RCU read lock. */
 static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
                                   struct net *net, u32 portid, u32 seq,
-                                  u32 flags, u8 cmd)
+                                  u32 flags, u8 cmd, gfp_t gfp)
 {
        struct ovs_header *ovs_header;
        struct ovs_vport_stats vport_stats;
@@ -1864,7 +1864,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
                goto nla_put_failure;
 
        if (!net_eq(net, dev_net(vport->dev))) {
-               int id = peernet2id_alloc(net, dev_net(vport->dev));
+               int id = peernet2id_alloc(net, dev_net(vport->dev), gfp);
 
                if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
                        goto nla_put_failure;
@@ -1905,11 +1905,12 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net,
        struct sk_buff *skb;
        int retval;
 
-       skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+       skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd);
+       retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd,
+                                        GFP_KERNEL);
        BUG_ON(retval < 0);
 
        return skb;
@@ -2042,7 +2043,7 @@ restart:
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_NEW);
+                                     OVS_VPORT_CMD_NEW, GFP_KERNEL);
 
        if (netdev_get_fwd_headroom(vport->dev) > dp->max_headroom)
                update_headroom(dp);
@@ -2101,7 +2102,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_NEW);
+                                     OVS_VPORT_CMD_NEW, GFP_ATOMIC);
        BUG_ON(err < 0);
 
        ovs_unlock();
@@ -2140,7 +2141,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_DEL);
+                                     OVS_VPORT_CMD_DEL, GFP_KERNEL);
        BUG_ON(err < 0);
 
        /* the vport deletion may trigger dp headroom update */
@@ -2182,7 +2183,7 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
                goto exit_unlock_free;
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_NEW);
+                                     OVS_VPORT_CMD_NEW, GFP_ATOMIC);
        BUG_ON(err < 0);
        rcu_read_unlock();
 
@@ -2218,7 +2219,8 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                                    NETLINK_CB(cb->skb).portid,
                                                    cb->nlh->nlmsg_seq,
                                                    NLM_F_MULTI,
-                                                   OVS_VPORT_CMD_NEW) < 0)
+                                                   OVS_VPORT_CMD_NEW,
+                                                   GFP_ATOMIC) < 0)
                                goto out;
 
                        j++;
index 3018799..1ae6295 100644 (file)
@@ -351,9 +351,9 @@ static __poll_t pn_socket_poll(struct file *file, struct socket *sock,
 
        if (sk->sk_state == TCP_CLOSE)
                return EPOLLERR;
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
-       if (!skb_queue_empty(&pn->ctrlreq_queue))
+       if (!skb_queue_empty_lockless(&pn->ctrlreq_queue))
                mask |= EPOLLPRI;
        if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
                return EPOLLHUP;
index 71547e8..b91b090 100644 (file)
@@ -220,7 +220,7 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp)
        peer = kzalloc(sizeof(struct rxrpc_peer), gfp);
        if (peer) {
                atomic_set(&peer->usage, 1);
-               peer->local = local;
+               peer->local = rxrpc_get_local(local);
                INIT_HLIST_HEAD(&peer->error_targets);
                peer->service_conns = RB_ROOT;
                seqlock_init(&peer->service_conn_lock);
@@ -311,7 +311,6 @@ void rxrpc_new_incoming_peer(struct rxrpc_sock *rx, struct rxrpc_local *local,
        unsigned long hash_key;
 
        hash_key = rxrpc_peer_hash_key(local, &peer->srx);
-       peer->local = local;
        rxrpc_init_peer(rx, peer, hash_key);
 
        spin_lock(&rxnet->peer_hash_lock);
@@ -386,7 +385,7 @@ struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
        int n;
 
        n = atomic_inc_return(&peer->usage);
-       trace_rxrpc_peer(peer, rxrpc_peer_got, n, here);
+       trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n, here);
        return peer;
 }
 
@@ -400,7 +399,7 @@ struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer)
        if (peer) {
                int n = atomic_fetch_add_unless(&peer->usage, 1, 0);
                if (n > 0)
-                       trace_rxrpc_peer(peer, rxrpc_peer_got, n + 1, here);
+                       trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n + 1, here);
                else
                        peer = NULL;
        }
@@ -421,6 +420,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer)
        list_del_init(&peer->keepalive_link);
        spin_unlock_bh(&rxnet->peer_hash_lock);
 
+       rxrpc_put_local(peer->local);
        kfree_rcu(peer, rcu);
 }
 
@@ -430,11 +430,13 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer)
 void rxrpc_put_peer(struct rxrpc_peer *peer)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id;
        int n;
 
        if (peer) {
+               debug_id = peer->debug_id;
                n = atomic_dec_return(&peer->usage);
-               trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
+               trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here);
                if (n == 0)
                        __rxrpc_put_peer(peer);
        }
@@ -447,13 +449,15 @@ void rxrpc_put_peer(struct rxrpc_peer *peer)
 void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = peer->debug_id;
        int n;
 
        n = atomic_dec_return(&peer->usage);
-       trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
+       trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here);
        if (n == 0) {
                hash_del_rcu(&peer->hash_link);
                list_del_init(&peer->keepalive_link);
+               rxrpc_put_local(peer->local);
                kfree_rcu(peer, rcu);
        }
 }
index 5d6ab4f..3e54ead 100644 (file)
@@ -661,6 +661,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                case RXRPC_CALL_SERVER_PREALLOC:
                case RXRPC_CALL_SERVER_SECURING:
                case RXRPC_CALL_SERVER_ACCEPTING:
+                       rxrpc_put_call(call, rxrpc_call_put);
                        ret = -EBUSY;
                        goto error_release_sock;
                default:
index a80fe8a..c53b720 100644 (file)
@@ -4,11 +4,11 @@
  * Copyright (C) 2013 Nandita Dukkipati <nanditad@google.com>
  */
 
-#include <linux/jhash.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
+#include <linux/siphash.h>
 #include <net/pkt_sched.h>
 #include <net/sock.h>
 
@@ -125,7 +125,7 @@ struct wdrr_bucket {
 
 struct hhf_sched_data {
        struct wdrr_bucket buckets[WDRR_BUCKET_CNT];
-       u32                perturbation;   /* hash perturbation */
+       siphash_key_t      perturbation;   /* hash perturbation */
        u32                quantum;        /* psched_mtu(qdisc_dev(sch)); */
        u32                drop_overlimit; /* number of times max qdisc packet
                                            * limit was hit
@@ -263,7 +263,7 @@ static enum wdrr_bucket_idx hhf_classify(struct sk_buff *skb, struct Qdisc *sch)
        }
 
        /* Get hashed flow-id of the skb. */
-       hash = skb_get_hash_perturb(skb, q->perturbation);
+       hash = skb_get_hash_perturb(skb, &q->perturbation);
 
        /* Check if this packet belongs to an already established HH flow. */
        flow_pos = hash & HHF_BIT_MASK;
@@ -580,7 +580,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
 
        sch->limit = 1000;
        q->quantum = psched_mtu(qdisc_dev(sch));
-       q->perturbation = prandom_u32();
+       get_random_bytes(&q->perturbation, sizeof(q->perturbation));
        INIT_LIST_HEAD(&q->new_buckets);
        INIT_LIST_HEAD(&q->old_buckets);
 
index 86350fe..15f8f24 100644 (file)
@@ -474,7 +474,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
         * skb will be queued.
         */
        if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-               struct Qdisc *rootq = qdisc_root(sch);
+               struct Qdisc *rootq = qdisc_root_bh(sch);
                u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
 
                q->duplicate = 0;
index 7cbdad8..1aa95e7 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/random.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
@@ -49,7 +49,7 @@ struct sfb_bucket {
  * (Section 4.4 of SFB reference : moving hash functions)
  */
 struct sfb_bins {
-       u32               perturbation; /* jhash perturbation */
+       siphash_key_t     perturbation; /* siphash key */
        struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS];
 };
 
@@ -221,7 +221,8 @@ static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_da
 
 static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q)
 {
-       q->bins[slot].perturbation = prandom_u32();
+       get_random_bytes(&q->bins[slot].perturbation,
+                        sizeof(q->bins[slot].perturbation));
 }
 
 static void sfb_swap_slot(struct sfb_sched_data *q)
@@ -318,9 +319,9 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                /* If using external classifiers, get result and record it. */
                if (!sfb_classify(skb, fl, &ret, &salt))
                        goto other_drop;
-               sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+               sfbhash = siphash_1u32(salt, &q->bins[slot].perturbation);
        } else {
-               sfbhash = skb_get_hash_perturb(skb, q->bins[slot].perturbation);
+               sfbhash = skb_get_hash_perturb(skb, &q->bins[slot].perturbation);
        }
 
 
@@ -356,7 +357,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                /* Inelastic flow */
                if (q->double_buffering) {
                        sfbhash = skb_get_hash_perturb(skb,
-                           q->bins[slot].perturbation);
+                           &q->bins[slot].perturbation);
                        if (!sfbhash)
                                sfbhash = 1;
                        sfb_skb_cb(skb)->hashes[slot] = sfbhash;
index 650f214..d483d6b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <net/netlink.h>
@@ -121,7 +121,7 @@ struct sfq_sched_data {
        u8              headdrop;
        u8              maxdepth;       /* limit of packets per flow */
 
-       u32             perturbation;
+       siphash_key_t   perturbation;
        u8              cur_depth;      /* depth of longest slot */
        u8              flags;
        unsigned short  scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
@@ -161,7 +161,7 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index
 static unsigned int sfq_hash(const struct sfq_sched_data *q,
                             const struct sk_buff *skb)
 {
-       return skb_get_hash_perturb(skb, q->perturbation) & (q->divisor - 1);
+       return skb_get_hash_perturb(skb, &q->perturbation) & (q->divisor - 1);
 }
 
 static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
@@ -611,9 +611,11 @@ static void sfq_perturbation(struct timer_list *t)
        struct sfq_sched_data *q = from_timer(q, t, perturb_timer);
        struct Qdisc *sch = q->sch;
        spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
+       siphash_key_t nkey;
 
+       get_random_bytes(&nkey, sizeof(nkey));
        spin_lock(root_lock);
-       q->perturbation = prandom_u32();
+       q->perturbation = nkey;
        if (!q->filter_list && q->tail)
                sfq_rehash(sch);
        spin_unlock(root_lock);
@@ -692,7 +694,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
        del_timer(&q->perturb_timer);
        if (q->perturb_period) {
                mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
-               q->perturbation = prandom_u32();
+               get_random_bytes(&q->perturbation, sizeof(q->perturbation));
        }
        sch_tree_unlock(sch);
        kfree(p);
@@ -749,7 +751,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
        q->quantum = psched_mtu(qdisc_dev(sch));
        q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
        q->perturb_period = 0;
-       q->perturbation = prandom_u32();
+       get_random_bytes(&q->perturbation, sizeof(q->perturbation));
 
        if (opt) {
                int err = sfq_change(sch, opt);
index 227b050..c766315 100644 (file)
@@ -7939,7 +7939,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
        mask = 0;
 
        /* Is there any exceptional events?  */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
        if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -7948,7 +7948,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
                mask |= EPOLLHUP;
 
        /* Is it readable?  Reconsider this code with TCP-style support.  */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* The association is either gone or not ready.  */
@@ -8334,7 +8334,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
                if (sk_can_busy_loop(sk)) {
                        sk_busy_loop(sk, noblock);
 
-                       if (!skb_queue_empty(&sk->sk_receive_queue))
+                       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                                continue;
                }
 
@@ -8777,7 +8777,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->inet_rcv_saddr = inet->inet_rcv_saddr;
        newinet->inet_dport = htons(asoc->peer.port);
        newinet->pmtudisc = inet->pmtudisc;
-       newinet->inet_id = asoc->next_tsn ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        newinet->uc_ttl = inet->uc_ttl;
        newinet->mc_loop = 1;
index 6c91f12..5841d62 100644 (file)
@@ -731,7 +731,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
                /* fall thru' */
        case TIPC_LISTEN:
        case TIPC_CONNECTING:
-               if (!skb_queue_empty(&sk->sk_receive_queue))
+               if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                        revents |= EPOLLIN | EPOLLRDNORM;
                break;
        case TIPC_OPEN:
@@ -739,7 +739,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
                        revents |= EPOLLOUT;
                if (!tipc_sk_type_connectionless(sk))
                        break;
-               if (skb_queue_empty(&sk->sk_receive_queue))
+               if (skb_queue_empty_lockless(&sk->sk_receive_queue))
                        break;
                revents |= EPOLLIN | EPOLLRDNORM;
                break;
index f601933..231b6c0 100644 (file)
@@ -2661,7 +2661,7 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
                mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
@@ -2690,7 +2690,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
        mask = 0;
 
        /* exceptional events? */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -2700,7 +2700,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
index 2a4613b..b2724fb 100644 (file)
@@ -873,7 +873,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
                 * the queue and write as long as the socket isn't shutdown for
                 * sending.
                 */
-               if (!skb_queue_empty(&sk->sk_receive_queue) ||
+               if (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
                    (sk->sk_shutdown & RCV_SHUTDOWN)) {
                        mask |= EPOLLIN | EPOLLRDNORM;
                }
index 1d84f91..8158b37 100644 (file)
@@ -38,6 +38,7 @@ $(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \
        @(set -e; \
          allf=""; \
          for f in $^ ; do \
+             test -f $$f || continue;\
              # similar to hexdump -v -e '1/1 "0x%.2x," "\n"' \
              thisf=$$(od -An -v -tx1 < $$f | \
                           sed -e 's/ /\n/g' | \
index a28d645..2ef1f56 100644 (file)
@@ -284,7 +284,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
        [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
                                   .len = IEEE80211_MAX_MESH_ID_LEN },
-       [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
+       [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_BINARY,
+                                         .len = ETH_ALEN },
 
        [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
        [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
index 5061a2e..176c04a 100644 (file)
@@ -59,7 +59,9 @@ static int write_kprobe_events(const char *val)
 {
        int fd, ret, flags;
 
-       if ((val != NULL) && (val[0] == '\0'))
+       if (val == NULL)
+               return -1;
+       else if (val[0] == '\0')
                flags = O_WRONLY | O_TRUNC;
        else
                flags = O_WRONLY | O_APPEND;
index 71f3941..365b3c2 100755 (executable)
@@ -73,8 +73,16 @@ scm_version()
                        printf -- '-svn%s' "`git svn find-rev $head`"
                fi
 
-               # Check for uncommitted changes
-               if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then
+               # Check for uncommitted changes.
+               # First, with git-status, but --no-optional-locks is only
+               # supported in git >= 2.14, so fall back to git-diff-index if
+               # it fails. Note that git-diff-index does not refresh the
+               # index, so it may give misleading results. See
+               # git-update-index(1), git-diff-index(1), and git-status(1).
+               if {
+                       git --no-optional-locks status -uno --porcelain 2>/dev/null ||
+                       git diff-index --name-only HEAD
+               } | grep -qvE '^(.. )?scripts/package'; then
                        printf '%s' -dirty
                fi
 
index 61a0cec..ec74705 100644 (file)
@@ -240,7 +240,8 @@ static int snd_timer_check_master(struct snd_timer_instance *master)
        return 0;
 }
 
-static int snd_timer_close_locked(struct snd_timer_instance *timeri);
+static int snd_timer_close_locked(struct snd_timer_instance *timeri,
+                                 struct device **card_devp_to_put);
 
 /*
  * open a timer instance
@@ -252,21 +253,23 @@ int snd_timer_open(struct snd_timer_instance **ti,
 {
        struct snd_timer *timer;
        struct snd_timer_instance *timeri = NULL;
+       struct device *card_dev_to_put = NULL;
        int err;
 
+       mutex_lock(&register_mutex);
        if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
                /* open a slave instance */
                if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE ||
                    tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) {
                        pr_debug("ALSA: timer: invalid slave class %i\n",
                                 tid->dev_sclass);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto unlock;
                }
-               mutex_lock(&register_mutex);
                timeri = snd_timer_instance_new(owner, NULL);
                if (!timeri) {
-                       mutex_unlock(&register_mutex);
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto unlock;
                }
                timeri->slave_class = tid->dev_sclass;
                timeri->slave_id = tid->device;
@@ -274,16 +277,13 @@ int snd_timer_open(struct snd_timer_instance **ti,
                list_add_tail(&timeri->open_list, &snd_timer_slave_list);
                err = snd_timer_check_slave(timeri);
                if (err < 0) {
-                       snd_timer_close_locked(timeri);
+                       snd_timer_close_locked(timeri, &card_dev_to_put);
                        timeri = NULL;
                }
-               mutex_unlock(&register_mutex);
-               *ti = timeri;
-               return err;
+               goto unlock;
        }
 
        /* open a master instance */
-       mutex_lock(&register_mutex);
        timer = snd_timer_find(tid);
 #ifdef CONFIG_MODULES
        if (!timer) {
@@ -294,25 +294,26 @@ int snd_timer_open(struct snd_timer_instance **ti,
        }
 #endif
        if (!timer) {
-               mutex_unlock(&register_mutex);
-               return -ENODEV;
+               err = -ENODEV;
+               goto unlock;
        }
        if (!list_empty(&timer->open_list_head)) {
                timeri = list_entry(timer->open_list_head.next,
                                    struct snd_timer_instance, open_list);
                if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
-                       mutex_unlock(&register_mutex);
-                       return -EBUSY;
+                       err = -EBUSY;
+                       timeri = NULL;
+                       goto unlock;
                }
        }
        if (timer->num_instances >= timer->max_instances) {
-               mutex_unlock(&register_mutex);
-               return -EBUSY;
+               err = -EBUSY;
+               goto unlock;
        }
        timeri = snd_timer_instance_new(owner, timer);
        if (!timeri) {
-               mutex_unlock(&register_mutex);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto unlock;
        }
        /* take a card refcount for safe disconnection */
        if (timer->card)
@@ -321,16 +322,16 @@ int snd_timer_open(struct snd_timer_instance **ti,
        timeri->slave_id = slave_id;
 
        if (list_empty(&timer->open_list_head) && timer->hw.open) {
-               int err = timer->hw.open(timer);
+               err = timer->hw.open(timer);
                if (err) {
                        kfree(timeri->owner);
                        kfree(timeri);
+                       timeri = NULL;
 
                        if (timer->card)
-                               put_device(&timer->card->card_dev);
+                               card_dev_to_put = &timer->card->card_dev;
                        module_put(timer->module);
-                       mutex_unlock(&register_mutex);
-                       return err;
+                       goto unlock;
                }
        }
 
@@ -338,10 +339,15 @@ int snd_timer_open(struct snd_timer_instance **ti,
        timer->num_instances++;
        err = snd_timer_check_master(timeri);
        if (err < 0) {
-               snd_timer_close_locked(timeri);
+               snd_timer_close_locked(timeri, &card_dev_to_put);
                timeri = NULL;
        }
+
+ unlock:
        mutex_unlock(&register_mutex);
+       /* put_device() is called after unlock for avoiding deadlock */
+       if (card_dev_to_put)
+               put_device(card_dev_to_put);
        *ti = timeri;
        return err;
 }
@@ -351,7 +357,8 @@ EXPORT_SYMBOL(snd_timer_open);
  * close a timer instance
  * call this with register_mutex down.
  */
-static int snd_timer_close_locked(struct snd_timer_instance *timeri)
+static int snd_timer_close_locked(struct snd_timer_instance *timeri,
+                                 struct device **card_devp_to_put)
 {
        struct snd_timer *timer = NULL;
        struct snd_timer_instance *slave, *tmp;
@@ -403,7 +410,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
                        timer->hw.close(timer);
                /* release a card refcount for safe disconnection */
                if (timer->card)
-                       put_device(&timer->card->card_dev);
+                       *card_devp_to_put = &timer->card->card_dev;
                module_put(timer->module);
        }
 
@@ -415,14 +422,18 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
  */
 int snd_timer_close(struct snd_timer_instance *timeri)
 {
+       struct device *card_dev_to_put = NULL;
        int err;
 
        if (snd_BUG_ON(!timeri))
                return -ENXIO;
 
        mutex_lock(&register_mutex);
-       err = snd_timer_close_locked(timeri);
+       err = snd_timer_close_locked(timeri, &card_dev_to_put);
        mutex_unlock(&register_mutex);
+       /* put_device() is called after unlock for avoiding deadlock */
+       if (card_dev_to_put)
+               put_device(card_dev_to_put);
        return err;
 }
 EXPORT_SYMBOL(snd_timer_close);
index 4d3034a..be2c056 100644 (file)
@@ -253,8 +253,7 @@ end:
        return err;
 }
 
-static unsigned int
-map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
+static int map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
 {
        unsigned int sec, sections, ch, channels;
        unsigned int pcm, midi, location;
index e858b6f..74244d8 100644 (file)
@@ -443,8 +443,6 @@ static void azx_int_disable(struct hdac_bus *bus)
        list_for_each_entry(azx_dev, &bus->stream_list, list)
                snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
 
-       synchronize_irq(bus->irq);
-
        /* disable SIE for all streams */
        snd_hdac_chip_writeb(bus, INTCTL, 0);
 
index bfc4508..0b24c5c 100644 (file)
@@ -1455,9 +1455,9 @@ static int azx_free(struct azx *chip)
        }
 
        if (bus->chip_init) {
-               azx_stop_chip(chip);
                azx_clear_irq_pending(chip);
                azx_stop_all_streams(chip);
+               azx_stop_chip(chip);
        }
 
        if (bus->irq >= 0)
index dd46354..7e86aeb 100644 (file)
@@ -421,6 +421,9 @@ 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 0x10ec0623:
+               alc_update_coef_idx(codec, 0x19, 1<<13, 0);
+               break;
        case 0x10ec0668:
                alc_update_coef_idx(codec, 0x7, 3<<13, 0);
                break;
@@ -2908,6 +2911,7 @@ enum {
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
        ALC269_TYPE_ALC300,
+       ALC269_TYPE_ALC623,
        ALC269_TYPE_ALC700,
 };
 
@@ -2943,6 +2947,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
        case ALC269_TYPE_ALC300:
+       case ALC269_TYPE_ALC623:
        case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
@@ -3458,7 +3463,9 @@ static void alc294_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->done_hp_init) {
+       /* required only at boot or S4 resume time */
+       if (!spec->done_hp_init ||
+           codec->core.dev.power.power_state.event == PM_EVENT_RESTORE) {
                alc294_hp_init(codec);
                spec->done_hp_init = true;
        }
@@ -5251,6 +5258,17 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
        }
 }
 
+static void alc256_fixup_dell_xps_13_headphone_noise2(struct hda_codec *codec,
+                                                     const struct hda_fixup *fix,
+                                                     int action)
+{
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+
+       snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 0, HDA_AMP_VOLMASK, 1);
+       snd_hda_override_wcaps(codec, 0x1a, get_wcaps(codec, 0x1a) & ~AC_WCAP_IN_AMP);
+}
+
 static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
                                             const struct hda_fixup *fix,
                                             int action)
@@ -5633,6 +5651,7 @@ enum {
        ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
        ALC275_FIXUP_DELL_XPS,
        ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
+       ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2,
        ALC293_FIXUP_LENOVO_SPK_NOISE,
        ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
        ALC255_FIXUP_DELL_SPK_NOISE,
@@ -6350,6 +6369,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
+       [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc256_fixup_dell_xps_13_headphone_noise2,
+               .chained = true,
+               .chain_id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE
+       },
        [ALC293_FIXUP_LENOVO_SPK_NOISE] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_disable_aamix,
@@ -6792,17 +6817,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
-       SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+       SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
        SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
        SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
        SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
-       SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+       SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
        SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
        SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
        SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
        SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
        SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+       SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2),
        SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
        SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
        SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
@@ -6978,6 +7003,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@ -7761,6 +7788,9 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC300;
                spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
                break;
+       case 0x10ec0623:
+               spec->codec_variant = ALC269_TYPE_ALC623;
+               break;
        case 0x10ec0700:
        case 0x10ec0701:
        case 0x10ec0703:
@@ -8879,6 +8909,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0623, "ALC623", patch_alc269),
        HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
        HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
        HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
index e3de1ff..439e402 100644 (file)
@@ -24,8 +24,7 @@
 
 #define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
                         SNDRV_PCM_FMTBIT_S24_3LE | \
-                        SNDRV_PCM_FMTBIT_S24_LE | \
-                        SNDRV_PCM_FMTBIT_S32_LE)
+                        SNDRV_PCM_FMTBIT_S24_LE)
 
 #define PCM3168A_FMT_I2S               0x0
 #define PCM3168A_FMT_LEFT_J            0x1
index 6f5dac0..21e7c43 100644 (file)
@@ -982,6 +982,16 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
 {
        struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
 
+       rt5682->hs_jack = hs_jack;
+
+       if (!hs_jack) {
+               regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+                                  RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
+               regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+                                  RT5682_POW_JDH | RT5682_POW_JDL, 0);
+               return 0;
+       }
+
        switch (rt5682->pdata.jd_src) {
        case RT5682_JD1:
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2,
@@ -1019,8 +1029,6 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
                break;
        }
 
-       rt5682->hs_jack = hs_jack;
-
        return 0;
 }
 
index 14f1b0c..01acb8d 100644 (file)
@@ -537,13 +537,10 @@ static SOC_ENUM_SINGLE_DECL(dac_osr,
 static SOC_ENUM_SINGLE_DECL(adc_osr,
                            WM8994_OVERSAMPLING, 1, osr_text);
 
-static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+static const struct snd_kcontrol_new wm8994_common_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
                 WM8994_AIF1_ADC1_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
-                WM8994_AIF1_ADC2_RIGHT_VOLUME,
-                1, 119, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
                 WM8994_AIF2_ADC_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
@@ -560,8 +557,6 @@ SOC_ENUM("AIF2DACR Source", aif2dacr_src),
 
 SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
                 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
-                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME,
                 WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
 
@@ -569,17 +564,12 @@ SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv),
 SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv),
 
 SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0),
-SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0),
 
 WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2),
 WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1),
 WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0),
 
-WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
-WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
-WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
-
 WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2),
 WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1),
 WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0),
@@ -598,9 +588,6 @@ SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0),
 SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf),
 SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0),
 
-SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
-SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
-
 SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf),
 SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0),
 
@@ -641,6 +628,24 @@ SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF2_DAC_FILTERS_2,
           8, 1, 0),
 };
 
+/* Controls not available on WM1811 */
+static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
+                WM8994_AIF1_ADC2_RIGHT_VOLUME,
+                1, 119, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
+                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
+
+SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
+
+WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
+WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
+WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
+
+SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
+SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
+};
+
 static const struct snd_kcontrol_new wm8994_eq_controls[] = {
 SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0,
               eq_tlv),
@@ -4262,13 +4267,15 @@ static int wm8994_component_probe(struct snd_soc_component *component)
        wm8994_handle_pdata(wm8994);
 
        wm_hubs_add_analogue_controls(component);
-       snd_soc_add_component_controls(component, wm8994_snd_controls,
-                            ARRAY_SIZE(wm8994_snd_controls));
+       snd_soc_add_component_controls(component, wm8994_common_snd_controls,
+                                      ARRAY_SIZE(wm8994_common_snd_controls));
        snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
                                  ARRAY_SIZE(wm8994_dapm_widgets));
 
        switch (control->type) {
        case WM8994:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
                                          ARRAY_SIZE(wm8994_specific_dapm_widgets));
                if (control->revision < 4) {
@@ -4288,8 +4295,10 @@ static int wm8994_component_probe(struct snd_soc_component *component)
                }
                break;
        case WM8958:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_add_component_controls(component, wm8958_snd_controls,
-                                    ARRAY_SIZE(wm8958_snd_controls));
+                                              ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
                if (control->revision < 1) {
index ee85056..b114fc7 100644 (file)
@@ -1147,8 +1147,7 @@ static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
        }
 
        if (in) {
-               if (in & WMFW_CTL_FLAG_READABLE)
-                       out |= rd;
+               out |= rd;
                if (in & WMFW_CTL_FLAG_WRITEABLE)
                        out |= wr;
                if (in & WMFW_CTL_FLAG_VOLATILE)
index 11399f8..b86f76c 100644 (file)
@@ -677,7 +677,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        ret = rockchip_pcm_platform_register(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Could not register PCM\n");
-               return ret;
+               goto err_suspend;
        }
 
        return 0;
index 61aa62f..c102c03 100644 (file)
@@ -1343,7 +1343,8 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        struct usb_interface *iface;
 
        /* Playback Designs */
-       if (USB_ID_VENDOR(chip->usb_id) == 0x23ba) {
+       if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
+           USB_ID_PRODUCT(chip->usb_id) < 0x0110) {
                switch (fp->altsetting) {
                case 1:
                        fp->dsd_dop = true;
@@ -1360,37 +1361,19 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        /* XMOS based USB DACs */
        switch (chip->usb_id) {
        case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
-       case USB_ID(0x20b1, 0x0002): /* Wyred 4 Sound DAC-2 DSD */
-       case USB_ID(0x20b1, 0x2004): /* Matrix Audio X-SPDIF 2 */
-       case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
-       case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
-       case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
-       case USB_ID(0x22d9, 0x0436): /* OPPO Sonica */
-       case USB_ID(0x22d9, 0x0461): /* OPPO UDP-205 */
        case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */
        case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */
                if (fp->altsetting == 2)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
-       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
-       case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
-       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
+       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */
+       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
        case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
        case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */
-       case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */
-       case USB_ID(0x20b1, 0x2005): /* Denafrips Ares DAC */
-       case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
-       case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
-       case USB_ID(0x20b1, 0x3021): /* Eastern El. MiniMax Tube DAC Supreme */
-       case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
-       case USB_ID(0x20b1, 0x302d): /* Unison Research Unico CD Due */
-       case USB_ID(0x20b1, 0x307b): /* CH Precision C1 DAC */
-       case USB_ID(0x20b1, 0x3086): /* Singxer F-1 converter board */
-       case USB_ID(0x22d9, 0x0426): /* OPPO HA-2 */
        case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */
        case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */
        case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
@@ -1445,9 +1428,12 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
         * from XMOS/Thesycon
         */
        switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x20b1:  /* XMOS based devices */
        case 0x152a:  /* Thesycon devices */
+       case 0x20b1:  /* XMOS based devices */
+       case 0x22d9:  /* Oppo */
+       case 0x23ba:  /* Playback Designs */
        case 0x25ce:  /* Mytek devices */
+       case 0x278b:  /* Rotel? */
        case 0x292b:  /* Gustard/Ess based devices */
        case 0x2ab6:  /* T+A devices */
        case 0x3842:  /* EVGA */
index ed61fb3..5b2cd5e 100644 (file)
@@ -20,7 +20,13 @@ MAKEFLAGS += --no-print-directory
 LIBFILE = $(OUTPUT)libsubcmd.a
 
 CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -fPIC
+
+ifeq ($(DEBUG),0)
+  ifeq ($(feature-fortify-source), 1)
+    CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
+  endif
+endif
 
 ifeq ($(CC_NO_CLANG), 0)
   CFLAGS += -O3
index 0b24266..e46be9e 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/types.h>
+#include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,7 +32,7 @@ get_cpuid(char *buffer, size_t sz)
                buffer[nb-1] = '\0';
                return 0;
        }
-       return -1;
+       return ENOBUFS;
 }
 
 char *
index 163b92f..cc72554 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <sys/types.h>
+#include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
@@ -56,7 +57,7 @@ int get_cpuid(char *buffer, size_t sz)
 
        sysinfo = fopen(SYSINFO, "r");
        if (sysinfo == NULL)
-               return -1;
+               return errno;
 
        while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
                if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
@@ -91,7 +92,7 @@ int get_cpuid(char *buffer, size_t sz)
 
        /* Missing manufacturer, type or model information should not happen */
        if (!manufacturer[0] || !type[0] || !model[0])
-               return -1;
+               return EINVAL;
 
        /*
         * Scan /proc/service_levels and return the CPU-MF counter facility
@@ -135,14 +136,14 @@ skip_sysinfo:
        else
                nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
                                  model);
-       return (nbytes >= sz) ? -1 : 0;
+       return (nbytes >= sz) ? ENOBUFS : 0;
 }
 
 char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 {
        char *buf = malloc(128);
 
-       if (buf && get_cpuid(buf, 128) < 0)
+       if (buf && get_cpuid(buf, 128))
                zfree(&buf);
        return buf;
 }
index fb0d71a..2a5daec 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/types.h>
+#include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -56,7 +57,7 @@ __get_cpuid(char *buffer, size_t sz, const char *fmt)
                buffer[nb-1] = '\0';
                return 0;
        }
-       return -1;
+       return ENOBUFS;
 }
 
 int
index 763c2ed..1452e51 100644 (file)
@@ -2626,6 +2626,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
        bool add_sym   = false;
        bool add_dso   = false;
        bool add_src   = false;
+       int ret = 0;
 
        if (!buf)
                return -ENOMEM;
@@ -2644,7 +2645,8 @@ static int build_cl_output(char *cl_sort, bool no_source)
                        add_dso = true;
                } else if (strcmp(tok, "offset")) {
                        pr_err("unrecognized sort token: %s\n", tok);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto err;
                }
        }
 
@@ -2667,13 +2669,15 @@ static int build_cl_output(char *cl_sort, bool no_source)
                add_sym ? "symbol," : "",
                add_dso ? "dso," : "",
                add_src ? "cl_srcline," : "",
-               "node") < 0)
-               return -ENOMEM;
+               "node") < 0) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        c2c.show_src = add_src;
-
+err:
        free(buf);
-       return 0;
+       return ret;
 }
 
 static int setup_coalesce(const char *coalesce, bool no_source)
index b63bca4..56dd5d1 100644 (file)
@@ -686,6 +686,7 @@ static char *compact_gfp_flags(char *gfp_flags)
                        new = realloc(new_flags, len + strlen(cpt) + 2);
                        if (new == NULL) {
                                free(new_flags);
+                               free(orig_flags);
                                return NULL;
                        }
 
index 2b1ef70..952e222 100644 (file)
@@ -699,14 +699,15 @@ static int process_sample_event(struct perf_tool *tool,
 
 static int cpu_isa_config(struct perf_kvm_stat *kvm)
 {
-       char buf[64], *cpuid;
+       char buf[128], *cpuid;
        int err;
 
        if (kvm->live) {
                err = get_cpuid(buf, sizeof(buf));
                if (err != 0) {
-                       pr_err("Failed to look up CPU type\n");
-                       return err;
+                       pr_err("Failed to look up CPU type: %s\n",
+                              str_error_r(err, buf, sizeof(buf)));
+                       return -err;
                }
                cpuid = buf;
        } else
index 53c11fc..d20f851 100644 (file)
@@ -1021,7 +1021,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
                        continue;
 
                insn = 0;
-               for (off = 0;; off += ilen) {
+               for (off = 0; off < (unsigned)len; off += ilen) {
                        uint64_t ip = start + off;
 
                        printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
@@ -1029,6 +1029,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
                                printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp);
                                break;
                        } else {
+                               ilen = 0;
                                printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
                                                   dump_insn(&x, ip, buffer + off, len - off, &ilen));
                                if (ilen == 0)
@@ -1036,6 +1037,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
                                insn++;
                        }
                }
+               if (off != (unsigned)len)
+                       printed += fprintf(fp, "\tmismatch of LBR data and executable\n");
        }
 
        /*
@@ -1066,6 +1069,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
                goto out;
        }
        for (off = 0; off <= end - start; off += ilen) {
+               ilen = 0;
                printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off,
                                   dump_insn(&x, start + off, buffer + off, len - off, &ilen));
                if (ilen == 0)
index 6b36b71..6cd9623 100644 (file)
@@ -446,12 +446,12 @@ static struct fixed {
        const char *name;
        const char *event;
 } fixed[] = {
-       { "inst_retired.any", "event=0xc0" },
-       { "inst_retired.any_p", "event=0xc0" },
-       { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" },
-       { "cpu_clk_unhalted.thread", "event=0x3c" },
-       { "cpu_clk_unhalted.core", "event=0x3c" },
-       { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" },
+       { "inst_retired.any", "event=0xc0,period=2000003" },
+       { "inst_retired.any_p", "event=0xc0,period=2000003" },
+       { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03,period=2000003" },
+       { "cpu_clk_unhalted.thread", "event=0x3c,period=2000003" },
+       { "cpu_clk_unhalted.core", "event=0x3c,period=2000003" },
+       { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1,period=2000003" },
        { NULL, NULL},
 };
 
index a693bcf..44c16fd 100644 (file)
@@ -20,12 +20,11 @@ static void sigsegv_handler(int sig __maybe_unused)
 static void the_hook(void *_hook_flags)
 {
        int *hook_flags = _hook_flags;
-       int *p = NULL;
 
        *hook_flags = 1234;
 
        /* Generate a segfault, test perf_hooks__recover */
-       *p = 0;
+       raise(SIGSEGV);
 }
 
 int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unused)
index daea1fd..6958d7e 100644 (file)
@@ -1614,7 +1614,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
 
        build_id_path = strdup(filename);
        if (!build_id_path)
-               return -1;
+               return ENOMEM;
 
        /*
         * old style build-id cache has name of XX/XXXXXXX.. while
@@ -1871,11 +1871,11 @@ int symbol__annotate(struct symbol *sym, struct map *map,
        int err;
 
        if (!arch_name)
-               return -1;
+               return errno;
 
        args.arch = arch = arch__find(arch_name);
        if (arch == NULL)
-               return -ENOTSUP;
+               return ENOTSUP;
 
        if (parch)
                *parch = arch;
@@ -2732,7 +2732,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
 
        notes->offsets = zalloc(size * sizeof(struct annotation_line *));
        if (notes->offsets == NULL)
-               return -1;
+               return ENOMEM;
 
        if (perf_evsel__is_group_event(evsel))
                nr_pcnt = evsel->nr_members;
@@ -2757,7 +2757,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
 
 out_free_offsets:
        zfree(&notes->offsets);
-       return -1;
+       return err;
 }
 
 #define ANNOTATION__CFG(n) \
index 6a6929f..1117ab8 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "symbol.h"
+#include <assert.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -751,6 +752,8 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
                        }
 
                        after->start = map->end;
+                       after->pgoff += map->end - pos->start;
+                       assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
                        __map_groups__insert(pos->groups, after);
                        if (verbose >= 2 && !use_browser)
                                map__fprintf(after, fp);
index 71cf7e7..823bbc7 100644 (file)
@@ -1953,11 +1953,12 @@ done:
 #define PCL_7S 11 /* PC7 Shrink */
 #define PCL__8 12 /* PC8 */
 #define PCL__9 13 /* PC9 */
-#define PCLUNL 14 /* Unlimited */
+#define PCL_10 14 /* PC10 */
+#define PCLUNL 15 /* Unlimited */
 
 int pkg_cstate_limit = PCLUKN;
 char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
-       "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "unlimited"};
+       "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"};
 
 int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
@@ -1965,7 +1966,7 @@ int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S,
 int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
 int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
+int glm_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 
 
@@ -3165,7 +3166,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
        case INTEL_FAM6_ATOM_GOLDMONT:  /* BXT */
        case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
        case INTEL_FAM6_ATOM_GOLDMONT_X:        /* DNV */
-               pkg_cstate_limits = bxt_pkg_cstate_limits;
+               pkg_cstate_limits = glm_pkg_cstate_limits;
                break;
        default:
                return 0;
index 2f190aa..c0885fb 100755 (executable)
@@ -1301,6 +1301,27 @@ ipv4_addr_metric_test()
        fi
        log_test $rc 0 "Prefix route with metric on link up"
 
+       # explicitly check for metric changes on edge scenarios
+       run_cmd "$IP addr flush dev dummy2"
+       run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
+       run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
+       rc=$?
+       if [ $rc -eq 0 ]; then
+               check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
+               rc=$?
+       fi
+       log_test $rc 0 "Modify metric of .0/24 address"
+
+       run_cmd "$IP addr flush dev dummy2"
+       run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
+       run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 261"
+       rc=$?
+       if [ $rc -eq 0 ]; then
+               check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
+               rc=$?
+       fi
+       log_test $rc 0 "Modify metric of address with peer route"
+
        $IP li del dummy1
        $IP li del dummy2
        cleanup
index fe3230c..fb7a59e 100644 (file)
@@ -129,7 +129,7 @@ static void test(int *rcv_fds, int count, int proto)
 {
        struct epoll_event ev;
        int epfd, i, test_fd;
-       uint16_t test_family;
+       int test_family;
        socklen_t len;
 
        epfd = epoll_create(1);
@@ -146,6 +146,7 @@ static void test(int *rcv_fds, int count, int proto)
        send_from_v4(proto);
 
        test_fd = receive_once(epfd, proto);
+       len = sizeof(test_family);
        if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len))
                error(1, errno, "failed to read socket domain");
        if (test_family != AF_INET)
index 33ced6e..8696282 100644 (file)
@@ -3,6 +3,7 @@ noarg:
        $(MAKE) -C ../
 
 TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors
+TEST_GEN_PROGS_EXTENDED := tlbie_test
 TEST_GEN_FILES := tempfile
 
 top_srcdir = ../../../../..
@@ -15,3 +16,4 @@ $(OUTPUT)/prot_sao: ../utils.c
 $(OUTPUT)/tempfile:
        dd if=/dev/zero of=$@ bs=64k count=1
 
+$(OUTPUT)/tlbie_test: LDLIBS += -lpthread
diff --git a/tools/testing/selftests/powerpc/mm/tlbie_test.c b/tools/testing/selftests/powerpc/mm/tlbie_test.c
new file mode 100644 (file)
index 0000000..f85a093
--- /dev/null
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019, Nick Piggin, Gautham R. Shenoy, Aneesh Kumar K.V, IBM Corp.
+ */
+
+/*
+ *
+ * Test tlbie/mtpidr race. We have 4 threads doing flush/load/compare/store
+ * sequence in a loop. The same threads also rung a context switch task
+ * that does sched_yield() in loop.
+ *
+ * The snapshot thread mark the mmap area PROT_READ in between, make a copy
+ * and copy it back to the original area. This helps us to detect if any
+ * store continued to happen after we marked the memory PROT_READ.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <linux/futex.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <time.h>
+#include <stdarg.h>
+#include <sched.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/prctl.h>
+
+static inline void dcbf(volatile unsigned int *addr)
+{
+       __asm__ __volatile__ ("dcbf %y0; sync" : : "Z"(*(unsigned char *)addr) : "memory");
+}
+
+static void err_msg(char *msg)
+{
+
+       time_t now;
+       time(&now);
+       printf("=================================\n");
+       printf("    Error: %s\n", msg);
+       printf("    %s", ctime(&now));
+       printf("=================================\n");
+       exit(1);
+}
+
+static char *map1;
+static char *map2;
+static pid_t rim_process_pid;
+
+/*
+ * A "rim-sequence" is defined to be the sequence of the following
+ * operations performed on a memory word:
+ *     1) FLUSH the contents of that word.
+ *     2) LOAD the contents of that word.
+ *     3) COMPARE the contents of that word with the content that was
+ *                previously stored at that word
+ *     4) STORE new content into that word.
+ *
+ * The threads in this test that perform the rim-sequence are termed
+ * as rim_threads.
+ */
+
+/*
+ * A "corruption" is defined to be the failed COMPARE operation in a
+ * rim-sequence.
+ *
+ * A rim_thread that detects a corruption informs about it to all the
+ * other rim_threads, and the mem_snapshot thread.
+ */
+static volatile unsigned int corruption_found;
+
+/*
+ * This defines the maximum number of rim_threads in this test.
+ *
+ * The THREAD_ID_BITS denote the number of bits required
+ * to represent the thread_ids [0..MAX_THREADS - 1].
+ * We are being a bit paranoid here and set it to 8 bits,
+ * though 6 bits suffice.
+ *
+ */
+#define MAX_THREADS            64
+#define THREAD_ID_BITS         8
+#define THREAD_ID_MASK         ((1 << THREAD_ID_BITS) - 1)
+static unsigned int rim_thread_ids[MAX_THREADS];
+static pthread_t rim_threads[MAX_THREADS];
+
+
+/*
+ * Each rim_thread works on an exclusive "chunk" of size
+ * RIM_CHUNK_SIZE.
+ *
+ * The ith rim_thread works on the ith chunk.
+ *
+ * The ith chunk begins at
+ * map1 + (i * RIM_CHUNK_SIZE)
+ */
+#define RIM_CHUNK_SIZE         1024
+#define BITS_PER_BYTE          8
+#define WORD_SIZE              (sizeof(unsigned int))
+#define WORD_BITS              (WORD_SIZE * BITS_PER_BYTE)
+#define WORDS_PER_CHUNK                (RIM_CHUNK_SIZE/WORD_SIZE)
+
+static inline char *compute_chunk_start_addr(unsigned int thread_id)
+{
+       char *chunk_start;
+
+       chunk_start = (char *)((unsigned long)map1 +
+                              (thread_id * RIM_CHUNK_SIZE));
+
+       return chunk_start;
+}
+
+/*
+ * The "word-offset" of a word-aligned address inside a chunk, is
+ * defined to be the number of words that precede the address in that
+ * chunk.
+ *
+ * WORD_OFFSET_BITS denote the number of bits required to represent
+ * the word-offsets of all the word-aligned addresses of a chunk.
+ */
+#define WORD_OFFSET_BITS       (__builtin_ctz(WORDS_PER_CHUNK))
+#define WORD_OFFSET_MASK       ((1 << WORD_OFFSET_BITS) - 1)
+
+static inline unsigned int compute_word_offset(char *start, unsigned int *addr)
+{
+       unsigned int delta_bytes, ret;
+       delta_bytes = (unsigned long)addr - (unsigned long)start;
+
+       ret = delta_bytes/WORD_SIZE;
+
+       return ret;
+}
+
+/*
+ * A "sweep" is defined to be the sequential execution of the
+ * rim-sequence by a rim_thread on its chunk one word at a time,
+ * starting from the first word of its chunk and ending with the last
+ * word of its chunk.
+ *
+ * Each sweep of a rim_thread is uniquely identified by a sweep_id.
+ * SWEEP_ID_BITS denote the number of bits required to represent
+ * the sweep_ids of rim_threads.
+ *
+ * As to why SWEEP_ID_BITS are computed as a function of THREAD_ID_BITS,
+ * WORD_OFFSET_BITS, and WORD_BITS, see the "store-pattern" below.
+ */
+#define SWEEP_ID_BITS          (WORD_BITS - (THREAD_ID_BITS + WORD_OFFSET_BITS))
+#define SWEEP_ID_MASK          ((1 << SWEEP_ID_BITS) - 1)
+
+/*
+ * A "store-pattern" is the word-pattern that is stored into a word
+ * location in the 4)STORE step of the rim-sequence.
+ *
+ * In the store-pattern, we shall encode:
+ *
+ *      - The thread-id of the rim_thread performing the store
+ *        (The most significant THREAD_ID_BITS)
+ *
+ *      - The word-offset of the address into which the store is being
+ *        performed (The next WORD_OFFSET_BITS)
+ *
+ *      - The sweep_id of the current sweep in which the store is
+ *        being performed. (The lower SWEEP_ID_BITS)
+ *
+ * Store Pattern: 32 bits
+ * |------------------|--------------------|---------------------------------|
+ * |    Thread id     |  Word offset       |         sweep_id                |
+ * |------------------|--------------------|---------------------------------|
+ *    THREAD_ID_BITS     WORD_OFFSET_BITS          SWEEP_ID_BITS
+ *
+ * In the store pattern, the (Thread-id + Word-offset) uniquely identify the
+ * address to which the store is being performed i.e,
+ *    address == map1 +
+ *              (Thread-id * RIM_CHUNK_SIZE) + (Word-offset * WORD_SIZE)
+ *
+ * And the sweep_id in the store pattern identifies the time when the
+ * store was performed by the rim_thread.
+ *
+ * We shall use this property in the 3)COMPARE step of the
+ * rim-sequence.
+ */
+#define SWEEP_ID_SHIFT 0
+#define WORD_OFFSET_SHIFT      (SWEEP_ID_BITS)
+#define THREAD_ID_SHIFT                (WORD_OFFSET_BITS + SWEEP_ID_BITS)
+
+/*
+ * Compute the store pattern for a given thread with id @tid, at
+ * location @addr in the sweep identified by @sweep_id
+ */
+static inline unsigned int compute_store_pattern(unsigned int tid,
+                                                unsigned int *addr,
+                                                unsigned int sweep_id)
+{
+       unsigned int ret = 0;
+       char *start = compute_chunk_start_addr(tid);
+       unsigned int word_offset = compute_word_offset(start, addr);
+
+       ret += (tid & THREAD_ID_MASK) << THREAD_ID_SHIFT;
+       ret += (word_offset & WORD_OFFSET_MASK) << WORD_OFFSET_SHIFT;
+       ret += (sweep_id & SWEEP_ID_MASK) << SWEEP_ID_SHIFT;
+       return ret;
+}
+
+/* Extract the thread-id from the given store-pattern */
+static inline unsigned int extract_tid(unsigned int pattern)
+{
+       unsigned int ret;
+
+       ret = (pattern >> THREAD_ID_SHIFT) & THREAD_ID_MASK;
+       return ret;
+}
+
+/* Extract the word-offset from the given store-pattern */
+static inline unsigned int extract_word_offset(unsigned int pattern)
+{
+       unsigned int ret;
+
+       ret = (pattern >> WORD_OFFSET_SHIFT) & WORD_OFFSET_MASK;
+
+       return ret;
+}
+
+/* Extract the sweep-id from the given store-pattern */
+static inline unsigned int extract_sweep_id(unsigned int pattern)
+
+{
+       unsigned int ret;
+
+       ret = (pattern >> SWEEP_ID_SHIFT) & SWEEP_ID_MASK;
+
+       return ret;
+}
+
+/************************************************************
+ *                                                          *
+ *          Logging the output of the verification          *
+ *                                                          *
+ ************************************************************/
+#define LOGDIR_NAME_SIZE 100
+static char logdir[LOGDIR_NAME_SIZE];
+
+static FILE *fp[MAX_THREADS];
+static const char logfilename[] ="Thread-%02d-Chunk";
+
+static inline void start_verification_log(unsigned int tid,
+                                         unsigned int *addr,
+                                         unsigned int cur_sweep_id,
+                                         unsigned int prev_sweep_id)
+{
+       FILE *f;
+       char logfile[30];
+       char path[LOGDIR_NAME_SIZE + 30];
+       char separator[2] = "/";
+       char *chunk_start = compute_chunk_start_addr(tid);
+       unsigned int size = RIM_CHUNK_SIZE;
+
+       sprintf(logfile, logfilename, tid);
+       strcpy(path, logdir);
+       strcat(path, separator);
+       strcat(path, logfile);
+       f = fopen(path, "w");
+
+       if (!f) {
+               err_msg("Unable to create logfile\n");
+       }
+
+       fp[tid] = f;
+
+       fprintf(f, "----------------------------------------------------------\n");
+       fprintf(f, "PID                = %d\n", rim_process_pid);
+       fprintf(f, "Thread id          = %02d\n", tid);
+       fprintf(f, "Chunk Start Addr   = 0x%016lx\n", (unsigned long)chunk_start);
+       fprintf(f, "Chunk Size         = %d\n", size);
+       fprintf(f, "Next Store Addr    = 0x%016lx\n", (unsigned long)addr);
+       fprintf(f, "Current sweep-id   = 0x%08x\n", cur_sweep_id);
+       fprintf(f, "Previous sweep-id  = 0x%08x\n", prev_sweep_id);
+       fprintf(f, "----------------------------------------------------------\n");
+}
+
+static inline void log_anamoly(unsigned int tid, unsigned int *addr,
+                              unsigned int expected, unsigned int observed)
+{
+       FILE *f = fp[tid];
+
+       fprintf(f, "Thread %02d: Addr 0x%lx: Expected 0x%x, Observed 0x%x\n",
+               tid, (unsigned long)addr, expected, observed);
+       fprintf(f, "Thread %02d: Expected Thread id   = %02d\n", tid, extract_tid(expected));
+       fprintf(f, "Thread %02d: Observed Thread id   = %02d\n", tid, extract_tid(observed));
+       fprintf(f, "Thread %02d: Expected Word offset = %03d\n", tid, extract_word_offset(expected));
+       fprintf(f, "Thread %02d: Observed Word offset = %03d\n", tid, extract_word_offset(observed));
+       fprintf(f, "Thread %02d: Expected sweep-id    = 0x%x\n", tid, extract_sweep_id(expected));
+       fprintf(f, "Thread %02d: Observed sweep-id    = 0x%x\n", tid, extract_sweep_id(observed));
+       fprintf(f, "----------------------------------------------------------\n");
+}
+
+static inline void end_verification_log(unsigned int tid, unsigned nr_anamolies)
+{
+       FILE *f = fp[tid];
+       char logfile[30];
+       char path[LOGDIR_NAME_SIZE + 30];
+       char separator[] = "/";
+
+       fclose(f);
+
+       if (nr_anamolies == 0) {
+               remove(path);
+               return;
+       }
+
+       sprintf(logfile, logfilename, tid);
+       strcpy(path, logdir);
+       strcat(path, separator);
+       strcat(path, logfile);
+
+       printf("Thread %02d chunk has %d corrupted words. For details check %s\n",
+               tid, nr_anamolies, path);
+}
+
+/*
+ * When a COMPARE step of a rim-sequence fails, the rim_thread informs
+ * everyone else via the shared_memory pointed to by
+ * corruption_found variable. On seeing this, every thread verifies the
+ * content of its chunk as follows.
+ *
+ * Suppose a thread identified with @tid was about to store (but not
+ * yet stored) to @next_store_addr in its current sweep identified
+ * @cur_sweep_id. Let @prev_sweep_id indicate the previous sweep_id.
+ *
+ * This implies that for all the addresses @addr < @next_store_addr,
+ * Thread @tid has already performed a store as part of its current
+ * sweep. Hence we expect the content of such @addr to be:
+ *    |-------------------------------------------------|
+ *    | tid   | word_offset(addr) |    cur_sweep_id     |
+ *    |-------------------------------------------------|
+ *
+ * Since Thread @tid is yet to perform stores on address
+ * @next_store_addr and above, we expect the content of such an
+ * address @addr to be:
+ *    |-------------------------------------------------|
+ *    | tid   | word_offset(addr) |    prev_sweep_id    |
+ *    |-------------------------------------------------|
+ *
+ * The verifier function @verify_chunk does this verification and logs
+ * any anamolies that it finds.
+ */
+static void verify_chunk(unsigned int tid, unsigned int *next_store_addr,
+                 unsigned int cur_sweep_id,
+                 unsigned int prev_sweep_id)
+{
+       unsigned int *iter_ptr;
+       unsigned int size = RIM_CHUNK_SIZE;
+       unsigned int expected;
+       unsigned int observed;
+       char *chunk_start = compute_chunk_start_addr(tid);
+
+       int nr_anamolies = 0;
+
+       start_verification_log(tid, next_store_addr,
+                              cur_sweep_id, prev_sweep_id);
+
+       for (iter_ptr = (unsigned int *)chunk_start;
+            (unsigned long)iter_ptr < (unsigned long)chunk_start + size;
+            iter_ptr++) {
+               unsigned int expected_sweep_id;
+
+               if (iter_ptr < next_store_addr) {
+                       expected_sweep_id = cur_sweep_id;
+               } else {
+                       expected_sweep_id = prev_sweep_id;
+               }
+
+               expected = compute_store_pattern(tid, iter_ptr, expected_sweep_id);
+
+               dcbf((volatile unsigned int*)iter_ptr); //Flush before reading
+               observed = *iter_ptr;
+
+               if (observed != expected) {
+                       nr_anamolies++;
+                       log_anamoly(tid, iter_ptr, expected, observed);
+               }
+       }
+
+       end_verification_log(tid, nr_anamolies);
+}
+
+static void set_pthread_cpu(pthread_t th, int cpu)
+{
+       cpu_set_t run_cpu_mask;
+       struct sched_param param;
+
+       CPU_ZERO(&run_cpu_mask);
+       CPU_SET(cpu, &run_cpu_mask);
+       pthread_setaffinity_np(th, sizeof(cpu_set_t), &run_cpu_mask);
+
+       param.sched_priority = 1;
+       if (0 && sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+               /* haven't reproduced with this setting, it kills random preemption which may be a factor */
+               fprintf(stderr, "could not set SCHED_FIFO, run as root?\n");
+       }
+}
+
+static void set_mycpu(int cpu)
+{
+       cpu_set_t run_cpu_mask;
+       struct sched_param param;
+
+       CPU_ZERO(&run_cpu_mask);
+       CPU_SET(cpu, &run_cpu_mask);
+       sched_setaffinity(0, sizeof(cpu_set_t), &run_cpu_mask);
+
+       param.sched_priority = 1;
+       if (0 && sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+               fprintf(stderr, "could not set SCHED_FIFO, run as root?\n");
+       }
+}
+
+static volatile int segv_wait;
+
+static void segv_handler(int signo, siginfo_t *info, void *extra)
+{
+       while (segv_wait) {
+               sched_yield();
+       }
+
+}
+
+static void set_segv_handler(void)
+{
+       struct sigaction sa;
+
+       sa.sa_flags = SA_SIGINFO;
+       sa.sa_sigaction = segv_handler;
+
+       if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+               perror("sigaction");
+               exit(EXIT_FAILURE);
+       }
+}
+
+int timeout = 0;
+/*
+ * This function is executed by every rim_thread.
+ *
+ * This function performs sweeps over the exclusive chunks of the
+ * rim_threads executing the rim-sequence one word at a time.
+ */
+static void *rim_fn(void *arg)
+{
+       unsigned int tid = *((unsigned int *)arg);
+
+       int size = RIM_CHUNK_SIZE;
+       char *chunk_start = compute_chunk_start_addr(tid);
+
+       unsigned int prev_sweep_id;
+       unsigned int cur_sweep_id = 0;
+
+       /* word access */
+       unsigned int pattern = cur_sweep_id;
+       unsigned int *pattern_ptr = &pattern;
+       unsigned int *w_ptr, read_data;
+
+       set_segv_handler();
+
+       /*
+        * Let us initialize the chunk:
+        *
+        * Each word-aligned address addr in the chunk,
+        * is initialized to :
+        *    |-------------------------------------------------|
+        *    | tid   | word_offset(addr) |         0           |
+        *    |-------------------------------------------------|
+        */
+       for (w_ptr = (unsigned int *)chunk_start;
+            (unsigned long)w_ptr < (unsigned long)(chunk_start) + size;
+            w_ptr++) {
+
+               *pattern_ptr = compute_store_pattern(tid, w_ptr, cur_sweep_id);
+               *w_ptr = *pattern_ptr;
+       }
+
+       while (!corruption_found && !timeout) {
+               prev_sweep_id = cur_sweep_id;
+               cur_sweep_id = cur_sweep_id + 1;
+
+               for (w_ptr = (unsigned int *)chunk_start;
+                    (unsigned long)w_ptr < (unsigned long)(chunk_start) + size;
+                    w_ptr++)  {
+                       unsigned int old_pattern;
+
+                       /*
+                        * Compute the pattern that we would have
+                        * stored at this location in the previous
+                        * sweep.
+                        */
+                       old_pattern = compute_store_pattern(tid, w_ptr, prev_sweep_id);
+
+                       /*
+                        * FLUSH:Ensure that we flush the contents of
+                        *       the cache before loading
+                        */
+                       dcbf((volatile unsigned int*)w_ptr); //Flush
+
+                       /* LOAD: Read the value */
+                       read_data = *w_ptr; //Load
+
+                       /*
+                        * COMPARE: Is it the same as what we had stored
+                        *          in the previous sweep ? It better be!
+                        */
+                       if (read_data != old_pattern) {
+                               /* No it isn't! Tell everyone */
+                               corruption_found = 1;
+                       }
+
+                       /*
+                        * Before performing a store, let us check if
+                        * any rim_thread has found a corruption.
+                        */
+                       if (corruption_found || timeout) {
+                               /*
+                                * Yes. Someone (including us!) has found
+                                * a corruption :(
+                                *
+                                * Let us verify that our chunk is
+                                * correct.
+                                */
+                               /* But first, let us allow the dust to settle down! */
+                               verify_chunk(tid, w_ptr, cur_sweep_id, prev_sweep_id);
+
+                               return 0;
+                       }
+
+                       /*
+                        * Compute the new pattern that we are going
+                        * to write to this location
+                        */
+                       *pattern_ptr = compute_store_pattern(tid, w_ptr, cur_sweep_id);
+
+                       /*
+                        * STORE: Now let us write this pattern into
+                        *        the location
+                        */
+                       *w_ptr = *pattern_ptr;
+               }
+       }
+
+       return NULL;
+}
+
+
+static unsigned long start_cpu = 0;
+static unsigned long nrthreads = 4;
+
+static pthread_t mem_snapshot_thread;
+
+static void *mem_snapshot_fn(void *arg)
+{
+       int page_size = getpagesize();
+       size_t size = page_size;
+       void *tmp = malloc(size);
+
+       while (!corruption_found && !timeout) {
+               /* Stop memory migration once corruption is found */
+               segv_wait = 1;
+
+               mprotect(map1, size, PROT_READ);
+
+               /*
+                * Load from the working alias (map1). Loading from map2
+                * also fails.
+                */
+               memcpy(tmp, map1, size);
+
+               /*
+                * Stores must go via map2 which has write permissions, but
+                * the corrupted data tends to be seen in the snapshot buffer,
+                * so corruption does not appear to be introduced at the
+                * copy-back via map2 alias here.
+                */
+               memcpy(map2, tmp, size);
+               /*
+                * Before releasing other threads, must ensure the copy
+                * back to
+                */
+               asm volatile("sync" ::: "memory");
+               mprotect(map1, size, PROT_READ|PROT_WRITE);
+               asm volatile("sync" ::: "memory");
+               segv_wait = 0;
+
+               usleep(1); /* This value makes a big difference */
+       }
+
+       return 0;
+}
+
+void alrm_sighandler(int sig)
+{
+       timeout = 1;
+}
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int page_size = getpagesize();
+       time_t now;
+       int i, dir_error;
+       pthread_attr_t attr;
+       key_t shm_key = (key_t) getpid();
+       int shmid, run_time = 20 * 60;
+       struct sigaction sa_alrm;
+
+       snprintf(logdir, LOGDIR_NAME_SIZE,
+                "/tmp/logdir-%u", (unsigned int)getpid());
+       while ((c = getopt(argc, argv, "r:hn:l:t:")) != -1) {
+               switch(c) {
+               case 'r':
+                       start_cpu = strtoul(optarg, NULL, 10);
+                       break;
+               case 'h':
+                       printf("%s [-r <start_cpu>] [-n <nrthreads>] [-l <logdir>] [-t <timeout>]\n", argv[0]);
+                       exit(0);
+                       break;
+               case 'n':
+                       nrthreads = strtoul(optarg, NULL, 10);
+                       break;
+               case 'l':
+                       strncpy(logdir, optarg, LOGDIR_NAME_SIZE - 1);
+                       break;
+               case 't':
+                       run_time = strtoul(optarg, NULL, 10);
+                       break;
+               default:
+                       printf("invalid option\n");
+                       exit(0);
+                       break;
+               }
+       }
+
+       if (nrthreads > MAX_THREADS)
+               nrthreads = MAX_THREADS;
+
+       shmid = shmget(shm_key, page_size, IPC_CREAT|0666);
+       if (shmid < 0) {
+               err_msg("Failed shmget\n");
+       }
+
+       map1 = shmat(shmid, NULL, 0);
+       if (map1 == (void *) -1) {
+               err_msg("Failed shmat");
+       }
+
+       map2 = shmat(shmid, NULL, 0);
+       if (map2 == (void *) -1) {
+               err_msg("Failed shmat");
+       }
+
+       dir_error = mkdir(logdir, 0755);
+
+       if (dir_error) {
+               err_msg("Failed mkdir");
+       }
+
+       printf("start_cpu list:%lu\n", start_cpu);
+       printf("number of worker threads:%lu + 1 snapshot thread\n", nrthreads);
+       printf("Allocated address:0x%016lx + secondary map:0x%016lx\n", (unsigned long)map1, (unsigned long)map2);
+       printf("logdir at : %s\n", logdir);
+       printf("Timeout: %d seconds\n", run_time);
+
+       time(&now);
+       printf("=================================\n");
+       printf("     Starting Test\n");
+       printf("     %s", ctime(&now));
+       printf("=================================\n");
+
+       for (i = 0; i < nrthreads; i++) {
+               if (1 && !fork()) {
+                       prctl(PR_SET_PDEATHSIG, SIGKILL);
+                       set_mycpu(start_cpu + i);
+                       for (;;)
+                               sched_yield();
+                       exit(0);
+               }
+       }
+
+
+       sa_alrm.sa_handler = &alrm_sighandler;
+       sigemptyset(&sa_alrm.sa_mask);
+       sa_alrm.sa_flags = 0;
+
+       if (sigaction(SIGALRM, &sa_alrm, 0) == -1) {
+               err_msg("Failed signal handler registration\n");
+       }
+
+       alarm(run_time);
+
+       pthread_attr_init(&attr);
+       for (i = 0; i < nrthreads; i++) {
+               rim_thread_ids[i] = i;
+               pthread_create(&rim_threads[i], &attr, rim_fn, &rim_thread_ids[i]);
+               set_pthread_cpu(rim_threads[i], start_cpu + i);
+       }
+
+       pthread_create(&mem_snapshot_thread, &attr, mem_snapshot_fn, map1);
+       set_pthread_cpu(mem_snapshot_thread, start_cpu + i);
+
+
+       pthread_join(mem_snapshot_thread, NULL);
+       for (i = 0; i < nrthreads; i++) {
+               pthread_join(rim_threads[i], NULL);
+       }
+
+       if (!timeout) {
+               time(&now);
+               printf("=================================\n");
+               printf("      Data Corruption Detected\n");
+               printf("      %s", ctime(&now));
+               printf("      See logfiles in %s\n", logdir);
+               printf("=================================\n");
+               return 1;
+       }
+       return 0;
+}