]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Jan 2018 19:41:09 +0000 (11:41 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Jan 2018 19:41:09 +0000 (11:41 -0800)
Pull KVM fixes from Radim Krčmář:
 "ARM:
   - fix incorrect huge page mappings on systems using the contiguous
     hint for hugetlbfs
   - support alternative GICv4 init sequence
   - correctly implement the ARM SMCC for HVC and SMC handling

  PPC:
   - add KVM IOCTL for reporting vulnerability and workaround status

  s390:
   - provide userspace interface for branch prediction changes in
     firmware

  x86:
   - use correct macros for bits"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: s390: wire up bpb feature
  KVM: PPC: Book3S: Provide information about hardware/firmware CVE workarounds
  KVM/x86: Fix wrong macro references of X86_CR0_PG_BIT and X86_CR4_PAE_BIT in kvm_valid_sregs()
  arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  KVM: arm64: Fix GICv4 init when called from vgic_its_create
  KVM: arm/arm64: Check pagesize when allocating a hugepage at Stage 2

195 files changed:
MAINTAINERS
arch/arm/boot/dts/da850-lcdk.dts
arch/arm/boot/dts/kirkwood-openblocks_a7.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/configs/sunxi_defconfig
arch/arm/net/bpf_jit_32.c
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
arch/arm64/net/bpf_jit_comp.c
arch/ia64/include/asm/atomic.h
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/ar7/platform.c
arch/mips/ath25/devices.c
arch/mips/kernel/mips-cm.c
arch/mips/lib/Makefile
arch/mips/lib/libgcc.h
arch/mips/lib/multi3.c [new file with mode: 0644]
arch/mips/mm/uasm-micromips.c
arch/mips/ralink/timer.c
arch/mips/rb532/Makefile
arch/mips/rb532/devices.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/hvcall.h
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/xmon/xmon.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/intel/rapl.c
arch/x86/include/asm/apic.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/mem_encrypt.h
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/vector.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/intel_rdt.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/head64.c
arch/x86/kernel/idt.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/setup.c
arch/x86/kernel/tsc.c
arch/x86/mm/fault.c
arch/x86/mm/kasan_init_64.c
arch/x86/mm/mem_encrypt.c
arch/x86/mm/mem_encrypt_boot.S
drivers/ata/libata-core.c
drivers/bcma/Kconfig
drivers/gpio/gpio-mmio.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mcp77.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmmcp77.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c
drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-core-smbus.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/input/misc/twl4030-vibra.c
drivers/input/misc/twl6040-vibra.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/synaptics.c
drivers/input/rmi4/rmi_driver.c
drivers/input/touchscreen/88pm860x-ts.c
drivers/input/touchscreen/of_touchscreen.c
drivers/md/dm-crypt.c
drivers/md/dm-integrity.c
drivers/md/dm-thin-metadata.c
drivers/md/persistent-data/dm-btree.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/fs_enet.h
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/fm10k/fm10k_pci.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/uar.c
drivers/net/ethernet/mellanox/mlx5/core/vport.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ppp/ppp_generic.c
drivers/net/tun.c
drivers/net/usb/lan78xx.c
drivers/net/usb/r8152.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
drivers/net/wireless/mac80211_hwsim.c
drivers/nvme/host/pci.c
drivers/phy/phy-core.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/ssb/Kconfig
fs/proc/array.c
include/linux/compiler-gcc.h
include/linux/delayacct.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/netlink.h
include/linux/ptr_ring.h
include/linux/vermagic.h
include/net/arp.h
include/net/cfg80211.h
include/net/sch_generic.h
include/net/tls.h
include/uapi/linux/openvswitch.h
kernel/bpf/arraymap.c
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/delayacct.c
kernel/futex.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_common.h
kernel/sched/core.c
kernel/time/timer.c
kernel/trace/Kconfig
kernel/trace/ring_buffer.c
kernel/trace/trace_events.c
kernel/workqueue.c
mm/memory.c
mm/page_owner.c
net/9p/trans_xen.c
net/can/af_can.c
net/core/filter.c
net/core/flow_dissector.c
net/core/neighbour.c
net/ipv4/arp.c
net/ipv4/esp4.c
net/ipv4/esp4_offload.c
net/ipv4/route.c
net/ipv6/esp6.c
net/ipv6/esp6_offload.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/key/af_key.c
net/netlink/af_netlink.c
net/openvswitch/flow_netlink.c
net/sched/cls_bpf.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sched/sch_ingress.c
net/sctp/ipv6.c
net/sctp/outqueue.c
net/sctp/socket.c
net/tipc/node.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/wext-compat.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
scripts/Makefile.build
scripts/decodecode
scripts/gdb/linux/tasks.py
sound/core/pcm_lib.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_clientmgr.h
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
tools/objtool/elf.c
tools/testing/selftests/bpf/test_verifier.c

index 18994806e441f86f2415e417458a02dc111fa6d2..e3581413420c61aa95cb04939576c84f3a2a3782 100644 (file)
@@ -9085,6 +9085,7 @@ F:        drivers/usb/image/microtek.*
 
 MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
+M:     James Hogan <jhogan@kernel.org>
 L:     linux-mips@linux-mips.org
 W:     http://www.linux-mips.org/
 T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
index eed89e659143a878c9a62159c52c834340c3a61b..a1f4d6d5a569bbb740b6a5d27f7232155853ec4a 100644 (file)
@@ -293,12 +293,12 @@ partition@0 {
                                        label = "u-boot env";
                                        reg = <0 0x020000>;
                                };
-                               partition@0x020000 {
+                               partition@20000 {
                                        /* The LCDK defaults to booting from this partition */
                                        label = "u-boot";
                                        reg = <0x020000 0x080000>;
                                };
-                               partition@0x0a0000 {
+                               partition@a0000 {
                                        label = "free space";
                                        reg = <0x0a0000 0>;
                                };
index cf2f5240e176d0b1d60f578db6028f143bfea97c..27cc913ca0f569e840762fc600034247819a1937 100644 (file)
@@ -53,7 +53,8 @@ s24c02: s24c02@50 {
                };
 
                pinctrl: pin-controller@10000 {
-                       pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>;
+                       pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header
+                                    &pmx_gpio_header_gpo>;
                        pinctrl-names = "default";
 
                        pmx_uart0: pmx-uart0 {
@@ -85,11 +86,16 @@ pmx_dip_switches: pmx-dip-switches {
                         * ground.
                         */
                        pmx_gpio_header: pmx-gpio-header {
-                               marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28",
+                               marvell,pins = "mpp17", "mpp29", "mpp28",
                                               "mpp35", "mpp34", "mpp40";
                                marvell,function = "gpio";
                        };
 
+                       pmx_gpio_header_gpo: pxm-gpio-header-gpo {
+                               marvell,pins = "mpp7";
+                               marvell,function = "gpo";
+                       };
+
                        pmx_gpio_init: pmx-init {
                                marvell,pins = "mpp38";
                                marvell,function = "gpio";
index 5840f5c75c3b388d47242c53aa0c0f7fbe3e3a68..4f2f2eea07552db91e67b5fb6fd9e2bd469b7905 100644 (file)
@@ -1104,7 +1104,7 @@ be1_out: port@1 {
 
                                        be1_out_tcon0: endpoint@0 {
                                                reg = <0>;
-                                               remote-endpoint = <&tcon1_in_be0>;
+                                               remote-endpoint = <&tcon0_in_be1>;
                                        };
 
                                        be1_out_tcon1: endpoint@1 {
index 59655e42e4b09a75edc0b285e2c18fd4926e21aa..bd0cd3204273d3fc4434ce2ac7ac2cf92deb4ef4 100644 (file)
@@ -1354,7 +1354,7 @@ be1_out: port@1 {
 
                                        be1_out_tcon0: endpoint@0 {
                                                reg = <0>;
-                                               remote-endpoint = <&tcon1_in_be0>;
+                                               remote-endpoint = <&tcon0_in_be1>;
                                        };
 
                                        be1_out_tcon1: endpoint@1 {
index 5caaf971fb500c8265bfd75350578cf3071ca90b..df433abfcb0284ec5d9df989f1f30957ba86f6fe 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=8
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_CMA=y
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CPU_FREQ=y
@@ -33,6 +34,7 @@ CONFIG_CAN_SUN4I=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_AHCI_SUNXI=y
index c199990e12b620fe40f34215abf2d577e6f90c70..323a4df59a6c0ec6657b42b714b161a6d3729cca 100644 (file)
 
 int bpf_jit_enable __read_mostly;
 
+/*
+ * eBPF prog stack layout:
+ *
+ *                         high
+ * original ARM_SP =>     +-----+
+ *                        |     | callee saved registers
+ *                        +-----+ <= (BPF_FP + SCRATCH_SIZE)
+ *                        | ... | eBPF JIT scratch space
+ * eBPF fp register =>    +-----+
+ *   (BPF_FP)             | ... | eBPF prog stack
+ *                        +-----+
+ *                        |RSVD | JIT scratchpad
+ * current ARM_SP =>      +-----+ <= (BPF_FP - STACK_SIZE + SCRATCH_SIZE)
+ *                        |     |
+ *                        | ... | Function call stack
+ *                        |     |
+ *                        +-----+
+ *                          low
+ *
+ * The callee saved registers depends on whether frame pointers are enabled.
+ * With frame pointers (to be compliant with the ABI):
+ *
+ *                                high
+ * original ARM_SP =>     +------------------+ \
+ *                        |        pc        | |
+ * current ARM_FP =>      +------------------+ } callee saved registers
+ *                        |r4-r8,r10,fp,ip,lr| |
+ *                        +------------------+ /
+ *                                low
+ *
+ * Without frame pointers:
+ *
+ *                                high
+ * original ARM_SP =>     +------------------+
+ *                        | r4-r8,r10,fp,lr  | callee saved registers
+ * current ARM_FP =>      +------------------+
+ *                                low
+ *
+ * When popping registers off the stack at the end of a BPF function, we
+ * reference them via the current ARM_FP register.
+ */
+#define CALLEE_MASK    (1 << ARM_R4 | 1 << ARM_R5 | 1 << ARM_R6 | \
+                        1 << ARM_R7 | 1 << ARM_R8 | 1 << ARM_R10 | \
+                        1 << ARM_FP)
+#define CALLEE_PUSH_MASK (CALLEE_MASK | 1 << ARM_LR)
+#define CALLEE_POP_MASK  (CALLEE_MASK | 1 << ARM_PC)
+
 #define STACK_OFFSET(k)        (k)
 #define TMP_REG_1      (MAX_BPF_JIT_REG + 0)   /* TEMP Register 1 */
 #define TMP_REG_2      (MAX_BPF_JIT_REG + 1)   /* TEMP Register 2 */
 #define TCALL_CNT      (MAX_BPF_JIT_REG + 2)   /* Tail Call Count */
 
-/* Flags used for JIT optimization */
-#define SEEN_CALL      (1 << 0)
-
 #define FLAG_IMM_OVERFLOW      (1 << 0)
 
 /*
@@ -95,7 +139,6 @@ static const u8 bpf2a32[][2] = {
  * idx                 :       index of current last JITed instruction.
  * prologue_bytes      :       bytes used in prologue.
  * epilogue_offset     :       offset of epilogue starting.
- * seen                        :       bit mask used for JIT optimization.
  * offsets             :       array of eBPF instruction offsets in
  *                             JITed code.
  * target              :       final JITed code.
@@ -110,7 +153,6 @@ struct jit_ctx {
        unsigned int idx;
        unsigned int prologue_bytes;
        unsigned int epilogue_offset;
-       u32 seen;
        u32 flags;
        u32 *offsets;
        u32 *target;
@@ -179,8 +221,13 @@ static void jit_fill_hole(void *area, unsigned int size)
                *ptr++ = __opcode_to_mem_arm(ARM_INST_UDF);
 }
 
-/* Stack must be multiples of 16 Bytes */
-#define STACK_ALIGN(sz) (((sz) + 3) & ~3)
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+/* EABI requires the stack to be aligned to 64-bit boundaries */
+#define STACK_ALIGNMENT        8
+#else
+/* Stack must be aligned to 32-bit boundaries */
+#define STACK_ALIGNMENT        4
+#endif
 
 /* Stack space for BPF_REG_2, BPF_REG_3, BPF_REG_4,
  * BPF_REG_5, BPF_REG_7, BPF_REG_8, BPF_REG_9,
@@ -194,7 +241,7 @@ static void jit_fill_hole(void *area, unsigned int size)
         + SCRATCH_SIZE + \
         + 4 /* extra for skb_copy_bits buffer */)
 
-#define STACK_SIZE STACK_ALIGN(_STACK_SIZE)
+#define STACK_SIZE ALIGN(_STACK_SIZE, STACK_ALIGNMENT)
 
 /* Get the offset of eBPF REGISTERs stored on scratch space. */
 #define STACK_VAR(off) (STACK_SIZE-off-4)
@@ -285,16 +332,19 @@ static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx)
                emit_mov_i_no8m(rd, val, ctx);
 }
 
-static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
+static void emit_bx_r(u8 tgt_reg, struct jit_ctx *ctx)
 {
-       ctx->seen |= SEEN_CALL;
-#if __LINUX_ARM_ARCH__ < 5
-       emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
-
        if (elf_hwcap & HWCAP_THUMB)
                emit(ARM_BX(tgt_reg), ctx);
        else
                emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
+}
+
+static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 5
+       emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
+       emit_bx_r(tgt_reg, ctx);
 #else
        emit(ARM_BLX_R(tgt_reg), ctx);
 #endif
@@ -354,7 +404,6 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
        }
 
        /* Call appropriate function */
-       ctx->seen |= SEEN_CALL;
        emit_mov_i(ARM_IP, op == BPF_DIV ?
                   (u32)jit_udiv32 : (u32)jit_mod32, ctx);
        emit_blx_r(ARM_IP, ctx);
@@ -620,8 +669,6 @@ static inline void emit_a32_lsh_r64(const u8 dst[], const u8 src[], bool dstk,
        /* Do LSH operation */
        emit(ARM_SUB_I(ARM_IP, rt, 32), ctx);
        emit(ARM_RSB_I(tmp2[0], rt, 32), ctx);
-       /* As we are using ARM_LR */
-       ctx->seen |= SEEN_CALL;
        emit(ARM_MOV_SR(ARM_LR, rm, SRTYPE_ASL, rt), ctx);
        emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd, SRTYPE_ASL, ARM_IP), ctx);
        emit(ARM_ORR_SR(ARM_IP, ARM_LR, rd, SRTYPE_LSR, tmp2[0]), ctx);
@@ -656,8 +703,6 @@ static inline void emit_a32_arsh_r64(const u8 dst[], const u8 src[], bool dstk,
        /* Do the ARSH operation */
        emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
        emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
-       /* As we are using ARM_LR */
-       ctx->seen |= SEEN_CALL;
        emit(ARM_MOV_SR(ARM_LR, rd, SRTYPE_LSR, rt), ctx);
        emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_ASL, ARM_IP), ctx);
        _emit(ARM_COND_MI, ARM_B(0), ctx);
@@ -692,8 +737,6 @@ static inline void emit_a32_lsr_r64(const u8 dst[], const u8 src[], bool dstk,
        /* Do LSH operation */
        emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
        emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
-       /* As we are using ARM_LR */
-       ctx->seen |= SEEN_CALL;
        emit(ARM_MOV_SR(ARM_LR, rd, SRTYPE_LSR, rt), ctx);
        emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_ASL, ARM_IP), ctx);
        emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_LSR, tmp2[0]), ctx);
@@ -828,8 +871,6 @@ static inline void emit_a32_mul_r64(const u8 dst[], const u8 src[], bool dstk,
        /* Do Multiplication */
        emit(ARM_MUL(ARM_IP, rd, rn), ctx);
        emit(ARM_MUL(ARM_LR, rm, rt), ctx);
-       /* As we are using ARM_LR */
-       ctx->seen |= SEEN_CALL;
        emit(ARM_ADD_R(ARM_LR, ARM_IP, ARM_LR), ctx);
 
        emit(ARM_UMULL(ARM_IP, rm, rd, rt), ctx);
@@ -872,33 +913,53 @@ static inline void emit_str_r(const u8 dst, const u8 src, bool dstk,
 }
 
 /* dst = *(size*)(src + off) */
-static inline void emit_ldx_r(const u8 dst, const u8 src, bool dstk,
-                             const s32 off, struct jit_ctx *ctx, const u8 sz){
+static inline void emit_ldx_r(const u8 dst[], const u8 src, bool dstk,
+                             s32 off, struct jit_ctx *ctx, const u8 sz){
        const u8 *tmp = bpf2a32[TMP_REG_1];
-       u8 rd = dstk ? tmp[1] : dst;
+       const u8 *rd = dstk ? tmp : dst;
        u8 rm = src;
+       s32 off_max;
 
-       if (off) {
+       if (sz == BPF_H)
+               off_max = 0xff;
+       else
+               off_max = 0xfff;
+
+       if (off < 0 || off > off_max) {
                emit_a32_mov_i(tmp[0], off, false, ctx);
                emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
                rm = tmp[0];
+               off = 0;
+       } else if (rd[1] == rm) {
+               emit(ARM_MOV_R(tmp[0], rm), ctx);
+               rm = tmp[0];
        }
        switch (sz) {
-       case BPF_W:
-               /* Load a Word */
-               emit(ARM_LDR_I(rd, rm, 0), ctx);
+       case BPF_B:
+               /* Load a Byte */
+               emit(ARM_LDRB_I(rd[1], rm, off), ctx);
+               emit_a32_mov_i(dst[0], 0, dstk, ctx);
                break;
        case BPF_H:
                /* Load a HalfWord */
-               emit(ARM_LDRH_I(rd, rm, 0), ctx);
+               emit(ARM_LDRH_I(rd[1], rm, off), ctx);
+               emit_a32_mov_i(dst[0], 0, dstk, ctx);
                break;
-       case BPF_B:
-               /* Load a Byte */
-               emit(ARM_LDRB_I(rd, rm, 0), ctx);
+       case BPF_W:
+               /* Load a Word */
+               emit(ARM_LDR_I(rd[1], rm, off), ctx);
+               emit_a32_mov_i(dst[0], 0, dstk, ctx);
+               break;
+       case BPF_DW:
+               /* Load a Double Word */
+               emit(ARM_LDR_I(rd[1], rm, off), ctx);
+               emit(ARM_LDR_I(rd[0], rm, off + 4), ctx);
                break;
        }
        if (dstk)
-               emit(ARM_STR_I(rd, ARM_SP, STACK_VAR(dst)), ctx);
+               emit(ARM_STR_I(rd[1], ARM_SP, STACK_VAR(dst[1])), ctx);
+       if (dstk && sz == BPF_DW)
+               emit(ARM_STR_I(rd[0], ARM_SP, STACK_VAR(dst[0])), ctx);
 }
 
 /* Arithmatic Operation */
@@ -906,7 +967,6 @@ static inline void emit_ar_r(const u8 rd, const u8 rt, const u8 rm,
                             const u8 rn, struct jit_ctx *ctx, u8 op) {
        switch (op) {
        case BPF_JSET:
-               ctx->seen |= SEEN_CALL;
                emit(ARM_AND_R(ARM_IP, rt, rn), ctx);
                emit(ARM_AND_R(ARM_LR, rd, rm), ctx);
                emit(ARM_ORRS_R(ARM_IP, ARM_LR, ARM_IP), ctx);
@@ -945,7 +1005,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
        const u8 *tcc = bpf2a32[TCALL_CNT];
        const int idx0 = ctx->idx;
 #define cur_offset (ctx->idx - idx0)
-#define jmp_offset (out_offset - (cur_offset))
+#define jmp_offset (out_offset - (cur_offset) - 2)
        u32 off, lo, hi;
 
        /* if (index >= array->map.max_entries)
@@ -956,7 +1016,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
        emit_a32_mov_i(tmp[1], off, false, ctx);
        emit(ARM_LDR_I(tmp2[1], ARM_SP, STACK_VAR(r2[1])), ctx);
        emit(ARM_LDR_R(tmp[1], tmp2[1], tmp[1]), ctx);
-       /* index (64 bit) */
+       /* index is 32-bit for arrays */
        emit(ARM_LDR_I(tmp2[1], ARM_SP, STACK_VAR(r3[1])), ctx);
        /* index >= array->map.max_entries */
        emit(ARM_CMP_R(tmp2[1], tmp[1]), ctx);
@@ -997,7 +1057,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
        emit_a32_mov_i(tmp2[1], off, false, ctx);
        emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx);
        emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx);
-       emit(ARM_BX(tmp[1]), ctx);
+       emit_bx_r(tmp[1], ctx);
 
        /* out: */
        if (out_offset == -1)
@@ -1070,54 +1130,22 @@ static void build_prologue(struct jit_ctx *ctx)
        const u8 r2 = bpf2a32[BPF_REG_1][1];
        const u8 r3 = bpf2a32[BPF_REG_1][0];
        const u8 r4 = bpf2a32[BPF_REG_6][1];
-       const u8 r5 = bpf2a32[BPF_REG_6][0];
-       const u8 r6 = bpf2a32[TMP_REG_1][1];
-       const u8 r7 = bpf2a32[TMP_REG_1][0];
-       const u8 r8 = bpf2a32[TMP_REG_2][1];
-       const u8 r10 = bpf2a32[TMP_REG_2][0];
        const u8 fplo = bpf2a32[BPF_REG_FP][1];
        const u8 fphi = bpf2a32[BPF_REG_FP][0];
-       const u8 sp = ARM_SP;
        const u8 *tcc = bpf2a32[TCALL_CNT];
 
-       u16 reg_set = 0;
-
-       /*
-        * eBPF prog stack layout
-        *
-        *                         high
-        * original ARM_SP =>     +-----+ eBPF prologue
-        *                        |FP/LR|
-        * current ARM_FP =>      +-----+
-        *                        | ... | callee saved registers
-        * eBPF fp register =>    +-----+ <= (BPF_FP)
-        *                        | ... | eBPF JIT scratch space
-        *                        |     | eBPF prog stack
-        *                        +-----+
-        *                        |RSVD | JIT scratchpad
-        * current A64_SP =>      +-----+ <= (BPF_FP - STACK_SIZE)
-        *                        |     |
-        *                        | ... | Function call stack
-        *                        |     |
-        *                        +-----+
-        *                          low
-        */
-
        /* Save callee saved registers. */
-       reg_set |= (1<<r4) | (1<<r5) | (1<<r6) | (1<<r7) | (1<<r8) | (1<<r10);
 #ifdef CONFIG_FRAME_POINTER
-       reg_set |= (1<<ARM_FP) | (1<<ARM_IP) | (1<<ARM_LR) | (1<<ARM_PC);
-       emit(ARM_MOV_R(ARM_IP, sp), ctx);
+       u16 reg_set = CALLEE_PUSH_MASK | 1 << ARM_IP | 1 << ARM_PC;
+       emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
        emit(ARM_PUSH(reg_set), ctx);
        emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
 #else
-       /* Check if call instruction exists in BPF body */
-       if (ctx->seen & SEEN_CALL)
-               reg_set |= (1<<ARM_LR);
-       emit(ARM_PUSH(reg_set), ctx);
+       emit(ARM_PUSH(CALLEE_PUSH_MASK), ctx);
+       emit(ARM_MOV_R(ARM_FP, ARM_SP), ctx);
 #endif
        /* Save frame pointer for later */
-       emit(ARM_SUB_I(ARM_IP, sp, SCRATCH_SIZE), ctx);
+       emit(ARM_SUB_I(ARM_IP, ARM_SP, SCRATCH_SIZE), ctx);
 
        ctx->stack_size = imm8m(STACK_SIZE);
 
@@ -1140,33 +1168,19 @@ static void build_prologue(struct jit_ctx *ctx)
        /* end of prologue */
 }
 
+/* restore callee saved registers. */
 static void build_epilogue(struct jit_ctx *ctx)
 {
-       const u8 r4 = bpf2a32[BPF_REG_6][1];
-       const u8 r5 = bpf2a32[BPF_REG_6][0];
-       const u8 r6 = bpf2a32[TMP_REG_1][1];
-       const u8 r7 = bpf2a32[TMP_REG_1][0];
-       const u8 r8 = bpf2a32[TMP_REG_2][1];
-       const u8 r10 = bpf2a32[TMP_REG_2][0];
-       u16 reg_set = 0;
-
-       /* unwind function call stack */
-       emit(ARM_ADD_I(ARM_SP, ARM_SP, ctx->stack_size), ctx);
-
-       /* restore callee saved registers. */
-       reg_set |= (1<<r4) | (1<<r5) | (1<<r6) | (1<<r7) | (1<<r8) | (1<<r10);
 #ifdef CONFIG_FRAME_POINTER
-       /* the first instruction of the prologue was: mov ip, sp */
-       reg_set |= (1<<ARM_FP) | (1<<ARM_SP) | (1<<ARM_PC);
+       /* When using frame pointers, some additional registers need to
+        * be loaded. */
+       u16 reg_set = CALLEE_POP_MASK | 1 << ARM_SP;
+       emit(ARM_SUB_I(ARM_SP, ARM_FP, hweight16(reg_set) * 4), ctx);
        emit(ARM_LDM(ARM_SP, reg_set), ctx);
 #else
-       if (ctx->seen & SEEN_CALL)
-               reg_set |= (1<<ARM_PC);
        /* Restore callee saved registers. */
-       emit(ARM_POP(reg_set), ctx);
-       /* Return back to the callee function */
-       if (!(ctx->seen & SEEN_CALL))
-               emit(ARM_BX(ARM_LR), ctx);
+       emit(ARM_MOV_R(ARM_SP, ARM_FP), ctx);
+       emit(ARM_POP(CALLEE_POP_MASK), ctx);
 #endif
 }
 
@@ -1394,8 +1408,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                        emit_rev32(rt, rt, ctx);
                        goto emit_bswap_uxt;
                case 64:
-                       /* Because of the usage of ARM_LR */
-                       ctx->seen |= SEEN_CALL;
                        emit_rev32(ARM_LR, rt, ctx);
                        emit_rev32(rt, rd, ctx);
                        emit(ARM_MOV_R(rd, ARM_LR), ctx);
@@ -1448,22 +1460,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                rn = sstk ? tmp2[1] : src_lo;
                if (sstk)
                        emit(ARM_LDR_I(rn, ARM_SP, STACK_VAR(src_lo)), ctx);
-               switch (BPF_SIZE(code)) {
-               case BPF_W:
-                       /* Load a Word */
-               case BPF_H:
-                       /* Load a Half-Word */
-               case BPF_B:
-                       /* Load a Byte */
-                       emit_ldx_r(dst_lo, rn, dstk, off, ctx, BPF_SIZE(code));
-                       emit_a32_mov_i(dst_hi, 0, dstk, ctx);
-                       break;
-               case BPF_DW:
-                       /* Load a double word */
-                       emit_ldx_r(dst_lo, rn, dstk, off, ctx, BPF_W);
-                       emit_ldx_r(dst_hi, rn, dstk, off+4, ctx, BPF_W);
-                       break;
-               }
+               emit_ldx_r(dst, rn, dstk, off, ctx, BPF_SIZE(code));
                break;
        /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */
        case BPF_LD | BPF_ABS | BPF_W:
index 7c9bdc7ab50bcfd12764d7206bb0fb75e30ec8c1..9db19314c60cda7de981992f55f2e623b92fcd00 100644 (file)
@@ -66,6 +66,7 @@ pmu {
                                     <&cpu1>,
                                     <&cpu2>,
                                     <&cpu3>;
+               interrupt-parent = <&intc>;
        };
 
        psci {
index e3b64d03fbd82844aaf65fc862e62d15af042133..9c7724e82aff20b14cc19da42c76fef92aa90723 100644 (file)
@@ -63,8 +63,10 @@ config-space@f2000000 {
                        cpm_ethernet: ethernet@0 {
                                compatible = "marvell,armada-7k-pp22";
                                reg = <0x0 0x100000>, <0x129000 0xb000>;
-                               clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>, <&cpm_clk 1 5>;
-                               clock-names = "pp_clk", "gop_clk", "mg_clk";
+                               clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>,
+                                        <&cpm_clk 1 5>, <&cpm_clk 1 18>;
+                               clock-names = "pp_clk", "gop_clk",
+                                             "mg_clk","axi_clk";
                                marvell,system-controller = <&cpm_syscon0>;
                                status = "disabled";
                                dma-coherent;
@@ -155,7 +157,8 @@ cpm_mdio: mdio@12a200 {
                                #size-cells = <0>;
                                compatible = "marvell,orion-mdio";
                                reg = <0x12a200 0x10>;
-                               clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>;
+                               clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>,
+                                        <&cpm_clk 1 6>, <&cpm_clk 1 18>;
                                status = "disabled";
                        };
 
@@ -338,8 +341,8 @@ cpm_sdhci0: sdhci@780000 {
                                compatible = "marvell,armada-cp110-sdhci";
                                reg = <0x780000 0x300>;
                                interrupts = <ICU_GRP_NSR 27 IRQ_TYPE_LEVEL_HIGH>;
-                               clock-names = "core";
-                               clocks = <&cpm_clk 1 4>;
+                               clock-names = "core","axi";
+                               clocks = <&cpm_clk 1 4>, <&cpm_clk 1 18>;
                                dma-coherent;
                                status = "disabled";
                        };
index 0d51096c69f802e68cbf1e6392e26e0a553138ec..87ac68b2cf37fab1dc1c68b5a7112af7524da083 100644 (file)
@@ -63,8 +63,10 @@ config-space@f4000000 {
                        cps_ethernet: ethernet@0 {
                                compatible = "marvell,armada-7k-pp22";
                                reg = <0x0 0x100000>, <0x129000 0xb000>;
-                               clocks = <&cps_clk 1 3>, <&cps_clk 1 9>, <&cps_clk 1 5>;
-                               clock-names = "pp_clk", "gop_clk", "mg_clk";
+                               clocks = <&cps_clk 1 3>, <&cps_clk 1 9>,
+                                        <&cps_clk 1 5>, <&cps_clk 1 18>;
+                               clock-names = "pp_clk", "gop_clk",
+                                             "mg_clk", "axi_clk";
                                marvell,system-controller = <&cps_syscon0>;
                                status = "disabled";
                                dma-coherent;
@@ -155,7 +157,8 @@ cps_mdio: mdio@12a200 {
                                #size-cells = <0>;
                                compatible = "marvell,orion-mdio";
                                reg = <0x12a200 0x10>;
-                               clocks = <&cps_clk 1 9>, <&cps_clk 1 5>;
+                               clocks = <&cps_clk 1 9>, <&cps_clk 1 5>,
+                                        <&cps_clk 1 6>, <&cps_clk 1 18>;
                                status = "disabled";
                        };
 
index ba38d403abb2fc92d8ea6ae9a6c3c38e70979062..bb32f7f6dd0f967fd1435ad539d922b69650fb2b 100644 (file)
@@ -148,7 +148,8 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
 /* Stack must be multiples of 16B */
 #define STACK_ALIGN(sz) (((sz) + 15) & ~15)
 
-#define PROLOGUE_OFFSET 8
+/* Tail call offset to jump into */
+#define PROLOGUE_OFFSET 7
 
 static int build_prologue(struct jit_ctx *ctx)
 {
@@ -200,19 +201,19 @@ static int build_prologue(struct jit_ctx *ctx)
        /* Initialize tail_call_cnt */
        emit(A64_MOVZ(1, tcc, 0, 0), ctx);
 
-       /* 4 byte extra for skb_copy_bits buffer */
-       ctx->stack_size = prog->aux->stack_depth + 4;
-       ctx->stack_size = STACK_ALIGN(ctx->stack_size);
-
-       /* Set up function call stack */
-       emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
-
        cur_offset = ctx->idx - idx0;
        if (cur_offset != PROLOGUE_OFFSET) {
                pr_err_once("PROLOGUE_OFFSET = %d, expected %d!\n",
                            cur_offset, PROLOGUE_OFFSET);
                return -1;
        }
+
+       /* 4 byte extra for skb_copy_bits buffer */
+       ctx->stack_size = prog->aux->stack_depth + 4;
+       ctx->stack_size = STACK_ALIGN(ctx->stack_size);
+
+       /* Set up function call stack */
+       emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
        return 0;
 }
 
@@ -260,11 +261,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
        emit(A64_LDR64(prg, tmp, prg), ctx);
        emit(A64_CBZ(1, prg, jmp_offset), ctx);
 
-       /* goto *(prog->bpf_func + prologue_size); */
+       /* goto *(prog->bpf_func + prologue_offset); */
        off = offsetof(struct bpf_prog, bpf_func);
        emit_a64_mov_i64(tmp, off, ctx);
        emit(A64_LDR64(tmp, prg, tmp), ctx);
        emit(A64_ADD_I(1, tmp, tmp, sizeof(u32) * PROLOGUE_OFFSET), ctx);
+       emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
        emit(A64_BR(tmp), ctx);
 
        /* out: */
index 28e02c99be6d72efca8128d8a11011e20bd89936..762eeb0fcc1dcaec27a4dff140274113a2c31fbf 100644 (file)
@@ -65,29 +65,30 @@ ia64_atomic_fetch_##op (int i, atomic_t *v)                         \
 ATOMIC_OPS(add, +)
 ATOMIC_OPS(sub, -)
 
-#define atomic_add_return(i,v)                                         \
+#ifdef __OPTIMIZE__
+#define __ia64_atomic_const(i) __builtin_constant_p(i) ?               \
+               ((i) == 1 || (i) == 4 || (i) == 8 || (i) == 16 ||       \
+                (i) == -1 || (i) == -4 || (i) == -8 || (i) == -16) : 0
+
+#define atomic_add_return(i, v)                                                \
 ({                                                                     \
-       int __ia64_aar_i = (i);                                         \
-       (__builtin_constant_p(i)                                        \
-        && (   (__ia64_aar_i ==  1) || (__ia64_aar_i ==   4)           \
-            || (__ia64_aar_i ==  8) || (__ia64_aar_i ==  16)           \
-            || (__ia64_aar_i == -1) || (__ia64_aar_i ==  -4)           \
-            || (__ia64_aar_i == -8) || (__ia64_aar_i == -16)))         \
-               ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter)       \
-               : ia64_atomic_add(__ia64_aar_i, v);                     \
+       int __i = (i);                                                  \
+       static const int __ia64_atomic_p = __ia64_atomic_const(i);      \
+       __ia64_atomic_p ? ia64_fetch_and_add(__i, &(v)->counter) :      \
+                               ia64_atomic_add(__i, v);                \
 })
 
-#define atomic_sub_return(i,v)                                         \
+#define atomic_sub_return(i, v)                                                \
 ({                                                                     \
-       int __ia64_asr_i = (i);                                         \
-       (__builtin_constant_p(i)                                        \
-        && (   (__ia64_asr_i ==   1) || (__ia64_asr_i ==   4)          \
-            || (__ia64_asr_i ==   8) || (__ia64_asr_i ==  16)          \
-            || (__ia64_asr_i ==  -1) || (__ia64_asr_i ==  -4)          \
-            || (__ia64_asr_i ==  -8) || (__ia64_asr_i == -16)))        \
-               ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter)      \
-               : ia64_atomic_sub(__ia64_asr_i, v);                     \
+       int __i = (i);                                                  \
+       static const int __ia64_atomic_p = __ia64_atomic_const(i);      \
+       __ia64_atomic_p ? ia64_fetch_and_add(-__i, &(v)->counter) :     \
+                               ia64_atomic_sub(__i, v);                \
 })
+#else
+#define atomic_add_return(i, v)        ia64_atomic_add(i, v)
+#define atomic_sub_return(i, v)        ia64_atomic_sub(i, v)
+#endif
 
 #define atomic_fetch_add(i,v)                                          \
 ({                                                                     \
index 350a990fc7196d3883a429e89e64dbb046c5c0b0..8e0b3702f1c082c8d38d6de568ce5e71370ac284 100644 (file)
@@ -259,6 +259,7 @@ config BCM47XX
        select LEDS_GPIO_REGISTER
        select BCM47XX_NVRAM
        select BCM47XX_SPROM
+       select BCM47XX_SSB if !BCM47XX_BCMA
        help
         Support for BCM47XX based boards
 
@@ -389,6 +390,7 @@ config LANTIQ
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_MIPS16
        select SYS_SUPPORTS_MULTITHREADING
+       select SYS_SUPPORTS_VPE_LOADER
        select SYS_HAS_EARLY_PRINTK
        select GPIOLIB
        select SWAP_IO_SPACE
@@ -516,6 +518,7 @@ config MIPS_MALTA
        select SYS_SUPPORTS_MIPS16
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_SMARTMIPS
+       select SYS_SUPPORTS_VPE_LOADER
        select SYS_SUPPORTS_ZBOOT
        select SYS_SUPPORTS_RELOCATABLE
        select USE_OF
@@ -2281,9 +2284,16 @@ config MIPSR2_TO_R6_EMULATOR
          The only reason this is a build-time option is to save ~14K from the
          final kernel image.
 
+config SYS_SUPPORTS_VPE_LOADER
+       bool
+       depends on SYS_SUPPORTS_MULTITHREADING
+       help
+         Indicates that the platform supports the VPE loader, and provides
+         physical_memsize.
+
 config MIPS_VPE_LOADER
        bool "VPE loader support."
-       depends on SYS_SUPPORTS_MULTITHREADING && MODULES
+       depends on SYS_SUPPORTS_VPE_LOADER && MODULES
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_IRQ_EI
        select MIPS_MT
index 464af5e025d67d60ba6ab9641da26965f1ac95e6..0749c3724543a7c5f40aa97761703201ed4c7733 100644 (file)
@@ -124,30 +124,36 @@ config SCACHE_DEBUGFS
 
          If unsure, say N.
 
-menuconfig MIPS_CPS_NS16550
+menuconfig MIPS_CPS_NS16550_BOOL
        bool "CPS SMP NS16550 UART output"
        depends on MIPS_CPS
        help
          Output debug information via an ns16550 compatible UART if exceptions
          occur early in the boot process of a secondary core.
 
-if MIPS_CPS_NS16550
+if MIPS_CPS_NS16550_BOOL
+
+config MIPS_CPS_NS16550
+       def_bool MIPS_CPS_NS16550_BASE != 0
 
 config MIPS_CPS_NS16550_BASE
        hex "UART Base Address"
        default 0x1b0003f8 if MIPS_MALTA
+       default 0
        help
          The base address of the ns16550 compatible UART on which to output
          debug information from the early stages of core startup.
 
+         This is only used if non-zero.
+
 config MIPS_CPS_NS16550_SHIFT
        int "UART Register Shift"
-       default 0 if MIPS_MALTA
+       default 0
        help
          The number of bits to shift ns16550 register indices by in order to
          form their addresses. That is, log base 2 of the span between
          adjacent ns16550 registers in the system.
 
-endif # MIPS_CPS_NS16550
+endif # MIPS_CPS_NS16550_BOOL
 
 endmenu
index 4674f1efbe7a597b0387936d79af53b3f62db6b5..e1675c25d5d48cb7c9da6f30983383d54a64251f 100644 (file)
@@ -575,7 +575,7 @@ static int __init ar7_register_uarts(void)
        uart_port.type          = PORT_AR7;
        uart_port.uartclk       = clk_get_rate(bus_clk) / 2;
        uart_port.iotype        = UPIO_MEM32;
-       uart_port.flags         = UPF_FIXED_TYPE;
+       uart_port.flags         = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
        uart_port.regshift      = 2;
 
        uart_port.line          = 0;
index e1156347da53f6cb7516e5f016568028a434b978..301a9028273c3a6bcc93ec8a40952245fcbd2f2e 100644 (file)
@@ -73,6 +73,7 @@ const char *get_system_type(void)
 
 void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
 {
+#ifdef CONFIG_SERIAL_8250_CONSOLE
        struct uart_port s;
 
        memset(&s, 0, sizeof(s));
@@ -85,6 +86,7 @@ void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
        s.uartclk = uartclk;
 
        early_serial_setup(&s);
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
 }
 
 int __init ath25_add_wmac(int nr, u32 base, int irq)
index dd5567b1e30555fd6d4ed07d5101603682b1e8ad..8f5bd04f320a90be3861dd75664fdead350655a3 100644 (file)
@@ -292,7 +292,6 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core,
                                  *this_cpu_ptr(&cm_core_lock_flags));
        } else {
                WARN_ON(cluster != 0);
-               WARN_ON(vp != 0);
                WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL);
 
                /*
index 78c2affeabf8154ae9046eaf10c228c1932b6b99..e84e12655fa8ac5e8af75f231e8b2f52136be042 100644 (file)
@@ -16,4 +16,5 @@ obj-$(CONFIG_CPU_R3000)               += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)       += r3k_dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o multi3.o \
+        ucmpdi2.o
index 28002ed90c2cb5fe336ae385cae47a45a20ab680..199a7f96282f2860b78b663780635b338f7e236b 100644 (file)
@@ -10,10 +10,18 @@ typedef int word_type __attribute__ ((mode (__word__)));
 struct DWstruct {
        int high, low;
 };
+
+struct TWstruct {
+       long long high, low;
+};
 #elif defined(__LITTLE_ENDIAN)
 struct DWstruct {
        int low, high;
 };
+
+struct TWstruct {
+       long long low, high;
+};
 #else
 #error I feel sick.
 #endif
@@ -23,4 +31,13 @@ typedef union {
        long long ll;
 } DWunion;
 
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6)
+typedef int ti_type __attribute__((mode(TI)));
+
+typedef union {
+       struct TWstruct s;
+       ti_type ti;
+} TWunion;
+#endif
+
 #endif /* __ASM_LIBGCC_H */
diff --git a/arch/mips/lib/multi3.c b/arch/mips/lib/multi3.c
new file mode 100644 (file)
index 0000000..111ad47
--- /dev/null
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/export.h>
+
+#include "libgcc.h"
+
+/*
+ * GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
+ * specific case only we'll implement it here.
+ *
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
+ */
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
+
+/* multiply 64-bit values, low 64-bits returned */
+static inline long long notrace dmulu(long long a, long long b)
+{
+       long long res;
+
+       asm ("dmulu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
+       return res;
+}
+
+/* multiply 64-bit unsigned values, high 64-bits of 128-bit result returned */
+static inline long long notrace dmuhu(long long a, long long b)
+{
+       long long res;
+
+       asm ("dmuhu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
+       return res;
+}
+
+/* multiply 128-bit values, low 128-bits returned */
+ti_type notrace __multi3(ti_type a, ti_type b)
+{
+       TWunion res, aa, bb;
+
+       aa.ti = a;
+       bb.ti = b;
+
+       /*
+        * a * b =           (a.lo * b.lo)
+        *         + 2^64  * (a.hi * b.lo + a.lo * b.hi)
+        *        [+ 2^128 * (a.hi * b.hi)]
+        */
+       res.s.low = dmulu(aa.s.low, bb.s.low);
+       res.s.high = dmuhu(aa.s.low, bb.s.low);
+       res.s.high += dmulu(aa.s.high, bb.s.low);
+       res.s.high += dmulu(aa.s.low, bb.s.high);
+
+       return res.ti;
+}
+EXPORT_SYMBOL(__multi3);
+
+#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
index cdb5a191b9d554c165991c9a507c9b8b83d81ac5..9bb6baa45da35943506e371a9c5c6da569459d15 100644 (file)
@@ -40,7 +40,7 @@
 
 #include "uasm.c"
 
-static const struct insn const insn_table_MM[insn_invalid] = {
+static const struct insn insn_table_MM[insn_invalid] = {
        [insn_addu]     = {M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD},
        [insn_addiu]    = {M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM},
        [insn_and]      = {M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD},
index d4469b20d176abb675e168d39e7b02bd511533ea..4f46a4509f79c4b417facbb86006ce15eef9dee1 100644 (file)
@@ -109,9 +109,9 @@ static int rt_timer_probe(struct platform_device *pdev)
        }
 
        rt->irq = platform_get_irq(pdev, 0);
-       if (!rt->irq) {
+       if (rt->irq < 0) {
                dev_err(&pdev->dev, "failed to load irq\n");
-               return -ENOENT;
+               return rt->irq;
        }
 
        rt->membase = devm_ioremap_resource(&pdev->dev, res);
index efdecdb6e3eaefd85a0865c1341b429494df676e..8186afca22340ac504efb9b3a2f912526646aa45 100644 (file)
@@ -2,4 +2,6 @@
 # Makefile for the RB532 board specific parts of the kernel
 #
 
-obj-y   += irq.o time.o setup.o serial.o prom.o gpio.o devices.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE) += serial.o
+
+obj-y   += irq.o time.o setup.o prom.o gpio.o devices.o
index 32ea3e6731d6c8e72d9945ba0c53f347e3bfac77..354d258396ff993f32878941d8c01621b887c8d7 100644 (file)
@@ -310,6 +310,8 @@ static int __init plat_setup_devices(void)
        return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
 }
 
+#ifdef CONFIG_NET
+
 static int __init setup_kmac(char *s)
 {
        printk(KERN_INFO "korina mac = %s\n", s);
@@ -322,4 +324,6 @@ static int __init setup_kmac(char *s)
 
 __setup("kmac=", setup_kmac);
 
+#endif /* CONFIG_NET */
+
 arch_initcall(plat_setup_devices);
index c51e6ce42e7a258d20b76f8331c6a8156ffda4b6..2ed525a44734cfaa62ba7125fab11225c1778a7a 100644 (file)
@@ -166,6 +166,7 @@ config PPC
        select GENERIC_CLOCKEVENTS_BROADCAST    if SMP
        select GENERIC_CMOS_UPDATE
        select GENERIC_CPU_AUTOPROBE
+       select GENERIC_CPU_VULNERABILITIES      if PPC_BOOK3S_64
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
        select GENERIC_SMP_IDLE_THREAD
index f0461618bf7bee95ffd27874e33501bd41ef80a4..eca3f9c689070632492b18e9cc9d55d075024dfe 100644 (file)
 #define PROC_TABLE_GTSE                0x01
 
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
 
 /**
  * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
index 9d213542a48bb91360b7b540ef429473494ebe98..8fd3a70047f1dae91f5e3d11479a178aa64b2ed3 100644 (file)
@@ -242,14 +242,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        unsigned short maj;
        unsigned short min;
 
-       /* We only show online cpus: disable preempt (overzealous, I
-        * knew) to prevent cpu going down. */
-       preempt_disable();
-       if (!cpu_online(cpu_id)) {
-               preempt_enable();
-               return 0;
-       }
-
 #ifdef CONFIG_SMP
        pvr = per_cpu(cpu_pvr, cpu_id);
 #else
@@ -358,9 +350,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
        seq_printf(m, "\n");
 #endif
-
-       preempt_enable();
-
        /* If this is the last cpu, print the summary */
        if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
                show_cpuinfo_summary(m);
index 491be4179ddd989fed6cba1e63963bf47653f4ba..e67413f4a8f0c1fc852c1231f09176c152ed9059 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/memory.h>
 #include <linux/nmi.h>
 
+#include <asm/debugfs.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -901,4 +902,41 @@ void __init setup_rfi_flush(enum l1d_flush_type types, bool enable)
        if (!no_rfi_flush)
                rfi_flush_enable(enable);
 }
+
+#ifdef CONFIG_DEBUG_FS
+static int rfi_flush_set(void *data, u64 val)
+{
+       if (val == 1)
+               rfi_flush_enable(true);
+       else if (val == 0)
+               rfi_flush_enable(false);
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int rfi_flush_get(void *data, u64 *val)
+{
+       *val = rfi_flush ? 1 : 0;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
+
+static __init int rfi_flush_debugfs_init(void)
+{
+       debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
+       return 0;
+}
+device_initcall(rfi_flush_debugfs_init);
+#endif
+
+ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       if (rfi_flush)
+               return sprintf(buf, "Mitigation: RFI Flush\n");
+
+       return sprintf(buf, "Vulnerable\n");
+}
 #endif /* CONFIG_PPC_BOOK3S_64 */
index cab24f549e7cbdc8786c5fa5b7450f0dcda8d87c..0ddc7ac6c5f13df2dd688a0dee38bfb53a2cdf80 100644 (file)
@@ -2344,10 +2344,10 @@ static void dump_one_paca(int cpu)
        DUMP(p, kernel_toc, "lx");
        DUMP(p, kernelbase, "lx");
        DUMP(p, kernel_msr, "lx");
-       DUMP(p, emergency_sp, "p");
+       DUMP(p, emergency_sp, "px");
 #ifdef CONFIG_PPC_BOOK3S_64
-       DUMP(p, nmi_emergency_sp, "p");
-       DUMP(p, mc_emergency_sp, "p");
+       DUMP(p, nmi_emergency_sp, "px");
+       DUMP(p, mc_emergency_sp, "px");
        DUMP(p, in_nmi, "x");
        DUMP(p, in_mce, "x");
        DUMP(p, hmi_event_available, "x");
@@ -2375,17 +2375,21 @@ static void dump_one_paca(int cpu)
        DUMP(p, slb_cache_ptr, "x");
        for (i = 0; i < SLB_CACHE_ENTRIES; i++)
                printf(" slb_cache[%d]:        = 0x%016lx\n", i, p->slb_cache[i]);
+
+       DUMP(p, rfi_flush_fallback_area, "px");
+       DUMP(p, l1d_flush_congruence, "llx");
+       DUMP(p, l1d_flush_sets, "llx");
 #endif
        DUMP(p, dscr_default, "llx");
 #ifdef CONFIG_PPC_BOOK3E
-       DUMP(p, pgd, "p");
-       DUMP(p, kernel_pgd, "p");
-       DUMP(p, tcd_ptr, "p");
-       DUMP(p, mc_kstack, "p");
-       DUMP(p, crit_kstack, "p");
-       DUMP(p, dbg_kstack, "p");
+       DUMP(p, pgd, "px");
+       DUMP(p, kernel_pgd, "px");
+       DUMP(p, tcd_ptr, "px");
+       DUMP(p, mc_kstack, "px");
+       DUMP(p, crit_kstack, "px");
+       DUMP(p, dbg_kstack, "px");
 #endif
-       DUMP(p, __current, "p");
+       DUMP(p, __current, "px");
        DUMP(p, kstack, "lx");
        printf(" kstack_base          = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
        DUMP(p, stab_rr, "lx");
@@ -2403,7 +2407,7 @@ static void dump_one_paca(int cpu)
 #endif
 
 #ifdef CONFIG_PPC_POWERNV
-       DUMP(p, core_idle_state_ptr, "p");
+       DUMP(p, core_idle_state_ptr, "px");
        DUMP(p, thread_idle_state, "x");
        DUMP(p, thread_mask, "x");
        DUMP(p, subcore_sibling_mask, "x");
index a1f28a54f23a42e85436ed607293bea14486391c..60c4c342316cdf75263e9b13913c65bd7c5838f1 100644 (file)
@@ -244,6 +244,17 @@ ENTRY(__switch_to_asm)
        movl    %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
 #endif
 
+#ifdef CONFIG_RETPOLINE
+       /*
+        * When switching from a shallower to a deeper call stack
+        * the RSB may either underflow or use entries populated
+        * with userspace addresses. On CPUs where those concerns
+        * exist, overwrite the RSB with entries which capture
+        * speculative execution to prevent attack.
+        */
+       FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
+#endif
+
        /* restore callee-saved registers */
        popl    %esi
        popl    %edi
index 4f8e1d35a97ca7071a11f33f07e2b87c2eac7acf..aa15b4c0e3d17dd64f513ce6a1915cdd24829016 100644 (file)
@@ -491,6 +491,17 @@ ENTRY(__switch_to_asm)
        movq    %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
 #endif
 
+#ifdef CONFIG_RETPOLINE
+       /*
+        * When switching from a shallower to a deeper call stack
+        * the RSB may either underflow or use entries populated
+        * with userspace addresses. On CPUs where those concerns
+        * exist, overwrite the RSB with entries which capture
+        * speculative execution to prevent attack.
+        */
+       FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
+#endif
+
        /* restore callee-saved registers */
        popq    %r15
        popq    %r14
index 005908ee9333f0e87cdd4db7ca14a278d52fa773..a2efb490f7435d137385c8dec0105f62ebd46264 100644 (file)
@@ -755,14 +755,14 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE_X, snbep_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_CORE, hsw_rapl_init),
-       X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_X,    hsw_rapl_init),
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_X,    hsx_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_ULT,  hsw_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_GT3E, hsw_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE,   hsw_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E,   hsw_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,      hsx_rapl_init),
-       X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsx_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, knl_rapl_init),
index a9e57f08bfa641d4cc9fb736bf2d1d4d22a6640c..98722773391db638438e22c2ef41e257b0f1f3fb 100644 (file)
@@ -136,6 +136,7 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
 extern void disable_local_APIC(void);
 extern void lapic_shutdown(void);
 extern void sync_Arb_IDs(void);
+extern void init_bsp_APIC(void);
 extern void apic_intr_mode_init(void);
 extern void setup_local_APIC(void);
 extern void init_apic_mappings(void);
index f275447862f4583909d14b6e2469c16e4a81b951..25b9375c1484b48f37c5e8f1d7fb286203491d1d 100644 (file)
 #define X86_FEATURE_RETPOLINE          ( 7*32+12) /* Generic Retpoline mitigation for Spectre variant 2 */
 #define X86_FEATURE_RETPOLINE_AMD      ( 7*32+13) /* AMD Retpoline mitigation for Spectre variant 2 */
 #define X86_FEATURE_INTEL_PPIN         ( 7*32+14) /* Intel Processor Inventory Number */
-#define X86_FEATURE_INTEL_PT           ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW      ( 7*32+16) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS      ( 7*32+17) /* AVX-512 Multiply Accumulation Single precision */
 
 #define X86_FEATURE_MBA                        ( 7*32+18) /* Memory Bandwidth Allocation */
+#define X86_FEATURE_RSB_CTXSW          ( 7*32+19) /* Fill RSB on context switches */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW         ( 8*32+ 0) /* Intel TPR Shadow */
 #define X86_FEATURE_AVX512IFMA         ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
 #define X86_FEATURE_CLFLUSHOPT         ( 9*32+23) /* CLFLUSHOPT instruction */
 #define X86_FEATURE_CLWB               ( 9*32+24) /* CLWB instruction */
+#define X86_FEATURE_INTEL_PT           ( 9*32+25) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512PF           ( 9*32+26) /* AVX-512 Prefetch */
 #define X86_FEATURE_AVX512ER           ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
 #define X86_FEATURE_AVX512CD           ( 9*32+28) /* AVX-512 Conflict Detection */
index c9459a4c3c680b754365cd8531b5c25f51b5fb54..22c5f3e6f8201aa03cbbbcd43e37e6bc30de6a35 100644 (file)
@@ -39,7 +39,7 @@ void __init sme_unmap_bootdata(char *real_mode_data);
 
 void __init sme_early_init(void);
 
-void __init sme_encrypt_kernel(void);
+void __init sme_encrypt_kernel(struct boot_params *bp);
 void __init sme_enable(struct boot_params *bp);
 
 int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
@@ -67,7 +67,7 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
 
 static inline void __init sme_early_init(void) { }
 
-static inline void __init sme_encrypt_kernel(void) { }
+static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
 static inline void __init sme_enable(struct boot_params *bp) { }
 
 static inline bool sme_active(void) { return false; }
index 402a11c803c38b0bf8de9d5664e5113249427d47..7b45d8424150899db45027fa07efa5ee9da26b73 100644 (file)
@@ -11,7 +11,7 @@
  * Fill the CPU return stack buffer.
  *
  * Each entry in the RSB, if used for a speculative 'ret', contains an
- * infinite 'pause; jmp' loop to capture speculative execution.
+ * infinite 'pause; lfence; jmp' loop to capture speculative execution.
  *
  * This is required in various cases for retpoline and IBRS-based
  * mitigations for the Spectre variant 2 vulnerability. Sometimes to
        call    772f;                           \
 773:   /* speculation trap */                  \
        pause;                                  \
+       lfence;                                 \
        jmp     773b;                           \
 772:                                           \
        call    774f;                           \
 775:   /* speculation trap */                  \
        pause;                                  \
+       lfence;                                 \
        jmp     775b;                           \
 774:                                           \
        dec     reg;                            \
@@ -73,6 +75,7 @@
        call    .Ldo_rop_\@
 .Lspec_trap_\@:
        pause
+       lfence
        jmp     .Lspec_trap_\@
 .Ldo_rop_\@:
        mov     \reg, (%_ASM_SP)
        "       .align 16\n"                                    \
        "901:   call   903f;\n"                                 \
        "902:   pause;\n"                                       \
+       "       lfence;\n"                                      \
        "       jmp    902b;\n"                                 \
        "       .align 16\n"                                    \
        "903:   addl   $4, %%esp;\n"                            \
index 880441f2414610298002c34652b96e571772e08f..25ddf02598d20a89cb1da2243aba687e6eee7657 100644 (file)
@@ -1286,6 +1286,55 @@ static int __init apic_intr_mode_select(void)
        return APIC_SYMMETRIC_IO;
 }
 
+/*
+ * An initial setup of the virtual wire mode.
+ */
+void __init init_bsp_APIC(void)
+{
+       unsigned int value;
+
+       /*
+        * Don't do the setup now if we have a SMP BIOS as the
+        * through-I/O-APIC virtual wire mode might be active.
+        */
+       if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC))
+               return;
+
+       /*
+        * Do not trust the local APIC being empty at bootup.
+        */
+       clear_local_APIC();
+
+       /*
+        * Enable APIC.
+        */
+       value = apic_read(APIC_SPIV);
+       value &= ~APIC_VECTOR_MASK;
+       value |= APIC_SPIV_APIC_ENABLED;
+
+#ifdef CONFIG_X86_32
+       /* This bit is reserved on P4/Xeon and should be cleared */
+       if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+           (boot_cpu_data.x86 == 15))
+               value &= ~APIC_SPIV_FOCUS_DISABLED;
+       else
+#endif
+               value |= APIC_SPIV_FOCUS_DISABLED;
+       value |= SPURIOUS_APIC_VECTOR;
+       apic_write(APIC_SPIV, value);
+
+       /*
+        * Set up the virtual wire mode.
+        */
+       apic_write(APIC_LVT0, APIC_DM_EXTINT);
+       value = APIC_DM_NMI;
+       if (!lapic_is_integrated())             /* 82489DX */
+               value |= APIC_LVT_LEVEL_TRIGGER;
+       if (apic_extnmi == APIC_EXTNMI_NONE)
+               value |= APIC_LVT_MASKED;
+       apic_write(APIC_LVT1, value);
+}
+
 /* Init the interrupt delivery mode for the BSP */
 void __init apic_intr_mode_init(void)
 {
index f8b03bb8e72560a436dbad677ddeed30f19531cf..3cc471beb50b499d89148bbdee37c697c596f743 100644 (file)
@@ -542,14 +542,17 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
 
                err = assign_irq_vector_policy(irqd, info);
                trace_vector_setup(virq + i, false, err);
-               if (err)
+               if (err) {
+                       irqd->chip_data = NULL;
+                       free_apic_chip_data(apicd);
                        goto error;
+               }
        }
 
        return 0;
 
 error:
-       x86_vector_free_irqs(domain, virq, i + 1);
+       x86_vector_free_irqs(domain, virq, i);
        return err;
 }
 
index e4dc26185aa70bcdecf8ca932b6c720121819558..390b3dc3d43827a88537e3208462755b565cb838 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/alternative.h>
 #include <asm/pgtable.h>
 #include <asm/set_memory.h>
+#include <asm/intel-family.h>
 
 static void __init spectre_v2_select_mitigation(void);
 
@@ -155,6 +156,23 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
        return SPECTRE_V2_CMD_NONE;
 }
 
+/* Check for Skylake-like CPUs (for RSB handling) */
+static bool __init is_skylake_era(void)
+{
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+           boot_cpu_data.x86 == 6) {
+               switch (boot_cpu_data.x86_model) {
+               case INTEL_FAM6_SKYLAKE_MOBILE:
+               case INTEL_FAM6_SKYLAKE_DESKTOP:
+               case INTEL_FAM6_SKYLAKE_X:
+               case INTEL_FAM6_KABYLAKE_MOBILE:
+               case INTEL_FAM6_KABYLAKE_DESKTOP:
+                       return true;
+               }
+       }
+       return false;
+}
+
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -213,6 +231,24 @@ static void __init spectre_v2_select_mitigation(void)
 
        spectre_v2_enabled = mode;
        pr_info("%s\n", spectre_v2_strings[mode]);
+
+       /*
+        * If neither SMEP or KPTI are available, there is a risk of
+        * hitting userspace addresses in the RSB after a context switch
+        * from a shallow call stack to a deeper one. To prevent this fill
+        * the entire RSB, even when using IBRS.
+        *
+        * Skylake era CPUs have a separate issue with *underflow* of the
+        * RSB, when they will predict 'ret' targets from the generic BTB.
+        * The proper mitigation for this is IBRS. If IBRS is not supported
+        * or deactivated in favour of retpolines the RSB fill on context
+        * switch is required.
+        */
+       if ((!boot_cpu_has(X86_FEATURE_PTI) &&
+            !boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) {
+               setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
+               pr_info("Filling RSB on context switch\n");
+       }
 }
 
 #undef pr_fmt
index 88dcf8479013569e93a58c278badaf690c29a27b..99442370de40d7b2fedcd3777d7865bf929877ff 100644 (file)
@@ -525,10 +525,6 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
                 */
                if (static_branch_unlikely(&rdt_mon_enable_key))
                        rmdir_mondata_subdir_allrdtgrp(r, d->id);
-               kfree(d->ctrl_val);
-               kfree(d->rmid_busy_llc);
-               kfree(d->mbm_total);
-               kfree(d->mbm_local);
                list_del(&d->list);
                if (is_mbm_enabled())
                        cancel_delayed_work(&d->mbm_over);
@@ -545,6 +541,10 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
                        cancel_delayed_work(&d->cqm_limbo);
                }
 
+               kfree(d->ctrl_val);
+               kfree(d->rmid_busy_llc);
+               kfree(d->mbm_total);
+               kfree(d->mbm_local);
                kfree(d);
                return;
        }
index 05459ad3db46e2139b7d97514899d398c321c541..d0e69769abfd39efea1d3b15fbf4f49b742b700f 100644 (file)
@@ -21,7 +21,6 @@ struct cpuid_bit {
 static const struct cpuid_bit cpuid_bits[] = {
        { X86_FEATURE_APERFMPERF,       CPUID_ECX,  0, 0x00000006, 0 },
        { X86_FEATURE_EPB,              CPUID_ECX,  3, 0x00000006, 0 },
-       { X86_FEATURE_INTEL_PT,         CPUID_EBX, 25, 0x00000007, 0 },
        { X86_FEATURE_AVX512_4VNNIW,    CPUID_EDX,  2, 0x00000007, 0 },
        { X86_FEATURE_AVX512_4FMAPS,    CPUID_EDX,  3, 0x00000007, 0 },
        { X86_FEATURE_CAT_L3,           CPUID_EBX,  1, 0x00000010, 0 },
index 6a5d757b9cfdc7c9bf4b815c0c13197ecbd32719..7ba5d819ebe3b351ff4124ded8c598adfcb1a5f1 100644 (file)
@@ -157,8 +157,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
        p = fixup_pointer(&phys_base, physaddr);
        *p += load_delta - sme_get_me_mask();
 
-       /* Encrypt the kernel (if SME is active) */
-       sme_encrypt_kernel();
+       /* Encrypt the kernel and related (if SME is active) */
+       sme_encrypt_kernel(bp);
 
        /*
         * Return the SME encryption mask (if SME is active) to be used as a
index d985cef3984ff030e3a83d50eaa9dc45f0a64a82..56d99be3706a23b600a50d2ae366b3a8fde251ed 100644 (file)
@@ -56,7 +56,7 @@ struct idt_data {
  * Early traps running on the DEFAULT_STACK because the other interrupt
  * stacks work only after cpu_init().
  */
-static const __initdata struct idt_data early_idts[] = {
+static const __initconst struct idt_data early_idts[] = {
        INTG(X86_TRAP_DB,               debug),
        SYSG(X86_TRAP_BP,               int3),
 #ifdef CONFIG_X86_32
@@ -70,7 +70,7 @@ static const __initdata struct idt_data early_idts[] = {
  * the traps which use them are reinitialized with IST after cpu_init() has
  * set up TSS.
  */
-static const __initdata struct idt_data def_idts[] = {
+static const __initconst struct idt_data def_idts[] = {
        INTG(X86_TRAP_DE,               divide_error),
        INTG(X86_TRAP_NMI,              nmi),
        INTG(X86_TRAP_BR,               bounds),
@@ -108,7 +108,7 @@ static const __initdata struct idt_data def_idts[] = {
 /*
  * The APIC and SMP idt entries
  */
-static const __initdata struct idt_data apic_idts[] = {
+static const __initconst struct idt_data apic_idts[] = {
 #ifdef CONFIG_SMP
        INTG(RESCHEDULE_VECTOR,         reschedule_interrupt),
        INTG(CALL_FUNCTION_VECTOR,      call_function_interrupt),
@@ -150,7 +150,7 @@ static const __initdata struct idt_data apic_idts[] = {
  * Early traps running on the DEFAULT_STACK because the other interrupt
  * stacks work only after cpu_init().
  */
-static const __initdata struct idt_data early_pf_idts[] = {
+static const __initconst struct idt_data early_pf_idts[] = {
        INTG(X86_TRAP_PF,               page_fault),
 };
 
@@ -158,7 +158,7 @@ static const __initdata struct idt_data early_pf_idts[] = {
  * Override for the debug_idt. Same as the default, but with interrupt
  * stack set to DEFAULT_STACK (0). Required for NMI trap handling.
  */
-static const __initdata struct idt_data dbg_idts[] = {
+static const __initconst struct idt_data dbg_idts[] = {
        INTG(X86_TRAP_DB,       debug),
        INTG(X86_TRAP_BP,       int3),
 };
@@ -180,7 +180,7 @@ gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
  * The exceptions which use Interrupt stacks. They are setup after
  * cpu_init() when the TSS has been initialized.
  */
-static const __initdata struct idt_data ist_idts[] = {
+static const __initconst struct idt_data ist_idts[] = {
        ISTG(X86_TRAP_DB,       debug,          DEBUG_STACK),
        ISTG(X86_TRAP_NMI,      nmi,            NMI_STACK),
        SISTG(X86_TRAP_BP,      int3,           DEBUG_STACK),
index 8da3e909e967dd1cd2c55955f7e5445574a07a24..a539410c4ea9946993d4db7408a2ccf7b1ca746a 100644 (file)
@@ -61,6 +61,9 @@ void __init init_ISA_irqs(void)
        struct irq_chip *chip = legacy_pic->chip;
        int i;
 
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+       init_bsp_APIC();
+#endif
        legacy_pic->init(0);
 
        for (i = 0; i < nr_legacy_irqs(); i++)
index 145810b0edf6738b57a0e6560c53392ae54a82e7..68d7ab81c62fd2b5788accfab97e39101d0b8036 100644 (file)
@@ -364,16 +364,6 @@ static void __init reserve_initrd(void)
            !ramdisk_image || !ramdisk_size)
                return;         /* No initrd provided by bootloader */
 
-       /*
-        * If SME is active, this memory will be marked encrypted by the
-        * kernel when it is accessed (including relocation). However, the
-        * ramdisk image was loaded decrypted by the bootloader, so make
-        * sure that it is encrypted before accessing it. For SEV the
-        * ramdisk will already be encrypted, so only do this for SME.
-        */
-       if (sme_active())
-               sme_early_encrypt(ramdisk_image, ramdisk_end - ramdisk_image);
-
        initrd_start = 0;
 
        mapped_size = memblock_mem_size(max_pfn_mapped);
index 8ea117f8142e192ac0a143f225e505803c82106a..e169e85db434776f1b406dd83f7071c303481058 100644 (file)
@@ -602,7 +602,6 @@ unsigned long native_calibrate_tsc(void)
                case INTEL_FAM6_KABYLAKE_DESKTOP:
                        crystal_khz = 24000;    /* 24.0 MHz */
                        break;
-               case INTEL_FAM6_SKYLAKE_X:
                case INTEL_FAM6_ATOM_DENVERTON:
                        crystal_khz = 25000;    /* 25.0 MHz */
                        break;
@@ -612,6 +611,8 @@ unsigned long native_calibrate_tsc(void)
                }
        }
 
+       if (crystal_khz == 0)
+               return 0;
        /*
         * TSC frequency determined by CPUID is a "hardware reported"
         * frequency and is the most accurate one so far we have. This
@@ -1315,6 +1316,12 @@ void __init tsc_init(void)
                (unsigned long)cpu_khz / 1000,
                (unsigned long)cpu_khz % 1000);
 
+       if (cpu_khz != tsc_khz) {
+               pr_info("Detected %lu.%03lu MHz TSC",
+                       (unsigned long)tsc_khz / 1000,
+                       (unsigned long)tsc_khz % 1000);
+       }
+
        /* Sanitize TSC ADJUST before cyc2ns gets initialized */
        tsc_store_and_check_tsc_adjust(true);
 
index 06fe3d51d385b88111961c0b5addc673fcd597a2..b3e40773dce0961039585a39b67ec991e9ac1a4c 100644 (file)
@@ -172,14 +172,15 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
  * 6. T1   : reaches here, sees vma_pkey(vma)=5, when we really
  *          faulted on a pte with its pkey=4.
  */
-static void fill_sig_info_pkey(int si_code, siginfo_t *info, u32 *pkey)
+static void fill_sig_info_pkey(int si_signo, int si_code, siginfo_t *info,
+               u32 *pkey)
 {
        /* This is effectively an #ifdef */
        if (!boot_cpu_has(X86_FEATURE_OSPKE))
                return;
 
        /* Fault not from Protection Keys: nothing to do */
-       if (si_code != SEGV_PKUERR)
+       if ((si_code != SEGV_PKUERR) || (si_signo != SIGSEGV))
                return;
        /*
         * force_sig_info_fault() is called from a number of
@@ -218,7 +219,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
                lsb = PAGE_SHIFT;
        info.si_addr_lsb = lsb;
 
-       fill_sig_info_pkey(si_code, &info, pkey);
+       fill_sig_info_pkey(si_signo, si_code, &info, pkey);
 
        force_sig_info(si_signo, &info, tsk);
 }
index 47388f0c0e59649ca3574d4e7c31b356dad7d247..af6f2f9c6a265d837f3882fcc45ef46da918fff0 100644 (file)
@@ -21,10 +21,14 @@ extern struct range pfn_mapped[E820_MAX_ENTRIES];
 
 static p4d_t tmp_p4d_table[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
 
-static __init void *early_alloc(size_t size, int nid)
+static __init void *early_alloc(size_t size, int nid, bool panic)
 {
-       return memblock_virt_alloc_try_nid_nopanic(size, size,
-               __pa(MAX_DMA_ADDRESS), BOOTMEM_ALLOC_ACCESSIBLE, nid);
+       if (panic)
+               return memblock_virt_alloc_try_nid(size, size,
+                       __pa(MAX_DMA_ADDRESS), BOOTMEM_ALLOC_ACCESSIBLE, nid);
+       else
+               return memblock_virt_alloc_try_nid_nopanic(size, size,
+                       __pa(MAX_DMA_ADDRESS), BOOTMEM_ALLOC_ACCESSIBLE, nid);
 }
 
 static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
@@ -38,14 +42,14 @@ static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
                if (boot_cpu_has(X86_FEATURE_PSE) &&
                    ((end - addr) == PMD_SIZE) &&
                    IS_ALIGNED(addr, PMD_SIZE)) {
-                       p = early_alloc(PMD_SIZE, nid);
+                       p = early_alloc(PMD_SIZE, nid, false);
                        if (p && pmd_set_huge(pmd, __pa(p), PAGE_KERNEL))
                                return;
                        else if (p)
                                memblock_free(__pa(p), PMD_SIZE);
                }
 
-               p = early_alloc(PAGE_SIZE, nid);
+               p = early_alloc(PAGE_SIZE, nid, true);
                pmd_populate_kernel(&init_mm, pmd, p);
        }
 
@@ -57,7 +61,7 @@ static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
                if (!pte_none(*pte))
                        continue;
 
-               p = early_alloc(PAGE_SIZE, nid);
+               p = early_alloc(PAGE_SIZE, nid, true);
                entry = pfn_pte(PFN_DOWN(__pa(p)), PAGE_KERNEL);
                set_pte_at(&init_mm, addr, pte, entry);
        } while (pte++, addr += PAGE_SIZE, addr != end);
@@ -75,14 +79,14 @@ static void __init kasan_populate_pud(pud_t *pud, unsigned long addr,
                if (boot_cpu_has(X86_FEATURE_GBPAGES) &&
                    ((end - addr) == PUD_SIZE) &&
                    IS_ALIGNED(addr, PUD_SIZE)) {
-                       p = early_alloc(PUD_SIZE, nid);
+                       p = early_alloc(PUD_SIZE, nid, false);
                        if (p && pud_set_huge(pud, __pa(p), PAGE_KERNEL))
                                return;
                        else if (p)
                                memblock_free(__pa(p), PUD_SIZE);
                }
 
-               p = early_alloc(PAGE_SIZE, nid);
+               p = early_alloc(PAGE_SIZE, nid, true);
                pud_populate(&init_mm, pud, p);
        }
 
@@ -101,7 +105,7 @@ static void __init kasan_populate_p4d(p4d_t *p4d, unsigned long addr,
        unsigned long next;
 
        if (p4d_none(*p4d)) {
-               void *p = early_alloc(PAGE_SIZE, nid);
+               void *p = early_alloc(PAGE_SIZE, nid, true);
 
                p4d_populate(&init_mm, p4d, p);
        }
@@ -122,7 +126,7 @@ static void __init kasan_populate_pgd(pgd_t *pgd, unsigned long addr,
        unsigned long next;
 
        if (pgd_none(*pgd)) {
-               p = early_alloc(PAGE_SIZE, nid);
+               p = early_alloc(PAGE_SIZE, nid, true);
                pgd_populate(&init_mm, pgd, p);
        }
 
index 391b13402e403041222ef8e6bd22f60edaeb9446..3ef362f598e3ed16f9f1b45d409fe800c2736ded 100644 (file)
@@ -464,37 +464,62 @@ void swiotlb_set_mem_attributes(void *vaddr, unsigned long size)
        set_memory_decrypted((unsigned long)vaddr, size >> PAGE_SHIFT);
 }
 
-static void __init sme_clear_pgd(pgd_t *pgd_base, unsigned long start,
-                                unsigned long end)
+struct sme_populate_pgd_data {
+       void    *pgtable_area;
+       pgd_t   *pgd;
+
+       pmdval_t pmd_flags;
+       pteval_t pte_flags;
+       unsigned long paddr;
+
+       unsigned long vaddr;
+       unsigned long vaddr_end;
+};
+
+static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
 {
        unsigned long pgd_start, pgd_end, pgd_size;
        pgd_t *pgd_p;
 
-       pgd_start = start & PGDIR_MASK;
-       pgd_end = end & PGDIR_MASK;
+       pgd_start = ppd->vaddr & PGDIR_MASK;
+       pgd_end = ppd->vaddr_end & PGDIR_MASK;
 
-       pgd_size = (((pgd_end - pgd_start) / PGDIR_SIZE) + 1);
-       pgd_size *= sizeof(pgd_t);
+       pgd_size = (((pgd_end - pgd_start) / PGDIR_SIZE) + 1) * sizeof(pgd_t);
 
-       pgd_p = pgd_base + pgd_index(start);
+       pgd_p = ppd->pgd + pgd_index(ppd->vaddr);
 
        memset(pgd_p, 0, pgd_size);
 }
 
-#define PGD_FLAGS      _KERNPG_TABLE_NOENC
-#define P4D_FLAGS      _KERNPG_TABLE_NOENC
-#define PUD_FLAGS      _KERNPG_TABLE_NOENC
-#define PMD_FLAGS      (__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL)
+#define PGD_FLAGS              _KERNPG_TABLE_NOENC
+#define P4D_FLAGS              _KERNPG_TABLE_NOENC
+#define PUD_FLAGS              _KERNPG_TABLE_NOENC
+#define PMD_FLAGS              _KERNPG_TABLE_NOENC
+
+#define PMD_FLAGS_LARGE                (__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL)
+
+#define PMD_FLAGS_DEC          PMD_FLAGS_LARGE
+#define PMD_FLAGS_DEC_WP       ((PMD_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \
+                                (_PAGE_PAT | _PAGE_PWT))
+
+#define PMD_FLAGS_ENC          (PMD_FLAGS_LARGE | _PAGE_ENC)
+
+#define PTE_FLAGS              (__PAGE_KERNEL_EXEC & ~_PAGE_GLOBAL)
+
+#define PTE_FLAGS_DEC          PTE_FLAGS
+#define PTE_FLAGS_DEC_WP       ((PTE_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \
+                                (_PAGE_PAT | _PAGE_PWT))
+
+#define PTE_FLAGS_ENC          (PTE_FLAGS | _PAGE_ENC)
 
-static void __init *sme_populate_pgd(pgd_t *pgd_base, void *pgtable_area,
-                                    unsigned long vaddr, pmdval_t pmd_val)
+static pmd_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
 {
        pgd_t *pgd_p;
        p4d_t *p4d_p;
        pud_t *pud_p;
        pmd_t *pmd_p;
 
-       pgd_p = pgd_base + pgd_index(vaddr);
+       pgd_p = ppd->pgd + pgd_index(ppd->vaddr);
        if (native_pgd_val(*pgd_p)) {
                if (IS_ENABLED(CONFIG_X86_5LEVEL))
                        p4d_p = (p4d_t *)(native_pgd_val(*pgd_p) & ~PTE_FLAGS_MASK);
@@ -504,15 +529,15 @@ static void __init *sme_populate_pgd(pgd_t *pgd_base, void *pgtable_area,
                pgd_t pgd;
 
                if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
-                       p4d_p = pgtable_area;
+                       p4d_p = ppd->pgtable_area;
                        memset(p4d_p, 0, sizeof(*p4d_p) * PTRS_PER_P4D);
-                       pgtable_area += sizeof(*p4d_p) * PTRS_PER_P4D;
+                       ppd->pgtable_area += sizeof(*p4d_p) * PTRS_PER_P4D;
 
                        pgd = native_make_pgd((pgdval_t)p4d_p + PGD_FLAGS);
                } else {
-                       pud_p = pgtable_area;
+                       pud_p = ppd->pgtable_area;
                        memset(pud_p, 0, sizeof(*pud_p) * PTRS_PER_PUD);
-                       pgtable_area += sizeof(*pud_p) * PTRS_PER_PUD;
+                       ppd->pgtable_area += sizeof(*pud_p) * PTRS_PER_PUD;
 
                        pgd = native_make_pgd((pgdval_t)pud_p + PGD_FLAGS);
                }
@@ -520,58 +545,160 @@ static void __init *sme_populate_pgd(pgd_t *pgd_base, void *pgtable_area,
        }
 
        if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
-               p4d_p += p4d_index(vaddr);
+               p4d_p += p4d_index(ppd->vaddr);
                if (native_p4d_val(*p4d_p)) {
                        pud_p = (pud_t *)(native_p4d_val(*p4d_p) & ~PTE_FLAGS_MASK);
                } else {
                        p4d_t p4d;
 
-                       pud_p = pgtable_area;
+                       pud_p = ppd->pgtable_area;
                        memset(pud_p, 0, sizeof(*pud_p) * PTRS_PER_PUD);
-                       pgtable_area += sizeof(*pud_p) * PTRS_PER_PUD;
+                       ppd->pgtable_area += sizeof(*pud_p) * PTRS_PER_PUD;
 
                        p4d = native_make_p4d((pudval_t)pud_p + P4D_FLAGS);
                        native_set_p4d(p4d_p, p4d);
                }
        }
 
-       pud_p += pud_index(vaddr);
+       pud_p += pud_index(ppd->vaddr);
        if (native_pud_val(*pud_p)) {
                if (native_pud_val(*pud_p) & _PAGE_PSE)
-                       goto out;
+                       return NULL;
 
                pmd_p = (pmd_t *)(native_pud_val(*pud_p) & ~PTE_FLAGS_MASK);
        } else {
                pud_t pud;
 
-               pmd_p = pgtable_area;
+               pmd_p = ppd->pgtable_area;
                memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
-               pgtable_area += sizeof(*pmd_p) * PTRS_PER_PMD;
+               ppd->pgtable_area += sizeof(*pmd_p) * PTRS_PER_PMD;
 
                pud = native_make_pud((pmdval_t)pmd_p + PUD_FLAGS);
                native_set_pud(pud_p, pud);
        }
 
-       pmd_p += pmd_index(vaddr);
+       return pmd_p;
+}
+
+static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
+{
+       pmd_t *pmd_p;
+
+       pmd_p = sme_prepare_pgd(ppd);
+       if (!pmd_p)
+               return;
+
+       pmd_p += pmd_index(ppd->vaddr);
        if (!native_pmd_val(*pmd_p) || !(native_pmd_val(*pmd_p) & _PAGE_PSE))
-               native_set_pmd(pmd_p, native_make_pmd(pmd_val));
+               native_set_pmd(pmd_p, native_make_pmd(ppd->paddr | ppd->pmd_flags));
+}
 
-out:
-       return pgtable_area;
+static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
+{
+       pmd_t *pmd_p;
+       pte_t *pte_p;
+
+       pmd_p = sme_prepare_pgd(ppd);
+       if (!pmd_p)
+               return;
+
+       pmd_p += pmd_index(ppd->vaddr);
+       if (native_pmd_val(*pmd_p)) {
+               if (native_pmd_val(*pmd_p) & _PAGE_PSE)
+                       return;
+
+               pte_p = (pte_t *)(native_pmd_val(*pmd_p) & ~PTE_FLAGS_MASK);
+       } else {
+               pmd_t pmd;
+
+               pte_p = ppd->pgtable_area;
+               memset(pte_p, 0, sizeof(*pte_p) * PTRS_PER_PTE);
+               ppd->pgtable_area += sizeof(*pte_p) * PTRS_PER_PTE;
+
+               pmd = native_make_pmd((pteval_t)pte_p + PMD_FLAGS);
+               native_set_pmd(pmd_p, pmd);
+       }
+
+       pte_p += pte_index(ppd->vaddr);
+       if (!native_pte_val(*pte_p))
+               native_set_pte(pte_p, native_make_pte(ppd->paddr | ppd->pte_flags));
+}
+
+static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
+{
+       while (ppd->vaddr < ppd->vaddr_end) {
+               sme_populate_pgd_large(ppd);
+
+               ppd->vaddr += PMD_PAGE_SIZE;
+               ppd->paddr += PMD_PAGE_SIZE;
+       }
+}
+
+static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
+{
+       while (ppd->vaddr < ppd->vaddr_end) {
+               sme_populate_pgd(ppd);
+
+               ppd->vaddr += PAGE_SIZE;
+               ppd->paddr += PAGE_SIZE;
+       }
+}
+
+static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
+                                  pmdval_t pmd_flags, pteval_t pte_flags)
+{
+       unsigned long vaddr_end;
+
+       ppd->pmd_flags = pmd_flags;
+       ppd->pte_flags = pte_flags;
+
+       /* Save original end value since we modify the struct value */
+       vaddr_end = ppd->vaddr_end;
+
+       /* If start is not 2MB aligned, create PTE entries */
+       ppd->vaddr_end = ALIGN(ppd->vaddr, PMD_PAGE_SIZE);
+       __sme_map_range_pte(ppd);
+
+       /* Create PMD entries */
+       ppd->vaddr_end = vaddr_end & PMD_PAGE_MASK;
+       __sme_map_range_pmd(ppd);
+
+       /* If end is not 2MB aligned, create PTE entries */
+       ppd->vaddr_end = vaddr_end;
+       __sme_map_range_pte(ppd);
+}
+
+static void __init sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
+{
+       __sme_map_range(ppd, PMD_FLAGS_ENC, PTE_FLAGS_ENC);
+}
+
+static void __init sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
+{
+       __sme_map_range(ppd, PMD_FLAGS_DEC, PTE_FLAGS_DEC);
+}
+
+static void __init sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
+{
+       __sme_map_range(ppd, PMD_FLAGS_DEC_WP, PTE_FLAGS_DEC_WP);
 }
 
 static unsigned long __init sme_pgtable_calc(unsigned long len)
 {
-       unsigned long p4d_size, pud_size, pmd_size;
+       unsigned long p4d_size, pud_size, pmd_size, pte_size;
        unsigned long total;
 
        /*
         * Perform a relatively simplistic calculation of the pagetable
-        * entries that are needed. That mappings will be covered by 2MB
-        * PMD entries so we can conservatively calculate the required
+        * entries that are needed. Those mappings will be covered mostly
+        * by 2MB PMD entries so we can conservatively calculate the required
         * number of P4D, PUD and PMD structures needed to perform the
-        * mappings. Incrementing the count for each covers the case where
-        * the addresses cross entries.
+        * mappings.  For mappings that are not 2MB aligned, PTE mappings
+        * would be needed for the start and end portion of the address range
+        * that fall outside of the 2MB alignment.  This results in, at most,
+        * two extra pages to hold PTE entries for each range that is mapped.
+        * Incrementing the count for each covers the case where the addresses
+        * cross entries.
         */
        if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
                p4d_size = (ALIGN(len, PGDIR_SIZE) / PGDIR_SIZE) + 1;
@@ -585,8 +712,9 @@ static unsigned long __init sme_pgtable_calc(unsigned long len)
        }
        pmd_size = (ALIGN(len, PUD_SIZE) / PUD_SIZE) + 1;
        pmd_size *= sizeof(pmd_t) * PTRS_PER_PMD;
+       pte_size = 2 * sizeof(pte_t) * PTRS_PER_PTE;
 
-       total = p4d_size + pud_size + pmd_size;
+       total = p4d_size + pud_size + pmd_size + pte_size;
 
        /*
         * Now calculate the added pagetable structures needed to populate
@@ -610,29 +738,29 @@ static unsigned long __init sme_pgtable_calc(unsigned long len)
        return total;
 }
 
-void __init sme_encrypt_kernel(void)
+void __init sme_encrypt_kernel(struct boot_params *bp)
 {
        unsigned long workarea_start, workarea_end, workarea_len;
        unsigned long execute_start, execute_end, execute_len;
        unsigned long kernel_start, kernel_end, kernel_len;
+       unsigned long initrd_start, initrd_end, initrd_len;
+       struct sme_populate_pgd_data ppd;
        unsigned long pgtable_area_len;
-       unsigned long paddr, pmd_flags;
        unsigned long decrypted_base;
-       void *pgtable_area;
-       pgd_t *pgd;
 
        if (!sme_active())
                return;
 
        /*
-        * Prepare for encrypting the kernel by building new pagetables with
-        * the necessary attributes needed to encrypt the kernel in place.
+        * Prepare for encrypting the kernel and initrd by building new
+        * pagetables with the necessary attributes needed to encrypt the
+        * kernel in place.
         *
         *   One range of virtual addresses will map the memory occupied
-        *   by the kernel as encrypted.
+        *   by the kernel and initrd as encrypted.
         *
         *   Another range of virtual addresses will map the memory occupied
-        *   by the kernel as decrypted and write-protected.
+        *   by the kernel and initrd as decrypted and write-protected.
         *
         *     The use of write-protect attribute will prevent any of the
         *     memory from being cached.
@@ -643,6 +771,20 @@ void __init sme_encrypt_kernel(void)
        kernel_end = ALIGN(__pa_symbol(_end), PMD_PAGE_SIZE);
        kernel_len = kernel_end - kernel_start;
 
+       initrd_start = 0;
+       initrd_end = 0;
+       initrd_len = 0;
+#ifdef CONFIG_BLK_DEV_INITRD
+       initrd_len = (unsigned long)bp->hdr.ramdisk_size |
+                    ((unsigned long)bp->ext_ramdisk_size << 32);
+       if (initrd_len) {
+               initrd_start = (unsigned long)bp->hdr.ramdisk_image |
+                              ((unsigned long)bp->ext_ramdisk_image << 32);
+               initrd_end = PAGE_ALIGN(initrd_start + initrd_len);
+               initrd_len = initrd_end - initrd_start;
+       }
+#endif
+
        /* Set the encryption workarea to be immediately after the kernel */
        workarea_start = kernel_end;
 
@@ -665,16 +807,21 @@ void __init sme_encrypt_kernel(void)
         */
        pgtable_area_len = sizeof(pgd_t) * PTRS_PER_PGD;
        pgtable_area_len += sme_pgtable_calc(execute_end - kernel_start) * 2;
+       if (initrd_len)
+               pgtable_area_len += sme_pgtable_calc(initrd_len) * 2;
 
        /* PUDs and PMDs needed in the current pagetables for the workarea */
        pgtable_area_len += sme_pgtable_calc(execute_len + pgtable_area_len);
 
        /*
         * The total workarea includes the executable encryption area and
-        * the pagetable area.
+        * the pagetable area. The start of the workarea is already 2MB
+        * aligned, align the end of the workarea on a 2MB boundary so that
+        * we don't try to create/allocate PTE entries from the workarea
+        * before it is mapped.
         */
        workarea_len = execute_len + pgtable_area_len;
-       workarea_end = workarea_start + workarea_len;
+       workarea_end = ALIGN(workarea_start + workarea_len, PMD_PAGE_SIZE);
 
        /*
         * Set the address to the start of where newly created pagetable
@@ -683,45 +830,30 @@ void __init sme_encrypt_kernel(void)
         * pagetables and when the new encrypted and decrypted kernel
         * mappings are populated.
         */
-       pgtable_area = (void *)execute_end;
+       ppd.pgtable_area = (void *)execute_end;
 
        /*
         * Make sure the current pagetable structure has entries for
         * addressing the workarea.
         */
-       pgd = (pgd_t *)native_read_cr3_pa();
-       paddr = workarea_start;
-       while (paddr < workarea_end) {
-               pgtable_area = sme_populate_pgd(pgd, pgtable_area,
-                                               paddr,
-                                               paddr + PMD_FLAGS);
-
-               paddr += PMD_PAGE_SIZE;
-       }
+       ppd.pgd = (pgd_t *)native_read_cr3_pa();
+       ppd.paddr = workarea_start;
+       ppd.vaddr = workarea_start;
+       ppd.vaddr_end = workarea_end;
+       sme_map_range_decrypted(&ppd);
 
        /* Flush the TLB - no globals so cr3 is enough */
        native_write_cr3(__native_read_cr3());
 
        /*
         * A new pagetable structure is being built to allow for the kernel
-        * to be encrypted. It starts with an empty PGD that will then be
-        * populated with new PUDs and PMDs as the encrypted and decrypted
-        * kernel mappings are created.
+        * and initrd to be encrypted. It starts with an empty PGD that will
+        * then be populated with new PUDs and PMDs as the encrypted and
+        * decrypted kernel mappings are created.
         */
-       pgd = pgtable_area;
-       memset(pgd, 0, sizeof(*pgd) * PTRS_PER_PGD);
-       pgtable_area += sizeof(*pgd) * PTRS_PER_PGD;
-
-       /* Add encrypted kernel (identity) mappings */
-       pmd_flags = PMD_FLAGS | _PAGE_ENC;
-       paddr = kernel_start;
-       while (paddr < kernel_end) {
-               pgtable_area = sme_populate_pgd(pgd, pgtable_area,
-                                               paddr,
-                                               paddr + pmd_flags);
-
-               paddr += PMD_PAGE_SIZE;
-       }
+       ppd.pgd = ppd.pgtable_area;
+       memset(ppd.pgd, 0, sizeof(pgd_t) * PTRS_PER_PGD);
+       ppd.pgtable_area += sizeof(pgd_t) * PTRS_PER_PGD;
 
        /*
         * A different PGD index/entry must be used to get different
@@ -730,47 +862,79 @@ void __init sme_encrypt_kernel(void)
         * the base of the mapping.
         */
        decrypted_base = (pgd_index(workarea_end) + 1) & (PTRS_PER_PGD - 1);
+       if (initrd_len) {
+               unsigned long check_base;
+
+               check_base = (pgd_index(initrd_end) + 1) & (PTRS_PER_PGD - 1);
+               decrypted_base = max(decrypted_base, check_base);
+       }
        decrypted_base <<= PGDIR_SHIFT;
 
+       /* Add encrypted kernel (identity) mappings */
+       ppd.paddr = kernel_start;
+       ppd.vaddr = kernel_start;
+       ppd.vaddr_end = kernel_end;
+       sme_map_range_encrypted(&ppd);
+
        /* Add decrypted, write-protected kernel (non-identity) mappings */
-       pmd_flags = (PMD_FLAGS & ~_PAGE_CACHE_MASK) | (_PAGE_PAT | _PAGE_PWT);
-       paddr = kernel_start;
-       while (paddr < kernel_end) {
-               pgtable_area = sme_populate_pgd(pgd, pgtable_area,
-                                               paddr + decrypted_base,
-                                               paddr + pmd_flags);
-
-               paddr += PMD_PAGE_SIZE;
+       ppd.paddr = kernel_start;
+       ppd.vaddr = kernel_start + decrypted_base;
+       ppd.vaddr_end = kernel_end + decrypted_base;
+       sme_map_range_decrypted_wp(&ppd);
+
+       if (initrd_len) {
+               /* Add encrypted initrd (identity) mappings */
+               ppd.paddr = initrd_start;
+               ppd.vaddr = initrd_start;
+               ppd.vaddr_end = initrd_end;
+               sme_map_range_encrypted(&ppd);
+               /*
+                * Add decrypted, write-protected initrd (non-identity) mappings
+                */
+               ppd.paddr = initrd_start;
+               ppd.vaddr = initrd_start + decrypted_base;
+               ppd.vaddr_end = initrd_end + decrypted_base;
+               sme_map_range_decrypted_wp(&ppd);
        }
 
        /* Add decrypted workarea mappings to both kernel mappings */
-       paddr = workarea_start;
-       while (paddr < workarea_end) {
-               pgtable_area = sme_populate_pgd(pgd, pgtable_area,
-                                               paddr,
-                                               paddr + PMD_FLAGS);
+       ppd.paddr = workarea_start;
+       ppd.vaddr = workarea_start;
+       ppd.vaddr_end = workarea_end;
+       sme_map_range_decrypted(&ppd);
 
-               pgtable_area = sme_populate_pgd(pgd, pgtable_area,
-                                               paddr + decrypted_base,
-                                               paddr + PMD_FLAGS);
-
-               paddr += PMD_PAGE_SIZE;
-       }
+       ppd.paddr = workarea_start;
+       ppd.vaddr = workarea_start + decrypted_base;
+       ppd.vaddr_end = workarea_end + decrypted_base;
+       sme_map_range_decrypted(&ppd);
 
        /* Perform the encryption */
        sme_encrypt_execute(kernel_start, kernel_start + decrypted_base,
-                           kernel_len, workarea_start, (unsigned long)pgd);
+                           kernel_len, workarea_start, (unsigned long)ppd.pgd);
+
+       if (initrd_len)
+               sme_encrypt_execute(initrd_start, initrd_start + decrypted_base,
+                                   initrd_len, workarea_start,
+                                   (unsigned long)ppd.pgd);
 
        /*
         * At this point we are running encrypted.  Remove the mappings for
         * the decrypted areas - all that is needed for this is to remove
         * the PGD entry/entries.
         */
-       sme_clear_pgd(pgd, kernel_start + decrypted_base,
-                     kernel_end + decrypted_base);
+       ppd.vaddr = kernel_start + decrypted_base;
+       ppd.vaddr_end = kernel_end + decrypted_base;
+       sme_clear_pgd(&ppd);
+
+       if (initrd_len) {
+               ppd.vaddr = initrd_start + decrypted_base;
+               ppd.vaddr_end = initrd_end + decrypted_base;
+               sme_clear_pgd(&ppd);
+       }
 
-       sme_clear_pgd(pgd, workarea_start + decrypted_base,
-                     workarea_end + decrypted_base);
+       ppd.vaddr = workarea_start + decrypted_base;
+       ppd.vaddr_end = workarea_end + decrypted_base;
+       sme_clear_pgd(&ppd);
 
        /* Flush the TLB - no globals so cr3 is enough */
        native_write_cr3(__native_read_cr3());
index 730e6d541df1d6c172f553032bc00d8b0f5b312a..01f682cf77a8b36bff9a2b45a8f8beb734b4b6c4 100644 (file)
@@ -22,9 +22,9 @@ ENTRY(sme_encrypt_execute)
 
        /*
         * Entry parameters:
-        *   RDI - virtual address for the encrypted kernel mapping
-        *   RSI - virtual address for the decrypted kernel mapping
-        *   RDX - length of kernel
+        *   RDI - virtual address for the encrypted mapping
+        *   RSI - virtual address for the decrypted mapping
+        *   RDX - length to encrypt
         *   RCX - virtual address of the encryption workarea, including:
         *     - stack page (PAGE_SIZE)
         *     - encryption routine page (PAGE_SIZE)
@@ -41,9 +41,9 @@ ENTRY(sme_encrypt_execute)
        addq    $PAGE_SIZE, %rax        /* Workarea encryption routine */
 
        push    %r12
-       movq    %rdi, %r10              /* Encrypted kernel */
-       movq    %rsi, %r11              /* Decrypted kernel */
-       movq    %rdx, %r12              /* Kernel length */
+       movq    %rdi, %r10              /* Encrypted area */
+       movq    %rsi, %r11              /* Decrypted area */
+       movq    %rdx, %r12              /* Area length */
 
        /* Copy encryption routine into the workarea */
        movq    %rax, %rdi                              /* Workarea encryption routine */
@@ -52,10 +52,10 @@ ENTRY(sme_encrypt_execute)
        rep     movsb
 
        /* Setup registers for call */
-       movq    %r10, %rdi              /* Encrypted kernel */
-       movq    %r11, %rsi              /* Decrypted kernel */
+       movq    %r10, %rdi              /* Encrypted area */
+       movq    %r11, %rsi              /* Decrypted area */
        movq    %r8, %rdx               /* Pagetables used for encryption */
-       movq    %r12, %rcx              /* Kernel length */
+       movq    %r12, %rcx              /* Area length */
        movq    %rax, %r8               /* Workarea encryption routine */
        addq    $PAGE_SIZE, %r8         /* Workarea intermediate copy buffer */
 
@@ -71,7 +71,7 @@ ENDPROC(sme_encrypt_execute)
 
 ENTRY(__enc_copy)
 /*
- * Routine used to encrypt kernel.
+ * Routine used to encrypt memory in place.
  *   This routine must be run outside of the kernel proper since
  *   the kernel will be encrypted during the process. So this
  *   routine is defined here and then copied to an area outside
@@ -79,19 +79,19 @@ ENTRY(__enc_copy)
  *   during execution.
  *
  *   On entry the registers must be:
- *     RDI - virtual address for the encrypted kernel mapping
- *     RSI - virtual address for the decrypted kernel mapping
+ *     RDI - virtual address for the encrypted mapping
+ *     RSI - virtual address for the decrypted mapping
  *     RDX - address of the pagetables to use for encryption
- *     RCX - length of kernel
+ *     RCX - length of area
  *      R8 - intermediate copy buffer
  *
  *     RAX - points to this routine
  *
- * The kernel will be encrypted by copying from the non-encrypted
- * kernel space to an intermediate buffer and then copying from the
- * intermediate buffer back to the encrypted kernel space. The physical
- * addresses of the two kernel space mappings are the same which
- * results in the kernel being encrypted "in place".
+ * The area will be encrypted by copying from the non-encrypted
+ * memory space to an intermediate buffer and then copying from the
+ * intermediate buffer back to the encrypted memory space. The physical
+ * addresses of the two mappings are the same which results in the area
+ * being encrypted "in place".
  */
        /* Enable the new page tables */
        mov     %rdx, %cr3
@@ -103,47 +103,55 @@ ENTRY(__enc_copy)
        orq     $X86_CR4_PGE, %rdx
        mov     %rdx, %cr4
 
+       push    %r15
+       push    %r12
+
+       movq    %rcx, %r9               /* Save area length */
+       movq    %rdi, %r10              /* Save encrypted area address */
+       movq    %rsi, %r11              /* Save decrypted area address */
+
        /* Set the PAT register PA5 entry to write-protect */
-       push    %rcx
        movl    $MSR_IA32_CR_PAT, %ecx
        rdmsr
-       push    %rdx                    /* Save original PAT value */
+       mov     %rdx, %r15              /* Save original PAT value */
        andl    $0xffff00ff, %edx       /* Clear PA5 */
        orl     $0x00000500, %edx       /* Set PA5 to WP */
        wrmsr
-       pop     %rdx                    /* RDX contains original PAT value */
-       pop     %rcx
-
-       movq    %rcx, %r9               /* Save kernel length */
-       movq    %rdi, %r10              /* Save encrypted kernel address */
-       movq    %rsi, %r11              /* Save decrypted kernel address */
 
        wbinvd                          /* Invalidate any cache entries */
 
-       /* Copy/encrypt 2MB at a time */
+       /* Copy/encrypt up to 2MB at a time */
+       movq    $PMD_PAGE_SIZE, %r12
 1:
-       movq    %r11, %rsi              /* Source - decrypted kernel */
+       cmpq    %r12, %r9
+       jnb     2f
+       movq    %r9, %r12
+
+2:
+       movq    %r11, %rsi              /* Source - decrypted area */
        movq    %r8, %rdi               /* Dest   - intermediate copy buffer */
-       movq    $PMD_PAGE_SIZE, %rcx    /* 2MB length */
+       movq    %r12, %rcx
        rep     movsb
 
        movq    %r8, %rsi               /* Source - intermediate copy buffer */
-       movq    %r10, %rdi              /* Dest   - encrypted kernel */
-       movq    $PMD_PAGE_SIZE, %rcx    /* 2MB length */
+       movq    %r10, %rdi              /* Dest   - encrypted area */
+       movq    %r12, %rcx
        rep     movsb
 
-       addq    $PMD_PAGE_SIZE, %r11
-       addq    $PMD_PAGE_SIZE, %r10
-       subq    $PMD_PAGE_SIZE, %r9     /* Kernel length decrement */
+       addq    %r12, %r11
+       addq    %r12, %r10
+       subq    %r12, %r9               /* Kernel length decrement */
        jnz     1b                      /* Kernel length not zero? */
 
        /* Restore PAT register */
-       push    %rdx                    /* Save original PAT value */
        movl    $MSR_IA32_CR_PAT, %ecx
        rdmsr
-       pop     %rdx                    /* Restore original PAT value */
+       mov     %r15, %rdx              /* Restore original PAT value */
        wrmsr
 
+       pop     %r12
+       pop     %r15
+
        ret
 .L__enc_copy_end:
 ENDPROC(__enc_copy)
index 8193b38a1cae7a8d738fb4c29828654dd02f0572..3c09122bf03825b6489a16b8f116bd05485aa1b4 100644 (file)
@@ -4449,6 +4449,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
         * https://bugzilla.kernel.org/show_bug.cgi?id=121671
         */
        { "LITEON CX1-JB*-HP",  NULL,           ATA_HORKAGE_MAX_SEC_1024 },
+       { "LITEON EP1-*",       NULL,           ATA_HORKAGE_MAX_SEC_1024 },
 
        /* Devices we expect to fail diagnostics */
 
index 02d78f6cecbb5b9a3e4f72c4315757c3bd879211..ba8acca036df27479a4d535a81328cd7223fe60f 100644 (file)
@@ -55,7 +55,7 @@ config BCMA_DRIVER_PCI
 
 config BCMA_DRIVER_PCI_HOSTMODE
        bool "Driver for PCI core working in hostmode"
-       depends on MIPS && BCMA_DRIVER_PCI
+       depends on MIPS && BCMA_DRIVER_PCI && PCI_DRIVERS_LEGACY
        help
          PCI core hostmode operation (external PCI bus).
 
index f9042bcc27a4a880a28a2c587e9067f9898ce517..7b14d6280e44401d5629034cff5a38b4a8685d72 100644 (file)
@@ -152,14 +152,13 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,
 {
        unsigned long get_mask = 0;
        unsigned long set_mask = 0;
-       int bit = 0;
 
-       while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) {
-               if (gc->bgpio_dir & BIT(bit))
-                       set_mask |= BIT(bit);
-               else
-                       get_mask |= BIT(bit);
-       }
+       /* Make sure we first clear any bits that are zero when we read the register */
+       *bits &= ~*mask;
+
+       /* Exploit the fact that we know which directions are set */
+       set_mask = *mask & gc->bgpio_dir;
+       get_mask = *mask & ~gc->bgpio_dir;
 
        if (set_mask)
                *bits |= gc->read_reg(gc->reg_set) & set_mask;
@@ -176,13 +175,13 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
 
 /*
  * This only works if the bits in the GPIO register are in native endianness.
- * It is dirt simple and fast in this case. (Also the most common case.)
  */
 static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask,
                              unsigned long *bits)
 {
-
-       *bits = gc->read_reg(gc->reg_dat) & *mask;
+       /* Make sure we first clear any bits that are zero when we read the register */
+       *bits &= ~*mask;
+       *bits |= gc->read_reg(gc->reg_dat) & *mask;
        return 0;
 }
 
@@ -196,9 +195,12 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
        unsigned long val;
        int bit;
 
+       /* Make sure we first clear any bits that are zero when we read the register */
+       *bits &= ~*mask;
+
        /* Create a mirrored mask */
-       bit = 0;
-       while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio)
+       bit = -1;
+       while ((bit = find_next_bit(mask, gc->ngpio, bit + 1)) < gc->ngpio)
                readmask |= bgpio_line2mask(gc, bit);
 
        /* Read the register */
@@ -208,8 +210,8 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
         * Mirror the result into the "bits" result, this will give line 0
         * in bit 0 ... line 31 in bit 31 for a 32bit register.
         */
-       bit = 0;
-       while ((bit = find_next_bit(&val, gc->ngpio, bit)) != gc->ngpio)
+       bit = -1;
+       while ((bit = find_next_bit(&val, gc->ngpio, bit + 1)) < gc->ngpio)
                *bits |= bgpio_line2mask(gc, bit);
 
        return 0;
index 123585eeb87db849d84e78b0892e10f962b14d9b..50f8443641b8b59e3fd39c34960b52f9dab5a9a1 100644 (file)
@@ -1211,23 +1211,6 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)
             pipe_name(pipe));
 }
 
-static void assert_cursor(struct drm_i915_private *dev_priv,
-                         enum pipe pipe, bool state)
-{
-       bool cur_state;
-
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
-               cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
-       else
-               cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
-
-       I915_STATE_WARN(cur_state != state,
-            "cursor on pipe %c assertion failure (expected %s, current %s)\n",
-                       pipe_name(pipe), onoff(state), onoff(cur_state));
-}
-#define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
-#define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
-
 void assert_pipe(struct drm_i915_private *dev_priv,
                 enum pipe pipe, bool state)
 {
@@ -1255,77 +1238,25 @@ void assert_pipe(struct drm_i915_private *dev_priv,
                        pipe_name(pipe), onoff(state), onoff(cur_state));
 }
 
-static void assert_plane(struct drm_i915_private *dev_priv,
-                        enum plane plane, bool state)
+static void assert_plane(struct intel_plane *plane, bool state)
 {
-       u32 val;
-       bool cur_state;
+       bool cur_state = plane->get_hw_state(plane);
 
-       val = I915_READ(DSPCNTR(plane));
-       cur_state = !!(val & DISPLAY_PLANE_ENABLE);
        I915_STATE_WARN(cur_state != state,
-            "plane %c assertion failure (expected %s, current %s)\n",
-                       plane_name(plane), onoff(state), onoff(cur_state));
+                       "%s assertion failure (expected %s, current %s)\n",
+                       plane->base.name, onoff(state), onoff(cur_state));
 }
 
-#define assert_plane_enabled(d, p) assert_plane(d, p, true)
-#define assert_plane_disabled(d, p) assert_plane(d, p, false)
-
-static void assert_planes_disabled(struct drm_i915_private *dev_priv,
-                                  enum pipe pipe)
-{
-       int i;
-
-       /* Primary planes are fixed to pipes on gen4+ */
-       if (INTEL_GEN(dev_priv) >= 4) {
-               u32 val = I915_READ(DSPCNTR(pipe));
-               I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
-                    "plane %c assertion failure, should be disabled but not\n",
-                    plane_name(pipe));
-               return;
-       }
+#define assert_plane_enabled(p) assert_plane(p, true)
+#define assert_plane_disabled(p) assert_plane(p, false)
 
-       /* Need to check both planes against the pipe */
-       for_each_pipe(dev_priv, i) {
-               u32 val = I915_READ(DSPCNTR(i));
-               enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
-                       DISPPLANE_SEL_PIPE_SHIFT;
-               I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
-                    "plane %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(i), pipe_name(pipe));
-       }
-}
-
-static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
-                                   enum pipe pipe)
+static void assert_planes_disabled(struct intel_crtc *crtc)
 {
-       int sprite;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_plane *plane;
 
-       if (INTEL_GEN(dev_priv) >= 9) {
-               for_each_sprite(dev_priv, pipe, sprite) {
-                       u32 val = I915_READ(PLANE_CTL(pipe, sprite));
-                       I915_STATE_WARN(val & PLANE_CTL_ENABLE,
-                            "plane %d assertion failure, should be off on pipe %c but is still active\n",
-                            sprite, pipe_name(pipe));
-               }
-       } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               for_each_sprite(dev_priv, pipe, sprite) {
-                       u32 val = I915_READ(SPCNTR(pipe, PLANE_SPRITE0 + sprite));
-                       I915_STATE_WARN(val & SP_ENABLE,
-                            "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                            sprite_name(pipe, sprite), pipe_name(pipe));
-               }
-       } else if (INTEL_GEN(dev_priv) >= 7) {
-               u32 val = I915_READ(SPRCTL(pipe));
-               I915_STATE_WARN(val & SPRITE_ENABLE,
-                    "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(pipe), pipe_name(pipe));
-       } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
-               u32 val = I915_READ(DVSCNTR(pipe));
-               I915_STATE_WARN(val & DVS_ENABLE,
-                    "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(pipe), pipe_name(pipe));
-       }
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane)
+               assert_plane_disabled(plane);
 }
 
 static void assert_vblank_disabled(struct drm_crtc *crtc)
@@ -1918,9 +1849,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
 
        DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
 
-       assert_planes_disabled(dev_priv, pipe);
-       assert_cursor_disabled(dev_priv, pipe);
-       assert_sprites_disabled(dev_priv, pipe);
+       assert_planes_disabled(crtc);
 
        /*
         * A pipe without a PLL won't actually be able to drive bits from
@@ -1989,9 +1918,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
         * Make sure planes won't keep trying to pump pixels to us,
         * or we might hang the display.
         */
-       assert_planes_disabled(dev_priv, pipe);
-       assert_cursor_disabled(dev_priv, pipe);
-       assert_sprites_disabled(dev_priv, pipe);
+       assert_planes_disabled(crtc);
 
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
@@ -2820,6 +2747,23 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,
                      crtc_state->active_planes);
 }
 
+static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
+                                        struct intel_plane *plane)
+{
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
+       struct intel_plane_state *plane_state =
+               to_intel_plane_state(plane->base.state);
+
+       intel_set_plane_visible(crtc_state, plane_state, false);
+
+       if (plane->id == PLANE_PRIMARY)
+               intel_pre_disable_primary_noatomic(&crtc->base);
+
+       trace_intel_disable_plane(&plane->base, crtc);
+       plane->disable_plane(plane, crtc);
+}
+
 static void
 intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                             struct intel_initial_plane_config *plane_config)
@@ -2877,12 +2821,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
         * simplest solution is to just disable the primary plane now and
         * pretend the BIOS never had it enabled.
         */
-       intel_set_plane_visible(to_intel_crtc_state(crtc_state),
-                               to_intel_plane_state(plane_state),
-                               false);
-       intel_pre_disable_primary_noatomic(&intel_crtc->base);
-       trace_intel_disable_plane(primary, intel_crtc);
-       intel_plane->disable_plane(intel_plane, intel_crtc);
+       intel_plane_disable_noatomic(intel_crtc, intel_plane);
 
        return;
 
@@ -3385,6 +3324,31 @@ static void i9xx_disable_primary_plane(struct intel_plane *primary,
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static bool i9xx_plane_get_hw_state(struct intel_plane *primary)
+{
+
+       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum plane plane = primary->plane;
+       enum pipe pipe = primary->pipe;
+       bool ret;
+
+       /*
+        * Not 100% correct for planes that can move between pipes,
+        * but that's only the case for gen2-4 which don't have any
+        * display power wells.
+        */
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32
 intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane)
 {
@@ -4866,7 +4830,8 @@ void hsw_enable_ips(struct intel_crtc *crtc)
         * a vblank wait.
         */
 
-       assert_plane_enabled(dev_priv, crtc->plane);
+       assert_plane_enabled(to_intel_plane(crtc->base.primary));
+
        if (IS_BROADWELL(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL,
@@ -4899,7 +4864,8 @@ void hsw_disable_ips(struct intel_crtc *crtc)
        if (!crtc->config->ips_enabled)
                return;
 
-       assert_plane_enabled(dev_priv, crtc->plane);
+       assert_plane_enabled(to_intel_plane(crtc->base.primary));
+
        if (IS_BROADWELL(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
@@ -5899,6 +5865,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        enum intel_display_power_domain domain;
+       struct intel_plane *plane;
        u64 domains;
        struct drm_atomic_state *state;
        struct intel_crtc_state *crtc_state;
@@ -5907,11 +5874,12 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
        if (!intel_crtc->active)
                return;
 
-       if (crtc->primary->state->visible) {
-               intel_pre_disable_primary_noatomic(crtc);
+       for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) {
+               const struct intel_plane_state *plane_state =
+                       to_intel_plane_state(plane->base.state);
 
-               intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
-               crtc->primary->state->visible = false;
+               if (plane_state->base.visible)
+                       intel_plane_disable_noatomic(intel_crtc, plane);
        }
 
        state = drm_atomic_state_alloc(crtc->dev);
@@ -9477,6 +9445,23 @@ static void i845_disable_cursor(struct intel_plane *plane,
        i845_update_cursor(plane, NULL, NULL);
 }
 
+static bool i845_cursor_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(PIPE_A);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
                           const struct intel_plane_state *plane_state)
 {
@@ -9670,6 +9655,28 @@ static void i9xx_disable_cursor(struct intel_plane *plane,
        i9xx_update_cursor(plane, NULL, NULL);
 }
 
+static bool i9xx_cursor_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       /*
+        * Not 100% correct for planes that can move between pipes,
+        * but that's only the case for gen2-3 which don't have any
+        * display power wells.
+        */
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
 
 /* VESA 640x480x72Hz mode to set on the pipe */
 static const struct drm_display_mode load_detect_mode = {
@@ -13205,6 +13212,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
                primary->update_plane = skl_update_plane;
                primary->disable_plane = skl_disable_plane;
+               primary->get_hw_state = skl_plane_get_hw_state;
        } else if (INTEL_GEN(dev_priv) >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
@@ -13215,6 +13223,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
                primary->update_plane = skl_update_plane;
                primary->disable_plane = skl_disable_plane;
+               primary->get_hw_state = skl_plane_get_hw_state;
        } else if (INTEL_GEN(dev_priv) >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
@@ -13222,6 +13231,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
                primary->update_plane = i9xx_update_primary_plane;
                primary->disable_plane = i9xx_disable_primary_plane;
+               primary->get_hw_state = i9xx_plane_get_hw_state;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
@@ -13229,6 +13239,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
                primary->update_plane = i9xx_update_primary_plane;
                primary->disable_plane = i9xx_disable_primary_plane;
+               primary->get_hw_state = i9xx_plane_get_hw_state;
        }
 
        if (INTEL_GEN(dev_priv) >= 9)
@@ -13318,10 +13329,12 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
                cursor->update_plane = i845_update_cursor;
                cursor->disable_plane = i845_disable_cursor;
+               cursor->get_hw_state = i845_cursor_get_hw_state;
                cursor->check_plane = i845_check_cursor;
        } else {
                cursor->update_plane = i9xx_update_cursor;
                cursor->disable_plane = i9xx_disable_cursor;
+               cursor->get_hw_state = i9xx_cursor_get_hw_state;
                cursor->check_plane = i9xx_check_cursor;
        }
 
@@ -14671,8 +14684,11 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
        DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n",
                      pipe_name(pipe));
 
-       assert_plane_disabled(dev_priv, PLANE_A);
-       assert_plane_disabled(dev_priv, PLANE_B);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_A)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_B)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_C)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(CURCNTR(PIPE_A)) & CURSOR_MODE);
+       WARN_ON(I915_READ(CURCNTR(PIPE_B)) & CURSOR_MODE);
 
        I915_WRITE(PIPECONF(pipe), 0);
        POSTING_READ(PIPECONF(pipe));
@@ -14683,22 +14699,36 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
        POSTING_READ(DPLL(pipe));
 }
 
-static bool
-intel_check_plane_mapping(struct intel_crtc *crtc)
+static bool intel_plane_mapping_ok(struct intel_crtc *crtc,
+                                  struct intel_plane *primary)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       u32 val;
+       enum plane plane = primary->plane;
+       u32 val = I915_READ(DSPCNTR(plane));
 
-       if (INTEL_INFO(dev_priv)->num_pipes == 1)
-               return true;
+       return (val & DISPLAY_PLANE_ENABLE) == 0 ||
+               (val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe);
+}
 
-       val = I915_READ(DSPCNTR(!crtc->plane));
+static void
+intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv)
+{
+       struct intel_crtc *crtc;
 
-       if ((val & DISPLAY_PLANE_ENABLE) &&
-           (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
-               return false;
+       if (INTEL_GEN(dev_priv) >= 4)
+               return;
 
-       return true;
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               struct intel_plane *plane =
+                       to_intel_plane(crtc->base.primary);
+
+               if (intel_plane_mapping_ok(crtc, plane))
+                       continue;
+
+               DRM_DEBUG_KMS("%s attached to the wrong pipe, disabling plane\n",
+                             plane->base.name);
+               intel_plane_disable_noatomic(crtc, plane);
+       }
 }
 
 static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
@@ -14754,33 +14784,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
 
                /* Disable everything but the primary plane */
                for_each_intel_plane_on_crtc(dev, crtc, plane) {
-                       if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
-                               continue;
+                       const struct intel_plane_state *plane_state =
+                               to_intel_plane_state(plane->base.state);
 
-                       trace_intel_disable_plane(&plane->base, crtc);
-                       plane->disable_plane(plane, crtc);
+                       if (plane_state->base.visible &&
+                           plane->base.type != DRM_PLANE_TYPE_PRIMARY)
+                               intel_plane_disable_noatomic(crtc, plane);
                }
        }
 
-       /* We need to sanitize the plane -> pipe mapping first because this will
-        * disable the crtc (and hence change the state) if it is wrong. Note
-        * that gen4+ has a fixed plane -> pipe mapping.  */
-       if (INTEL_GEN(dev_priv) < 4 && !intel_check_plane_mapping(crtc)) {
-               bool plane;
-
-               DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n",
-                             crtc->base.base.id, crtc->base.name);
-
-               /* Pipe has the wrong plane attached and the plane is active.
-                * Temporarily change the plane mapping and disable everything
-                * ...  */
-               plane = crtc->plane;
-               crtc->base.primary->state->visible = true;
-               crtc->plane = !plane;
-               intel_crtc_disable_noatomic(&crtc->base, ctx);
-               crtc->plane = plane;
-       }
-
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
        if (crtc->active && !intel_crtc_has_encoders(crtc))
@@ -14885,24 +14897,21 @@ void i915_redisable_vga(struct drm_i915_private *dev_priv)
        intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 }
 
-static bool primary_get_hw_state(struct intel_plane *plane)
-{
-       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-
-       return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
-}
-
 /* FIXME read out full plane state for all planes */
 static void readout_plane_state(struct intel_crtc *crtc)
 {
-       struct intel_plane *primary = to_intel_plane(crtc->base.primary);
-       bool visible;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
+       struct intel_plane *plane;
 
-       visible = crtc->active && primary_get_hw_state(primary);
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
+               struct intel_plane_state *plane_state =
+                       to_intel_plane_state(plane->base.state);
+               bool visible = plane->get_hw_state(plane);
 
-       intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
-                               to_intel_plane_state(primary->base.state),
-                               visible);
+               intel_set_plane_visible(crtc_state, plane_state, visible);
+       }
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15100,6 +15109,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
        /* HW state is read out, now we need to sanitize this mess. */
        get_encoder_power_domains(dev_priv);
 
+       intel_sanitize_plane_mapping(dev_priv);
+
        for_each_intel_encoder(dev, encoder) {
                intel_sanitize_encoder(encoder);
        }
index 6c7f8bca574eb4414f9a1d95894a5e10c25882b5..5d77f75a9f9ce7c886e6aeaea15029bdc57d09b9 100644 (file)
@@ -862,6 +862,7 @@ struct intel_plane {
                             const struct intel_plane_state *plane_state);
        void (*disable_plane)(struct intel_plane *plane,
                              struct intel_crtc *crtc);
+       bool (*get_hw_state)(struct intel_plane *plane);
        int (*check_plane)(struct intel_plane *plane,
                           struct intel_crtc_state *crtc_state,
                           struct intel_plane_state *state);
@@ -1924,6 +1925,7 @@ void skl_update_plane(struct intel_plane *plane,
                      const struct intel_crtc_state *crtc_state,
                      const struct intel_plane_state *plane_state);
 void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc);
+bool skl_plane_get_hw_state(struct intel_plane *plane);
 
 /* intel_tv.c */
 void intel_tv_init(struct drm_i915_private *dev_priv);
index 4fcf80ca91dd488eefd68f534e633971e60d7917..4a8a5d918a839b586e4e1d5b2f64499e6c456921 100644 (file)
@@ -329,6 +329,26 @@ skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+bool
+skl_plane_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(PLANE_CTL(pipe, plane_id)) & PLANE_CTL_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static void
 chv_update_csc(struct intel_plane *plane, uint32_t format)
 {
@@ -506,6 +526,26 @@ vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static bool
+vlv_plane_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(SPCNTR(pipe, plane_id)) & SP_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
                          const struct intel_plane_state *plane_state)
 {
@@ -646,6 +686,25 @@ ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static bool
+ivb_plane_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret =  I915_READ(SPRCTL(pipe)) & SPRITE_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
                          const struct intel_plane_state *plane_state)
 {
@@ -777,6 +836,25 @@ g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static bool
+g4x_plane_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(DVSCNTR(pipe)) & DVS_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static int
 intel_check_sprite_plane(struct intel_plane *plane,
                         struct intel_crtc_state *crtc_state,
@@ -1232,6 +1310,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
                intel_plane->update_plane = skl_update_plane;
                intel_plane->disable_plane = skl_disable_plane;
+               intel_plane->get_hw_state = skl_plane_get_hw_state;
 
                plane_formats = skl_plane_formats;
                num_plane_formats = ARRAY_SIZE(skl_plane_formats);
@@ -1242,6 +1321,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
                intel_plane->update_plane = skl_update_plane;
                intel_plane->disable_plane = skl_disable_plane;
+               intel_plane->get_hw_state = skl_plane_get_hw_state;
 
                plane_formats = skl_plane_formats;
                num_plane_formats = ARRAY_SIZE(skl_plane_formats);
@@ -1252,6 +1332,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
                intel_plane->update_plane = vlv_update_plane;
                intel_plane->disable_plane = vlv_disable_plane;
+               intel_plane->get_hw_state = vlv_plane_get_hw_state;
 
                plane_formats = vlv_plane_formats;
                num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
@@ -1267,6 +1348,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
                intel_plane->update_plane = ivb_update_plane;
                intel_plane->disable_plane = ivb_disable_plane;
+               intel_plane->get_hw_state = ivb_plane_get_hw_state;
 
                plane_formats = snb_plane_formats;
                num_plane_formats = ARRAY_SIZE(snb_plane_formats);
@@ -1277,6 +1359,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
                intel_plane->update_plane = g4x_update_plane;
                intel_plane->disable_plane = g4x_disable_plane;
+               intel_plane->get_hw_state = g4x_plane_get_hw_state;
 
                modifiers = i9xx_plane_format_modifiers;
                if (IS_GEN6(dev_priv)) {
index 0760b93e9d1fd84a7833c3247a2bc4e9cec069e7..baab93398e54a51f84a1cac5fb71af629d52b2eb 100644 (file)
@@ -121,6 +121,7 @@ int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int g84_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
+int mcp77_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gk104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gk20a_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
index 435ff8662cfa823a56f5d84a8fe66d4bc8929230..ef687414969ee94c65dae3df12009f2f70fec1e2 100644 (file)
@@ -1447,11 +1447,13 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
                                args.nv50.ro = 0;
                                args.nv50.kind = mem->kind;
                                args.nv50.comp = mem->comp;
+                               argc = sizeof(args.nv50);
                                break;
                        case NVIF_CLASS_MEM_GF100:
                                args.gf100.version = 0;
                                args.gf100.ro = 0;
                                args.gf100.kind = mem->kind;
+                               argc = sizeof(args.gf100);
                                break;
                        default:
                                WARN_ON(1);
@@ -1459,7 +1461,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
                        }
 
                        ret = nvif_object_map_handle(&mem->mem.object,
-                                                    &argc, argc,
+                                                    &args, argc,
                                                     &handle, &length);
                        if (ret != 1)
                                return ret ? ret : -EINVAL;
index 00eeaaffeae565a04044fc55e52990eb71d1063b..08e77cd55e6e46a20f5c089fddc0308ee9e9ca19 100644 (file)
@@ -1251,7 +1251,7 @@ nvaa_chipset = {
        .i2c = g94_i2c_new,
        .imem = nv50_instmem_new,
        .mc = g98_mc_new,
-       .mmu = g84_mmu_new,
+       .mmu = mcp77_mmu_new,
        .mxm = nv50_mxm_new,
        .pci = g94_pci_new,
        .therm = g84_therm_new,
@@ -1283,7 +1283,7 @@ nvac_chipset = {
        .i2c = g94_i2c_new,
        .imem = nv50_instmem_new,
        .mc = g98_mc_new,
-       .mmu = g84_mmu_new,
+       .mmu = mcp77_mmu_new,
        .mxm = nv50_mxm_new,
        .pci = g94_pci_new,
        .therm = g84_therm_new,
index 9646adec57cbc169cff79363a8d1e4be6ec4accf..243f0a5c8a62530007c7815d226d46b3fb7f0fbd 100644 (file)
@@ -73,7 +73,8 @@ static int
 nvkm_bar_fini(struct nvkm_subdev *subdev, bool suspend)
 {
        struct nvkm_bar *bar = nvkm_bar(subdev);
-       bar->func->bar1.fini(bar);
+       if (bar->func->bar1.fini)
+               bar->func->bar1.fini(bar);
        return 0;
 }
 
index b10077d38839b6ce314edfa64bb9692c2a3ba61c..35878fb538f2c58fb1116c367c2314b3a391e7bd 100644 (file)
@@ -26,7 +26,6 @@ gk20a_bar_func = {
        .dtor = gf100_bar_dtor,
        .oneinit = gf100_bar_oneinit,
        .bar1.init = gf100_bar_bar1_init,
-       .bar1.fini = gf100_bar_bar1_fini,
        .bar1.wait = gf100_bar_bar1_wait,
        .bar1.vmm = gf100_bar_bar1_vmm,
        .flush = g84_bar_flush,
index 352a65f9371cdcc42386d5e09d2bdb4a014c23c4..67ee983bb026a31040ae6cf02534ab47e599cfb1 100644 (file)
@@ -4,6 +4,7 @@ nvkm-y += nvkm/subdev/mmu/nv41.o
 nvkm-y += nvkm/subdev/mmu/nv44.o
 nvkm-y += nvkm/subdev/mmu/nv50.o
 nvkm-y += nvkm/subdev/mmu/g84.o
+nvkm-y += nvkm/subdev/mmu/mcp77.o
 nvkm-y += nvkm/subdev/mmu/gf100.o
 nvkm-y += nvkm/subdev/mmu/gk104.o
 nvkm-y += nvkm/subdev/mmu/gk20a.o
@@ -22,6 +23,7 @@ nvkm-y += nvkm/subdev/mmu/vmmnv04.o
 nvkm-y += nvkm/subdev/mmu/vmmnv41.o
 nvkm-y += nvkm/subdev/mmu/vmmnv44.o
 nvkm-y += nvkm/subdev/mmu/vmmnv50.o
+nvkm-y += nvkm/subdev/mmu/vmmmcp77.o
 nvkm-y += nvkm/subdev/mmu/vmmgf100.o
 nvkm-y += nvkm/subdev/mmu/vmmgk104.o
 nvkm-y += nvkm/subdev/mmu/vmmgk20a.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mcp77.c
new file mode 100644 (file)
index 0000000..0527b50
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mem.h"
+#include "vmm.h"
+
+#include <nvif/class.h>
+
+static const struct nvkm_mmu_func
+mcp77_mmu = {
+       .dma_bits = 40,
+       .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV50}},
+       .mem = {{ -1,  0, NVIF_CLASS_MEM_NV50}, nv50_mem_new, nv50_mem_map },
+       .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV50}, mcp77_vmm_new, false, 0x0200 },
+       .kind = nv50_mmu_kind,
+       .kind_sys = true,
+};
+
+int
+mcp77_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+       return nvkm_mmu_new_(&mcp77_mmu, device, index, pmmu);
+}
index 6d8f61ea467affe73af5137e5c652e0786105eaa..da06e64d8a7d170074fcaadd0657e3971e07a027 100644 (file)
@@ -95,6 +95,9 @@ struct nvkm_vmm_desc {
        const struct nvkm_vmm_desc_func *func;
 };
 
+extern const struct nvkm_vmm_desc nv50_vmm_desc_12[];
+extern const struct nvkm_vmm_desc nv50_vmm_desc_16[];
+
 extern const struct nvkm_vmm_desc gk104_vmm_desc_16_12[];
 extern const struct nvkm_vmm_desc gk104_vmm_desc_16_16[];
 extern const struct nvkm_vmm_desc gk104_vmm_desc_17_12[];
@@ -169,6 +172,11 @@ int nv04_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32,
                  const char *, struct nvkm_vmm **);
 int nv04_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
 
+int nv50_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
+void nv50_vmm_part(struct nvkm_vmm *, struct nvkm_memory *);
+int nv50_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
+void nv50_vmm_flush(struct nvkm_vmm *, int);
+
 int gf100_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *,
                   struct nvkm_mmu *, u64, u64, void *, u32,
                   struct lock_class_key *, const char *, struct nvkm_vmm **);
@@ -200,6 +208,8 @@ int nv44_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
                 struct lock_class_key *, const char *, struct nvkm_vmm **);
 int nv50_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
                 struct lock_class_key *, const char *, struct nvkm_vmm **);
+int mcp77_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
+                 struct lock_class_key *, const char *, struct nvkm_vmm **);
 int g84_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
                struct lock_class_key *, const char *, struct nvkm_vmm **);
 int gf100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmmcp77.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmmcp77.c
new file mode 100644 (file)
index 0000000..e63d984
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "vmm.h"
+
+static const struct nvkm_vmm_func
+mcp77_vmm = {
+       .join = nv50_vmm_join,
+       .part = nv50_vmm_part,
+       .valid = nv50_vmm_valid,
+       .flush = nv50_vmm_flush,
+       .page_block = 1 << 29,
+       .page = {
+               { 16, &nv50_vmm_desc_16[0], NVKM_VMM_PAGE_xVxx },
+               { 12, &nv50_vmm_desc_12[0], NVKM_VMM_PAGE_xVHx },
+               {}
+       }
+};
+
+int
+mcp77_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
+             struct lock_class_key *key, const char *name,
+             struct nvkm_vmm **pvmm)
+{
+       return nv04_vmm_new_(&mcp77_vmm, mmu, 0, addr, size,
+                            argv, argc, key, name, pvmm);
+}
index 863a2edd98616cbb6349204dce73990048d99450..64f75d90620201e1a66f65744c94bb6fdc0fb9a0 100644 (file)
@@ -32,7 +32,7 @@ static inline void
 nv50_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
                 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
 {
-       u64 next = addr | map->type, data;
+       u64 next = addr + map->type, data;
        u32 pten;
        int log2blk;
 
@@ -69,7 +69,7 @@ nv50_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
                VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes);
                nvkm_kmap(pt->memory);
                while (ptes--) {
-                       const u64 data = *map->dma++ | map->type;
+                       const u64 data = *map->dma++ + map->type;
                        VMM_WO064(pt, vmm, ptei++ * 8, data);
                        map->type += map->ctag;
                }
@@ -163,21 +163,21 @@ nv50_vmm_pgd = {
        .pde = nv50_vmm_pgd_pde,
 };
 
-static const struct nvkm_vmm_desc
+const struct nvkm_vmm_desc
 nv50_vmm_desc_12[] = {
        { PGT, 17, 8, 0x1000, &nv50_vmm_pgt },
        { PGD, 11, 0, 0x0000, &nv50_vmm_pgd },
        {}
 };
 
-static const struct nvkm_vmm_desc
+const struct nvkm_vmm_desc
 nv50_vmm_desc_16[] = {
        { PGT, 13, 8, 0x1000, &nv50_vmm_pgt },
        { PGD, 11, 0, 0x0000, &nv50_vmm_pgd },
        {}
 };
 
-static void
+void
 nv50_vmm_flush(struct nvkm_vmm *vmm, int level)
 {
        struct nvkm_subdev *subdev = &vmm->mmu->subdev;
@@ -223,7 +223,7 @@ nv50_vmm_flush(struct nvkm_vmm *vmm, int level)
        mutex_unlock(&subdev->mutex);
 }
 
-static int
+int
 nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
               struct nvkm_vmm_map *map)
 {
@@ -321,7 +321,7 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        return 0;
 }
 
-static void
+void
 nv50_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
 {
        struct nvkm_vmm_join *join;
@@ -335,7 +335,7 @@ nv50_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
        }
 }
 
-static int
+int
 nv50_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
 {
        const u32 pd_offset = vmm->mmu->func->vmm.pd_offset;
index dc332ea56f6c757e7f5b9e54331986698ebc31fc..3ecffa52c81466f6998575cf87b830a353478c72 100644 (file)
@@ -102,10 +102,13 @@ static int sun4i_tmds_determine_rate(struct clk_hw *hw,
                                        goto out;
                                }
 
-                               if (abs(rate - rounded / i) <
-                                   abs(rate - best_parent / best_div)) {
+                               if (!best_parent ||
+                                   abs(rate - rounded / i / j) <
+                                   abs(rate - best_parent / best_half /
+                                       best_div)) {
                                        best_parent = rounded;
-                                       best_div = i;
+                                       best_half = i;
+                                       best_div = j;
                                }
                        }
                }
index 641294aef1652e1d8599016090aacd4bb33364b0..fcd58145d0dacede735bc53dc4fce40c8bb9063c 100644 (file)
@@ -1863,7 +1863,7 @@ u32 vmw_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
  */
 int vmw_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
-       return -ENOSYS;
+       return -EINVAL;
 }
 
 /**
index b8a09807c5de8ebd447af97a56465323672d33d2..3824595fece126136be84e3fe614028d8b14124a 100644 (file)
@@ -266,8 +266,8 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
        .set_property = vmw_du_connector_set_property,
        .destroy = vmw_ldu_connector_destroy,
        .reset = vmw_du_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+       .atomic_duplicate_state = vmw_du_connector_duplicate_state,
+       .atomic_destroy_state = vmw_du_connector_destroy_state,
        .atomic_set_property = vmw_du_connector_atomic_set_property,
        .atomic_get_property = vmw_du_connector_atomic_get_property,
 };
index bc5f6026573da9dacbc09f2b8fe8a2d62ee24ded..63a4cd794b73a12821ea8adbfb72e997367c5193 100644 (file)
@@ -420,8 +420,8 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
        .set_property = vmw_du_connector_set_property,
        .destroy = vmw_sou_connector_destroy,
        .reset = vmw_du_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+       .atomic_duplicate_state = vmw_du_connector_duplicate_state,
+       .atomic_destroy_state = vmw_du_connector_destroy_state,
        .atomic_set_property = vmw_du_connector_atomic_set_property,
        .atomic_get_property = vmw_du_connector_atomic_get_property,
 };
index 706164b4c5be46bf2f98aa5a8ddde44800eeae0e..f7829a74140cf1b764d8ed3f8e00ec4e60f9eaad 100644 (file)
@@ -821,8 +821,12 @@ void i2c_unregister_device(struct i2c_client *client)
 {
        if (!client)
                return;
-       if (client->dev.of_node)
+
+       if (client->dev.of_node) {
                of_node_clear_flag(client->dev.of_node, OF_POPULATED);
+               of_node_put(client->dev.of_node);
+       }
+
        if (ACPI_COMPANION(&client->dev))
                acpi_device_clear_enumerated(ACPI_COMPANION(&client->dev));
        device_unregister(&client->dev);
index 4bb9927afd0106f6cf6de9fd433c0b66b18173aa..a1082c04ac5c63c097ac5b0c2d33a7df741d2070 100644 (file)
@@ -397,16 +397,17 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
                                   the underlying bus driver */
                break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
+               if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+                       dev_err(&adapter->dev, "Invalid block %s size %d\n",
+                               read_write == I2C_SMBUS_READ ? "read" : "write",
+                               data->block[0]);
+                       return -EINVAL;
+               }
+
                if (read_write == I2C_SMBUS_READ) {
                        msg[1].len = data->block[0];
                } else {
                        msg[0].len = data->block[0] + 1;
-                       if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
-                               dev_err(&adapter->dev,
-                                       "Invalid block write size %d\n",
-                                       data->block[0]);
-                               return -EINVAL;
-                       }
                        for (i = 1; i <= data->block[0]; i++)
                                msgbuf0[i] = data->block[i];
                }
index 7750a9c38b066777982c8309d8436b5780235d36..1df7da47f431743306fd9e2283cbba3090aac9c4 100644 (file)
@@ -763,11 +763,11 @@ static int complete_subctxt(struct hfi1_filedata *fd)
        }
 
        if (ret) {
-               hfi1_rcd_put(fd->uctxt);
-               fd->uctxt = NULL;
                spin_lock_irqsave(&fd->dd->uctxt_lock, flags);
                __clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts);
                spin_unlock_irqrestore(&fd->dd->uctxt_lock, flags);
+               hfi1_rcd_put(fd->uctxt);
+               fd->uctxt = NULL;
        }
 
        return ret;
index 8ac50de2b2421ea66cb23eff88c09f8ecf3a0f94..262c1aa2e028aae1e9c9bd7f4a3541105faffa17 100644 (file)
@@ -1324,7 +1324,8 @@ static int mlx5_ib_alloc_transport_domain(struct mlx5_ib_dev *dev, u32 *tdn)
                return err;
 
        if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
-           !MLX5_CAP_GEN(dev->mdev, disable_local_lb))
+           (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
+            !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
                return err;
 
        mutex_lock(&dev->lb_mutex);
@@ -1342,7 +1343,8 @@ static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn)
        mlx5_core_dealloc_transport_domain(dev->mdev, tdn);
 
        if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
-           !MLX5_CAP_GEN(dev->mdev, disable_local_lb))
+           (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
+            !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
                return;
 
        mutex_lock(&dev->lb_mutex);
@@ -4158,7 +4160,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
                goto err_cnt;
 
        dev->mdev->priv.uar = mlx5_get_uars_page(dev->mdev);
-       if (!dev->mdev->priv.uar)
+       if (IS_ERR(dev->mdev->priv.uar))
                goto err_cong;
 
        err = mlx5_alloc_bfreg(dev->mdev, &dev->bfreg, false, false);
@@ -4187,7 +4189,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
        }
 
        if ((MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
-           MLX5_CAP_GEN(mdev, disable_local_lb))
+           (MLX5_CAP_GEN(mdev, disable_local_lb_uc) ||
+            MLX5_CAP_GEN(mdev, disable_local_lb_mc)))
                mutex_init(&dev->lb_mutex);
 
        dev->ib_active = true;
index 31ad28853efa9a851580728691cf2f2bbf4e1d75..cffe5966aef97a1c8b4be352b9aa1b103b5426ed 100644 (file)
@@ -4362,12 +4362,11 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev,
 
        memset(ah_attr, 0, sizeof(*ah_attr));
 
-       ah_attr->type = rdma_ah_find_type(&ibdev->ib_dev, path->port);
-       rdma_ah_set_port_num(ah_attr, path->port);
-       if (rdma_ah_get_port_num(ah_attr) == 0 ||
-           rdma_ah_get_port_num(ah_attr) > MLX5_CAP_GEN(dev, num_ports))
+       if (!path->port || path->port > MLX5_CAP_GEN(dev, num_ports))
                return;
 
+       ah_attr->type = rdma_ah_find_type(&ibdev->ib_dev, path->port);
+
        rdma_ah_set_port_num(ah_attr, path->port);
        rdma_ah_set_sl(ah_attr, path->dci_cfi_prio_sl & 0xf);
 
index 720dfb3a1ac271bd16950563006664e83cab6be8..1b02283ce20eff38897f2dcf729924ff6998ff52 100644 (file)
@@ -741,6 +741,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
 
+       ib_drain_qp(isert_conn->qp);
        list_del_init(&isert_conn->node);
        isert_conn->cm_id = NULL;
        isert_put_conn(isert_conn);
index 6c51d404874bbda9dd3e414ed7e644524c13e7c4..c37aea9ac272a1a90dfc82e101f7fa5ecf1b569c 100644 (file)
@@ -178,12 +178,14 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
                         twl4030_vibra_suspend, twl4030_vibra_resume);
 
 static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
-                             struct device_node *node)
+                             struct device_node *parent)
 {
+       struct device_node *node;
+
        if (pdata && pdata->coexist)
                return true;
 
-       node = of_find_node_by_name(node, "codec");
+       node = of_get_child_by_name(parent, "codec");
        if (node) {
                of_node_put(node);
                return true;
index 5690eb7ff954d23390d966d2f5c7137513a68b9f..15e0d352c4cc2445b2fb05636e1e7eb950001d91 100644 (file)
@@ -248,8 +248,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
        int vddvibr_uV = 0;
        int error;
 
-       of_node_get(twl6040_core_dev->of_node);
-       twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node,
+       twl6040_core_node = of_get_child_by_name(twl6040_core_dev->of_node,
                                                 "vibra");
        if (!twl6040_core_node) {
                dev_err(&pdev->dev, "parent of node is missing?\n");
index 579b899add268ebb74499c6ce4272e211116160d..dbe57da8c1a1ba5c9339cd6ac8596d76665c5d9f 100644 (file)
@@ -1250,29 +1250,32 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
        case SS4_PACKET_ID_MULTI:
                if (priv->flags & ALPS_BUTTONPAD) {
                        if (IS_SS4PLUS_DEV(priv->dev_id)) {
-                               f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
-                               f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
+                               f->mt[2].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
+                               f->mt[3].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
+                               no_data_x = SS4_PLUS_MFPACKET_NO_AX_BL;
                        } else {
                                f->mt[2].x = SS4_BTL_MF_X_V2(p, 0);
                                f->mt[3].x = SS4_BTL_MF_X_V2(p, 1);
+                               no_data_x = SS4_MFPACKET_NO_AX_BL;
                        }
+                       no_data_y = SS4_MFPACKET_NO_AY_BL;
 
                        f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0);
                        f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1);
-                       no_data_x = SS4_MFPACKET_NO_AX_BL;
-                       no_data_y = SS4_MFPACKET_NO_AY_BL;
                } else {
                        if (IS_SS4PLUS_DEV(priv->dev_id)) {
-                               f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0);
-                               f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1);
+                               f->mt[2].x = SS4_PLUS_STD_MF_X_V2(p, 0);
+                               f->mt[3].x = SS4_PLUS_STD_MF_X_V2(p, 1);
+                               no_data_x = SS4_PLUS_MFPACKET_NO_AX;
                        } else {
-                               f->mt[0].x = SS4_STD_MF_X_V2(p, 0);
-                               f->mt[1].x = SS4_STD_MF_X_V2(p, 1);
+                               f->mt[2].x = SS4_STD_MF_X_V2(p, 0);
+                               f->mt[3].x = SS4_STD_MF_X_V2(p, 1);
+                               no_data_x = SS4_MFPACKET_NO_AX;
                        }
+                       no_data_y = SS4_MFPACKET_NO_AY;
+
                        f->mt[2].y = SS4_STD_MF_Y_V2(p, 0);
                        f->mt[3].y = SS4_STD_MF_Y_V2(p, 1);
-                       no_data_x = SS4_MFPACKET_NO_AX;
-                       no_data_y = SS4_MFPACKET_NO_AY;
                }
 
                f->first_mp = 0;
index c80a7c76cb767187c13e18c5104042270886e736..79b6d69d1486a2d0b6e9eaf82af08ce7ed919b83 100644 (file)
@@ -141,10 +141,12 @@ enum SS4_PACKET_ID {
 #define SS4_TS_Z_V2(_b)                (s8)(_b[4] & 0x7F)
 
 
-#define SS4_MFPACKET_NO_AX     8160    /* X-Coordinate value */
-#define SS4_MFPACKET_NO_AY     4080    /* Y-Coordinate value */
-#define SS4_MFPACKET_NO_AX_BL  8176    /* Buttonless X-Coordinate value */
-#define SS4_MFPACKET_NO_AY_BL  4088    /* Buttonless Y-Coordinate value */
+#define SS4_MFPACKET_NO_AX             8160    /* X-Coordinate value */
+#define SS4_MFPACKET_NO_AY             4080    /* Y-Coordinate value */
+#define SS4_MFPACKET_NO_AX_BL          8176    /* Buttonless X-Coord value */
+#define SS4_MFPACKET_NO_AY_BL          4088    /* Buttonless Y-Coord value */
+#define SS4_PLUS_MFPACKET_NO_AX                4080    /* SS4 PLUS, X */
+#define SS4_PLUS_MFPACKET_NO_AX_BL     4088    /* Buttonless SS4 PLUS, X */
 
 /*
  * enum V7_PACKET_ID - defines the packet type for V7
index ee5466a374bf0f370000cf002d94bf2514d02318..cd9f61cb3fc67fd3f5f8fe7a55fb1094d5bf1672 100644 (file)
@@ -173,6 +173,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0046", /* X250 */
        "LEN004a", /* W541 */
        "LEN200f", /* T450s */
+       "LEN2018", /* T460p */
        NULL
 };
 
index 4f2bb5947a4ea17123cf5cf12f33279ed7c7e9ff..141ea228aac6a39641c70eb01ff0bf33cd5aaf1f 100644 (file)
@@ -230,8 +230,10 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
                rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
                        "Failed to process interrupt request: %d\n", ret);
 
-       if (count)
+       if (count) {
                kfree(attn_data.data);
+               attn_data.data = NULL;
+       }
 
        if (!kfifo_is_empty(&drvdata->attn_fifo))
                return rmi_irq_fn(irq, dev_id);
index 7ed828a51f4c87883ca4258a5cc1ca9cad375dcc..3486d94038056675b0d00c19630deadebff87b60 100644 (file)
@@ -126,7 +126,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
        int data, n, ret;
        if (!np)
                return -ENODEV;
-       np = of_find_node_by_name(np, "touch");
+       np = of_get_child_by_name(np, "touch");
        if (!np) {
                dev_err(&pdev->dev, "Can't find touch node\n");
                return -EINVAL;
@@ -144,13 +144,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
        if (data) {
                ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
                if (ret < 0)
-                       return -EINVAL;
+                       goto err_put_node;
        }
        /* set tsi prebias time */
        if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
                ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
                if (ret < 0)
-                       return -EINVAL;
+                       goto err_put_node;
        }
        /* set prebias & prechg time of pen detect */
        data = 0;
@@ -161,10 +161,18 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
        if (data) {
                ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
                if (ret < 0)
-                       return -EINVAL;
+                       goto err_put_node;
        }
        of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
+
+       of_node_put(np);
+
        return 0;
+
+err_put_node:
+       of_node_put(np);
+
+       return -EINVAL;
 }
 #else
 #define pm860x_touch_dt_init(x, y, z)  (-1)
index 8d7f9c8f2771c7fe621590346e60060cd7fee55e..9642f103b7268cb79da418d9b65de8d8bfbb8542 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/input.h>
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
+#include <linux/module.h>
 
 static bool touchscreen_get_prop_u32(struct device *dev,
                                     const char *property,
@@ -185,3 +186,6 @@ void touchscreen_report_pos(struct input_dev *input,
        input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
 }
 EXPORT_SYMBOL(touchscreen_report_pos);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Device-tree helpers functions for touchscreen devices");
index 9fc12f556534b71ccbb91848d4eb9dc7395bd8fa..554d60394c0663980d89c3bb84a48007f365470b 100644 (file)
@@ -1954,10 +1954,15 @@ static int crypt_setkey(struct crypt_config *cc)
        /* Ignore extra keys (which are used for IV etc) */
        subkey_size = crypt_subkey_size(cc);
 
-       if (crypt_integrity_hmac(cc))
+       if (crypt_integrity_hmac(cc)) {
+               if (subkey_size < cc->key_mac_size)
+                       return -EINVAL;
+
                crypt_copy_authenckey(cc->authenc_key, cc->key,
                                      subkey_size - cc->key_mac_size,
                                      cc->key_mac_size);
+       }
+
        for (i = 0; i < cc->tfms_count; i++) {
                if (crypt_integrity_hmac(cc))
                        r = crypto_aead_setkey(cc->cipher_tfm.tfms_aead[i],
@@ -2053,9 +2058,6 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
 
        ret = crypt_setkey(cc);
 
-       /* wipe the kernel key payload copy in each case */
-       memset(cc->key, 0, cc->key_size * sizeof(u8));
-
        if (!ret) {
                set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
                kzfree(cc->key_string);
@@ -2523,6 +2525,10 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key)
                }
        }
 
+       /* wipe the kernel key payload copy */
+       if (cc->key_string)
+               memset(cc->key, 0, cc->key_size * sizeof(u8));
+
        return ret;
 }
 
@@ -2740,6 +2746,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                        cc->tag_pool_max_sectors * cc->on_disk_tag_size);
                if (!cc->tag_pool) {
                        ti->error = "Cannot allocate integrity tags mempool";
+                       ret = -ENOMEM;
                        goto bad;
                }
 
@@ -2961,6 +2968,9 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
                                return ret;
                        if (cc->iv_gen_ops && cc->iv_gen_ops->init)
                                ret = cc->iv_gen_ops->init(cc);
+                       /* wipe the kernel key payload copy */
+                       if (cc->key_string)
+                               memset(cc->key, 0, cc->key_size * sizeof(u8));
                        return ret;
                }
                if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
@@ -3007,7 +3017,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 18, 0},
+       .version = {1, 18, 1},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
index 05c7bfd0c9d9a7b06804d01fa3085f6ca67afbd7..46d7c8749222d3e0a8ad43acac6dd62ed5e8b824 100644 (file)
@@ -2559,7 +2559,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
        int r = 0;
        unsigned i;
        __u64 journal_pages, journal_desc_size, journal_tree_size;
-       unsigned char *crypt_data = NULL;
+       unsigned char *crypt_data = NULL, *crypt_iv = NULL;
+       struct skcipher_request *req = NULL;
 
        ic->commit_ids[0] = cpu_to_le64(0x1111111111111111ULL);
        ic->commit_ids[1] = cpu_to_le64(0x2222222222222222ULL);
@@ -2617,9 +2618,20 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
 
                if (blocksize == 1) {
                        struct scatterlist *sg;
-                       SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt);
-                       unsigned char iv[ivsize];
-                       skcipher_request_set_tfm(req, ic->journal_crypt);
+
+                       req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
+                       if (!req) {
+                               *error = "Could not allocate crypt request";
+                               r = -ENOMEM;
+                               goto bad;
+                       }
+
+                       crypt_iv = kmalloc(ivsize, GFP_KERNEL);
+                       if (!crypt_iv) {
+                               *error = "Could not allocate iv";
+                               r = -ENOMEM;
+                               goto bad;
+                       }
 
                        ic->journal_xor = dm_integrity_alloc_page_list(ic);
                        if (!ic->journal_xor) {
@@ -2641,9 +2653,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                sg_set_buf(&sg[i], va, PAGE_SIZE);
                        }
                        sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
-                       memset(iv, 0x00, ivsize);
+                       memset(crypt_iv, 0x00, ivsize);
 
-                       skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, iv);
+                       skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);
                        init_completion(&comp.comp);
                        comp.in_flight = (atomic_t)ATOMIC_INIT(1);
                        if (do_crypt(true, req, &comp))
@@ -2659,10 +2671,22 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                        crypto_free_skcipher(ic->journal_crypt);
                        ic->journal_crypt = NULL;
                } else {
-                       SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt);
-                       unsigned char iv[ivsize];
                        unsigned crypt_len = roundup(ivsize, blocksize);
 
+                       req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
+                       if (!req) {
+                               *error = "Could not allocate crypt request";
+                               r = -ENOMEM;
+                               goto bad;
+                       }
+
+                       crypt_iv = kmalloc(ivsize, GFP_KERNEL);
+                       if (!crypt_iv) {
+                               *error = "Could not allocate iv";
+                               r = -ENOMEM;
+                               goto bad;
+                       }
+
                        crypt_data = kmalloc(crypt_len, GFP_KERNEL);
                        if (!crypt_data) {
                                *error = "Unable to allocate crypt data";
@@ -2670,8 +2694,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                goto bad;
                        }
 
-                       skcipher_request_set_tfm(req, ic->journal_crypt);
-
                        ic->journal_scatterlist = dm_integrity_alloc_journal_scatterlist(ic, ic->journal);
                        if (!ic->journal_scatterlist) {
                                *error = "Unable to allocate sg list";
@@ -2695,12 +2717,12 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                struct skcipher_request *section_req;
                                __u32 section_le = cpu_to_le32(i);
 
-                               memset(iv, 0x00, ivsize);
+                               memset(crypt_iv, 0x00, ivsize);
                                memset(crypt_data, 0x00, crypt_len);
                                memcpy(crypt_data, &section_le, min((size_t)crypt_len, sizeof(section_le)));
 
                                sg_init_one(&sg, crypt_data, crypt_len);
-                               skcipher_request_set_crypt(req, &sg, &sg, crypt_len, iv);
+                               skcipher_request_set_crypt(req, &sg, &sg, crypt_len, crypt_iv);
                                init_completion(&comp.comp);
                                comp.in_flight = (atomic_t)ATOMIC_INIT(1);
                                if (do_crypt(true, req, &comp))
@@ -2758,6 +2780,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
        }
 bad:
        kfree(crypt_data);
+       kfree(crypt_iv);
+       skcipher_request_free(req);
+
        return r;
 }
 
index d31d18d9727c69d555d7971e53ddde6b6c401bf3..36ef284ad086b881324771d4f882dc6fa96d6dde 100644 (file)
 #define SECTOR_TO_BLOCK_SHIFT 3
 
 /*
+ * For btree insert:
  *  3 for btree insert +
  *  2 for btree lookup used within space map
+ * For btree remove:
+ *  2 for shadow spine +
+ *  4 for rebalance 3 child node
  */
-#define THIN_MAX_CONCURRENT_LOCKS 5
+#define THIN_MAX_CONCURRENT_LOCKS 6
 
 /* This should be plenty */
 #define SPACE_MAP_ROOT_SIZE 128
index f21ce6a3d4cf563ed7b768f65f7452e55af99826..58b319757b1e5a1c274bd98681d6ce229bbbabbe 100644 (file)
@@ -683,23 +683,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
        pn->keys[1] = rn->keys[0];
        memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
 
-       /*
-        * rejig the spine.  This is ugly, since it knows too
-        * much about the spine
-        */
-       if (s->nodes[0] != new_parent) {
-               unlock_block(s->info, s->nodes[0]);
-               s->nodes[0] = new_parent;
-       }
-       if (key < le64_to_cpu(rn->keys[0])) {
-               unlock_block(s->info, right);
-               s->nodes[1] = left;
-       } else {
-               unlock_block(s->info, left);
-               s->nodes[1] = right;
-       }
-       s->count = 2;
-
+       unlock_block(s->info, left);
+       unlock_block(s->info, right);
        return 0;
 }
 
index 85140c9af58129784c2c8ed338f9540e12905ae1..8b941f814472f871a74cdb32058700f1311f2b5a 100644 (file)
@@ -687,6 +687,20 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
                return;
        }
 
+       /* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */
+       if (is_imx53_esdhc(imx_data)) {
+               /*
+                * According to the i.MX53 reference manual, if DLLCTRL[10] can
+                * be set, then the controller is eSDHCv3, else it is eSDHCv2.
+                */
+               val = readl(host->ioaddr + ESDHC_DLL_CTRL);
+               writel(val | BIT(10), host->ioaddr + ESDHC_DLL_CTRL);
+               temp = readl(host->ioaddr + ESDHC_DLL_CTRL);
+               writel(val, host->ioaddr + ESDHC_DLL_CTRL);
+               if (temp & BIT(10))
+                       pre_div = 2;
+       }
+
        temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
        temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
                | ESDHC_CLOCK_MASK);
index 7ccdc3e30c98c25d238d0a124ffb854675b1732c..53d6bb045e9e91193452320b9e6cc5226849c1da 100644 (file)
@@ -184,7 +184,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
        void *cmd_head = pcan_usb_fd_cmd_buffer(dev);
        int err = 0;
        u8 *packet_ptr;
-       int i, n = 1, packet_len;
+       int packet_len;
        ptrdiff_t cmd_len;
 
        /* usb device unregistered? */
@@ -201,17 +201,13 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
        }
 
        packet_ptr = cmd_head;
+       packet_len = cmd_len;
 
        /* firmware is not able to re-assemble 512 bytes buffer in full-speed */
-       if ((dev->udev->speed != USB_SPEED_HIGH) &&
-           (cmd_len > PCAN_UFD_LOSPD_PKT_SIZE)) {
-               packet_len = PCAN_UFD_LOSPD_PKT_SIZE;
-               n += cmd_len / packet_len;
-       } else {
-               packet_len = cmd_len;
-       }
+       if (unlikely(dev->udev->speed != USB_SPEED_HIGH))
+               packet_len = min(packet_len, PCAN_UFD_LOSPD_PKT_SIZE);
 
-       for (i = 0; i < n; i++) {
+       do {
                err = usb_bulk_msg(dev->udev,
                                   usb_sndbulkpipe(dev->udev,
                                                   PCAN_USBPRO_EP_CMDOUT),
@@ -224,7 +220,12 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
                }
 
                packet_ptr += packet_len;
-       }
+               cmd_len -= packet_len;
+
+               if (cmd_len < PCAN_UFD_LOSPD_PKT_SIZE)
+                       packet_len = cmd_len;
+
+       } while (packet_len > 0);
 
        return err;
 }
index 410a0a95130b4ed1b292dcc628ae820c164146da..b3e7fafee3dfb97375b9dc460a57fa10ed789280 100644 (file)
@@ -1913,3 +1913,7 @@ static struct platform_driver cs89x0_driver = {
 module_platform_driver_probe(cs89x0_driver, cs89x0_platform_probe);
 
 #endif /* CONFIG_CS89x0_PLATFORM */
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Crystal Semiconductor (Now Cirrus Logic) CS89[02]0 network driver");
+MODULE_AUTHOR("Russell Nelson <nelson@crynwr.com>");
index 7892f2f0c6b56473ed86b39d6525535f61f7b741..2c2976a2dda6b9f1055af98c19cbc9d17bf8279b 100644 (file)
@@ -613,9 +613,11 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static void fs_timeout(struct net_device *dev)
+static void fs_timeout_work(struct work_struct *work)
 {
-       struct fs_enet_private *fep = netdev_priv(dev);
+       struct fs_enet_private *fep = container_of(work, struct fs_enet_private,
+                                                  timeout_work);
+       struct net_device *dev = fep->ndev;
        unsigned long flags;
        int wake = 0;
 
@@ -627,7 +629,6 @@ static void fs_timeout(struct net_device *dev)
                phy_stop(dev->phydev);
                (*fep->ops->stop)(dev);
                (*fep->ops->restart)(dev);
-               phy_start(dev->phydev);
        }
 
        phy_start(dev->phydev);
@@ -639,6 +640,13 @@ static void fs_timeout(struct net_device *dev)
                netif_wake_queue(dev);
 }
 
+static void fs_timeout(struct net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+
+       schedule_work(&fep->timeout_work);
+}
+
 /*-----------------------------------------------------------------------------
  *  generic link-change handler - should be sufficient for most cases
  *-----------------------------------------------------------------------------*/
@@ -759,6 +767,7 @@ static int fs_enet_close(struct net_device *dev)
        netif_stop_queue(dev);
        netif_carrier_off(dev);
        napi_disable(&fep->napi);
+       cancel_work_sync(&fep->timeout_work);
        phy_stop(dev->phydev);
 
        spin_lock_irqsave(&fep->lock, flags);
@@ -1019,6 +1028,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 
        ndev->netdev_ops = &fs_enet_netdev_ops;
        ndev->watchdog_timeo = 2 * HZ;
+       INIT_WORK(&fep->timeout_work, fs_timeout_work);
        netif_napi_add(ndev, &fep->napi, fs_enet_napi, fpi->napi_weight);
 
        ndev->ethtool_ops = &fs_ethtool_ops;
index 92e06b37a199bb9aa7bdb8a23c298296aa5bd217..195fae6aec4ae71bbdcd77114c1e86148c43c061 100644 (file)
@@ -125,6 +125,7 @@ struct fs_enet_private {
        spinlock_t lock;        /* during all ops except TX pckt processing */
        spinlock_t tx_lock;     /* during fs_start_xmit and fs_tx         */
        struct fs_platform_info *fpi;
+       struct work_struct timeout_work;
        const struct fs_ops *ops;
        int rx_ring, tx_ring;
        dma_addr_t ring_mem_addr;
index 1dc4aef37d3a4faf3592ab0dede92b802a831824..ab2e1917cd04290eef52bf188f2f2def6ae389cc 100644 (file)
@@ -756,6 +756,12 @@ static int ibmvnic_login(struct net_device *netdev)
                }
        } while (adapter->renegotiate);
 
+       /* handle pending MAC address changes after successful login */
+       if (adapter->mac_change_pending) {
+               __ibmvnic_set_mac(netdev, &adapter->desired.mac);
+               adapter->mac_change_pending = false;
+       }
+
        return 0;
 }
 
@@ -993,11 +999,6 @@ static int ibmvnic_open(struct net_device *netdev)
 
        mutex_lock(&adapter->reset_lock);
 
-       if (adapter->mac_change_pending) {
-               __ibmvnic_set_mac(netdev, &adapter->desired.mac);
-               adapter->mac_change_pending = false;
-       }
-
        if (adapter->state != VNIC_CLOSED) {
                rc = ibmvnic_login(netdev);
                if (rc) {
@@ -1275,6 +1276,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        unsigned char *dst;
        u64 *handle_array;
        int index = 0;
+       u8 proto = 0;
        int ret = 0;
 
        if (adapter->resetting) {
@@ -1363,17 +1365,18 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        }
 
        if (skb->protocol == htons(ETH_P_IP)) {
-               if (ip_hdr(skb)->version == 4)
-                       tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_IPV4;
-               else if (ip_hdr(skb)->version == 6)
-                       tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_IPV6;
-
-               if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-                       tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_TCP;
-               else if (ip_hdr(skb)->protocol != IPPROTO_TCP)
-                       tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_UDP;
+               tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_IPV4;
+               proto = ip_hdr(skb)->protocol;
+       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_IPV6;
+               proto = ipv6_hdr(skb)->nexthdr;
        }
 
+       if (proto == IPPROTO_TCP)
+               tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_TCP;
+       else if (proto == IPPROTO_UDP)
+               tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_UDP;
+
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD;
                hdrs += 2;
@@ -1527,7 +1530,7 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
        struct sockaddr *addr = p;
 
-       if (adapter->state != VNIC_OPEN) {
+       if (adapter->state == VNIC_PROBED) {
                memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr));
                adapter->mac_change_pending = true;
                return 0;
@@ -3345,7 +3348,11 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
                return;
        }
 
+       adapter->ip_offload_ctrl.len =
+           cpu_to_be32(sizeof(adapter->ip_offload_ctrl));
        adapter->ip_offload_ctrl.version = cpu_to_be32(INITIAL_VERSION_IOB);
+       adapter->ip_offload_ctrl.ipv4_chksum = buf->ipv4_chksum;
+       adapter->ip_offload_ctrl.ipv6_chksum = buf->ipv6_chksum;
        adapter->ip_offload_ctrl.tcp_ipv4_chksum = buf->tcp_ipv4_chksum;
        adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum;
        adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum;
index 7f605221a6867ed8e4c53de10048040f06e509d6..a434fecfdfeb6aaf74719d0182d89c5008efcd02 100644 (file)
@@ -2463,7 +2463,6 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface)
        return err;
 }
 
-#ifdef CONFIG_PM
 /**
  * fm10k_resume - Generic PM resume hook
  * @dev: generic device structure
@@ -2472,7 +2471,7 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface)
  * suspend or hibernation. This function does not need to handle lower PCIe
  * device state as the stack takes care of that for us.
  **/
-static int fm10k_resume(struct device *dev)
+static int __maybe_unused fm10k_resume(struct device *dev)
 {
        struct fm10k_intfc *interface = pci_get_drvdata(to_pci_dev(dev));
        struct net_device *netdev = interface->netdev;
@@ -2499,7 +2498,7 @@ static int fm10k_resume(struct device *dev)
  * system suspend or hibernation. This function does not need to handle lower
  * PCIe device state as the stack takes care of that for us.
  **/
-static int fm10k_suspend(struct device *dev)
+static int __maybe_unused fm10k_suspend(struct device *dev)
 {
        struct fm10k_intfc *interface = pci_get_drvdata(to_pci_dev(dev));
        struct net_device *netdev = interface->netdev;
@@ -2511,8 +2510,6 @@ static int fm10k_suspend(struct device *dev)
        return 0;
 }
 
-#endif /* CONFIG_PM */
-
 /**
  * fm10k_io_error_detected - called when PCI error is detected
  * @pdev: Pointer to PCI device
@@ -2643,11 +2640,9 @@ static struct pci_driver fm10k_driver = {
        .id_table               = fm10k_pci_tbl,
        .probe                  = fm10k_probe,
        .remove                 = fm10k_remove,
-#ifdef CONFIG_PM
        .driver = {
                .pm             = &fm10k_pm_ops,
        },
-#endif /* CONFIG_PM */
        .sriov_configure        = fm10k_iov_configure,
        .err_handler            = &fm10k_err_handler
 };
index 543060c305a073c0457cc31ae7318f425a0e7c49..c2d89bfa1a70ce597af7f663e57e65f519f2733c 100644 (file)
@@ -895,7 +895,7 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
                           u16 vid);
 void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv);
 void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
-void mlx5e_timestamp_set(struct mlx5e_priv *priv);
+void mlx5e_timestamp_init(struct mlx5e_priv *priv);
 
 struct mlx5e_redirect_rqt_param {
        bool is_rss;
index 9bcf38f4123b504637c080413078c23304d9e49e..3d46ef48d5b82ef0d1f85e93a0ac0694080173b4 100644 (file)
@@ -922,8 +922,9 @@ static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
 
 static void mlx5e_ets_init(struct mlx5e_priv *priv)
 {
-       int i;
        struct ieee_ets ets;
+       int err;
+       int i;
 
        if (!MLX5_CAP_GEN(priv->mdev, ets))
                return;
@@ -936,11 +937,16 @@ static void mlx5e_ets_init(struct mlx5e_priv *priv)
                ets.prio_tc[i] = i;
        }
 
-       /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
-       ets.prio_tc[0] = 1;
-       ets.prio_tc[1] = 0;
+       if (ets.ets_cap > 1) {
+               /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
+               ets.prio_tc[0] = 1;
+               ets.prio_tc[1] = 0;
+       }
 
-       mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+       err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+       if (err)
+               netdev_err(priv->netdev,
+                          "%s, Failed to init ETS: %d\n", __func__, err);
 }
 
 enum {
index 8f05efa5c829bccb67ddd8b24dc2997adfe4a6c8..ea5fff2c31436f18e2f4e8a800f69613bf320733 100644 (file)
@@ -207,8 +207,7 @@ void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv,
                return;
 
        mutex_lock(&priv->state_lock);
-       if (test_bit(MLX5E_STATE_OPENED, &priv->state))
-               mlx5e_update_stats(priv, true);
+       mlx5e_update_stats(priv, true);
        mutex_unlock(&priv->state_lock);
 
        for (i = 0; i < mlx5e_num_stats_grps; i++)
index d9d8227f195f0e151ba948e0622ea90a411817c4..d8aefeed124d56631c89413876370e77d8775c13 100644 (file)
@@ -2669,7 +2669,7 @@ void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
                netif_carrier_on(netdev);
 }
 
-void mlx5e_timestamp_set(struct mlx5e_priv *priv)
+void mlx5e_timestamp_init(struct mlx5e_priv *priv)
 {
        priv->tstamp.tx_type   = HWTSTAMP_TX_OFF;
        priv->tstamp.rx_filter = HWTSTAMP_FILTER_NONE;
@@ -2690,7 +2690,6 @@ int mlx5e_open_locked(struct net_device *netdev)
        mlx5e_activate_priv_channels(priv);
        if (priv->profile->update_carrier)
                priv->profile->update_carrier(priv);
-       mlx5e_timestamp_set(priv);
 
        if (priv->profile->update_stats)
                queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
@@ -3219,12 +3218,12 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
        return 0;
 }
 
-#define MLX5E_SET_FEATURE(netdev, feature, enable)     \
+#define MLX5E_SET_FEATURE(features, feature, enable)   \
        do {                                            \
                if (enable)                             \
-                       netdev->features |= feature;    \
+                       *features |= feature;           \
                else                                    \
-                       netdev->features &= ~feature;   \
+                       *features &= ~feature;          \
        } while (0)
 
 typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);
@@ -3347,6 +3346,7 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
 #endif
 
 static int mlx5e_handle_feature(struct net_device *netdev,
+                               netdev_features_t *features,
                                netdev_features_t wanted_features,
                                netdev_features_t feature,
                                mlx5e_feature_handler feature_handler)
@@ -3365,34 +3365,40 @@ static int mlx5e_handle_feature(struct net_device *netdev,
                return err;
        }
 
-       MLX5E_SET_FEATURE(netdev, feature, enable);
+       MLX5E_SET_FEATURE(features, feature, enable);
        return 0;
 }
 
 static int mlx5e_set_features(struct net_device *netdev,
                              netdev_features_t features)
 {
+       netdev_features_t oper_features = netdev->features;
        int err;
 
-       err  = mlx5e_handle_feature(netdev, features, NETIF_F_LRO,
-                                   set_feature_lro);
-       err |= mlx5e_handle_feature(netdev, features,
+       err  = mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_LRO, set_feature_lro);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
                                    NETIF_F_HW_VLAN_CTAG_FILTER,
                                    set_feature_cvlan_filter);
-       err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC,
-                                   set_feature_tc_num_filters);
-       err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL,
-                                   set_feature_rx_all);
-       err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXFCS,
-                                   set_feature_rx_fcs);
-       err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX,
-                                   set_feature_rx_vlan);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_HW_TC, set_feature_tc_num_filters);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_RXALL, set_feature_rx_all);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_RXFCS, set_feature_rx_fcs);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
 #ifdef CONFIG_RFS_ACCEL
-       err |= mlx5e_handle_feature(netdev, features, NETIF_F_NTUPLE,
-                                   set_feature_arfs);
+       err |= mlx5e_handle_feature(netdev, &oper_features, features,
+                                   NETIF_F_NTUPLE, set_feature_arfs);
 #endif
 
-       return err ? -EINVAL : 0;
+       if (err) {
+               netdev->features = oper_features;
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
@@ -4139,6 +4145,8 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
        INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work);
        INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);
        INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
+
+       mlx5e_timestamp_init(priv);
 }
 
 static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
index 2c43606c26b59871d2232ab14c816b10cb8bdc83..3409d86eb06bb9497a095aa07cd86ded8cc15205 100644 (file)
@@ -877,6 +877,8 @@ static void mlx5e_init_rep(struct mlx5_core_dev *mdev,
 
        mlx5e_build_rep_params(mdev, &priv->channels.params);
        mlx5e_build_rep_netdev(netdev);
+
+       mlx5e_timestamp_init(priv);
 }
 
 static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
index 1f1f8af87d4df8d10f90eacda6d0d6f2c69b22b1..5a4608281f38d236d77d8f86f81f52d683f3eadc 100644 (file)
@@ -238,15 +238,19 @@ static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
        int err = 0;
 
        /* Temporarily enable local_lb */
-       if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
-               mlx5_nic_vport_query_local_lb(priv->mdev, &lbtp->local_lb);
-               if (!lbtp->local_lb)
-                       mlx5_nic_vport_update_local_lb(priv->mdev, true);
+       err = mlx5_nic_vport_query_local_lb(priv->mdev, &lbtp->local_lb);
+       if (err)
+               return err;
+
+       if (!lbtp->local_lb) {
+               err = mlx5_nic_vport_update_local_lb(priv->mdev, true);
+               if (err)
+                       return err;
        }
 
        err = mlx5e_refresh_tirs(priv, true);
        if (err)
-               return err;
+               goto out;
 
        lbtp->loopback_ok = false;
        init_completion(&lbtp->comp);
@@ -256,16 +260,21 @@ static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
        lbtp->pt.dev = priv->netdev;
        lbtp->pt.af_packet_priv = lbtp;
        dev_add_pack(&lbtp->pt);
+
+       return 0;
+
+out:
+       if (!lbtp->local_lb)
+               mlx5_nic_vport_update_local_lb(priv->mdev, false);
+
        return err;
 }
 
 static void mlx5e_test_loopback_cleanup(struct mlx5e_priv *priv,
                                        struct mlx5e_lbt_priv *lbtp)
 {
-       if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
-               if (!lbtp->local_lb)
-                       mlx5_nic_vport_update_local_lb(priv->mdev, false);
-       }
+       if (!lbtp->local_lb)
+               mlx5_nic_vport_update_local_lb(priv->mdev, false);
 
        dev_remove_pack(&lbtp->pt);
        mlx5e_refresh_tirs(priv, false);
index 8812d7208e8f3522500b3f3e971b4a7341b22c8f..ee2f378c503084eb9d1842b77444f80b63379b5c 100644 (file)
@@ -86,6 +86,8 @@ void mlx5i_init(struct mlx5_core_dev *mdev,
        mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev));
        mlx5i_build_nic_params(mdev, &priv->channels.params);
 
+       mlx5e_timestamp_init(priv);
+
        /* netdev init */
        netdev->hw_features    |= NETIF_F_SG;
        netdev->hw_features    |= NETIF_F_IP_CSUM;
@@ -450,7 +452,6 @@ static int mlx5i_open(struct net_device *netdev)
 
        mlx5e_refresh_tirs(epriv, false);
        mlx5e_activate_priv_channels(epriv);
-       mlx5e_timestamp_set(epriv);
 
        mutex_unlock(&epriv->state_lock);
        return 0;
index fa8aed62b2314a1be9c0ece89ac9b8b29572a7d4..5701f125e99c10afc45fc431bb53a6855cd216cc 100644 (file)
@@ -423,9 +423,13 @@ void mlx5_pps_event(struct mlx5_core_dev *mdev,
 
        switch (clock->ptp_info.pin_config[pin].func) {
        case PTP_PF_EXTTS:
+               ptp_event.index = pin;
+               ptp_event.timestamp = timecounter_cyc2time(&clock->tc,
+                                       be64_to_cpu(eqe->data.pps.time_stamp));
                if (clock->pps_info.enabled) {
                        ptp_event.type = PTP_CLOCK_PPSUSR;
-                       ptp_event.pps_times.ts_real = ns_to_timespec64(eqe->data.pps.time_stamp);
+                       ptp_event.pps_times.ts_real =
+                                       ns_to_timespec64(ptp_event.timestamp);
                } else {
                        ptp_event.type = PTP_CLOCK_EXTTS;
                }
index 8a89c7e8cd631f2e14cb7cbac99a8983964b7eda..0f88fd30a09a0c52a889f68b1cbcade3c37ff56f 100644 (file)
@@ -319,6 +319,7 @@ static int mlx5_alloc_irq_vectors(struct mlx5_core_dev *dev)
        struct mlx5_eq_table *table = &priv->eq_table;
        int num_eqs = 1 << MLX5_CAP_GEN(dev, log_max_eq);
        int nvec;
+       int err;
 
        nvec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() +
               MLX5_EQ_VEC_COMP_BASE;
@@ -328,21 +329,23 @@ static int mlx5_alloc_irq_vectors(struct mlx5_core_dev *dev)
 
        priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
        if (!priv->irq_info)
-               goto err_free_msix;
+               return -ENOMEM;
 
        nvec = pci_alloc_irq_vectors(dev->pdev,
                        MLX5_EQ_VEC_COMP_BASE + 1, nvec,
                        PCI_IRQ_MSIX);
-       if (nvec < 0)
-               return nvec;
+       if (nvec < 0) {
+               err = nvec;
+               goto err_free_irq_info;
+       }
 
        table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
 
        return 0;
 
-err_free_msix:
+err_free_irq_info:
        kfree(priv->irq_info);
-       return -ENOMEM;
+       return err;
 }
 
 static void mlx5_free_irq_vectors(struct mlx5_core_dev *dev)
@@ -578,8 +581,7 @@ static int mlx5_core_set_hca_defaults(struct mlx5_core_dev *dev)
        int ret = 0;
 
        /* Disable local_lb by default */
-       if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
-           MLX5_CAP_GEN(dev, disable_local_lb))
+       if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH)
                ret = mlx5_nic_vport_update_local_lb(dev, false);
 
        return ret;
@@ -1121,9 +1123,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
                goto err_stop_poll;
        }
 
-       if (boot && mlx5_init_once(dev, priv)) {
-               dev_err(&pdev->dev, "sw objs init failed\n");
-               goto err_stop_poll;
+       if (boot) {
+               err = mlx5_init_once(dev, priv);
+               if (err) {
+                       dev_err(&pdev->dev, "sw objs init failed\n");
+                       goto err_stop_poll;
+               }
        }
 
        err = mlx5_alloc_irq_vectors(dev);
@@ -1133,8 +1138,9 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
        }
 
        dev->priv.uar = mlx5_get_uars_page(dev);
-       if (!dev->priv.uar) {
+       if (IS_ERR(dev->priv.uar)) {
                dev_err(&pdev->dev, "Failed allocating uar, aborting\n");
+               err = PTR_ERR(dev->priv.uar);
                goto err_disable_msix;
        }
 
index 222b25908d012614639b4e9ef2a8a7727a82cd18..8b97066dd1f19e1b5a3151a7e6228a86b65dcd68 100644 (file)
@@ -168,18 +168,16 @@ struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev)
        struct mlx5_uars_page *ret;
 
        mutex_lock(&mdev->priv.bfregs.reg_head.lock);
-       if (list_empty(&mdev->priv.bfregs.reg_head.list)) {
-               ret = alloc_uars_page(mdev, false);
-               if (IS_ERR(ret)) {
-                       ret = NULL;
-                       goto out;
-               }
-               list_add(&ret->list, &mdev->priv.bfregs.reg_head.list);
-       } else {
+       if (!list_empty(&mdev->priv.bfregs.reg_head.list)) {
                ret = list_first_entry(&mdev->priv.bfregs.reg_head.list,
                                       struct mlx5_uars_page, list);
                kref_get(&ret->ref_count);
+               goto out;
        }
+       ret = alloc_uars_page(mdev, false);
+       if (IS_ERR(ret))
+               goto out;
+       list_add(&ret->list, &mdev->priv.bfregs.reg_head.list);
 out:
        mutex_unlock(&mdev->priv.bfregs.reg_head.lock);
 
index d653b0025b13eae0dbbe3f278fc894be1d0164f2..a1296a62497dab01e43d6293d902548af8b6195e 100644 (file)
@@ -908,23 +908,33 @@ int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable)
        void *in;
        int err;
 
-       mlx5_core_dbg(mdev, "%s local_lb\n", enable ? "enable" : "disable");
+       if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) &&
+           !MLX5_CAP_GEN(mdev, disable_local_lb_uc))
+               return 0;
+
        in = kvzalloc(inlen, GFP_KERNEL);
        if (!in)
                return -ENOMEM;
 
-       MLX5_SET(modify_nic_vport_context_in, in,
-                field_select.disable_mc_local_lb, 1);
        MLX5_SET(modify_nic_vport_context_in, in,
                 nic_vport_context.disable_mc_local_lb, !enable);
-
-       MLX5_SET(modify_nic_vport_context_in, in,
-                field_select.disable_uc_local_lb, 1);
        MLX5_SET(modify_nic_vport_context_in, in,
                 nic_vport_context.disable_uc_local_lb, !enable);
 
+       if (MLX5_CAP_GEN(mdev, disable_local_lb_mc))
+               MLX5_SET(modify_nic_vport_context_in, in,
+                        field_select.disable_mc_local_lb, 1);
+
+       if (MLX5_CAP_GEN(mdev, disable_local_lb_uc))
+               MLX5_SET(modify_nic_vport_context_in, in,
+                        field_select.disable_uc_local_lb, 1);
+
        err = mlx5_modify_nic_vport_context(mdev, in, inlen);
 
+       if (!err)
+               mlx5_core_dbg(mdev, "%s local_lb\n",
+                             enable ? "enable" : "disable");
+
        kvfree(in);
        return err;
 }
index 434b3922b34f06689e3e85c0dc70810902c51275..6c0391c13fe002f5372381c42a41b6c2f8087924 100644 (file)
@@ -821,13 +821,18 @@ static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
        int err;
 
-       err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
-       if (err)
-               return err;
        fib->lpm_tree = new_tree;
        mlxsw_sp_lpm_tree_hold(new_tree);
+       err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
+       if (err)
+               goto err_tree_bind;
        mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
        return 0;
+
+err_tree_bind:
+       mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
+       fib->lpm_tree = old_tree;
+       return err;
 }
 
 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
@@ -868,11 +873,14 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
        return err;
 
 no_replace:
-       err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
-       if (err)
-               return err;
        fib->lpm_tree = new_tree;
        mlxsw_sp_lpm_tree_hold(new_tree);
+       err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
+       if (err) {
+               mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
+               fib->lpm_tree = NULL;
+               return err;
+       }
        return 0;
 }
 
index 2801ecd09eab098e66ef28aa89fcd5c5f7e7430d..6c02b2d6ba06625e8f11833c1f3a23f07895766a 100644 (file)
@@ -333,7 +333,7 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
            ls >= ARRAY_SIZE(ls_to_ethtool))
                return 0;
 
-       cmd->base.speed = ls_to_ethtool[sts];
+       cmd->base.speed = ls_to_ethtool[ls];
        cmd->base.duplex = DUPLEX_FULL;
 
        return 0;
index be48d9abd0010ed88cb6c6161cbf4e7b81429710..3588081b2e274f2308eb795ca06632b9a5a442e8 100644 (file)
@@ -776,6 +776,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
        int rc = 0;
        struct qed_spq *p_spq = p_hwfn ? p_hwfn->p_spq : NULL;
        bool b_ret_ent = true;
+       bool eblock;
 
        if (!p_hwfn)
                return -EINVAL;
@@ -794,6 +795,11 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
        if (rc)
                goto spq_post_fail;
 
+       /* Check if entry is in block mode before qed_spq_add_entry,
+        * which might kfree p_ent.
+        */
+       eblock = (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK);
+
        /* Add the request to the pending queue */
        rc = qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
        if (rc)
@@ -811,7 +817,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
 
        spin_unlock_bh(&p_spq->lock);
 
-       if (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK) {
+       if (eblock) {
                /* For entries in QED BLOCK mode, the completion code cannot
                 * perform the necessary cleanup - if it did, we couldn't
                 * access p_ent here to see whether it's successful or not.
index b9e2846589f8678e72683c230d601d7f517de5da..53924a4fc31c75382e0a2d910b09d389a066ec2a 100644 (file)
@@ -2089,8 +2089,8 @@ static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf)
                add_reg(CSMR);
        if (cd->select_mii)
                add_reg(RMII_MII);
-       add_reg(ARSTR);
        if (cd->tsu) {
+               add_tsu_reg(ARSTR);
                add_tsu_reg(TSU_CTRST);
                add_tsu_reg(TSU_FWEN0);
                add_tsu_reg(TSU_FWEN1);
index ed58c746e4af194a9edc8edb3d5c15bd3e2e0acd..f5a7eb22d0f50e38a39c94f1dbb01cd17dff73c7 100644 (file)
@@ -715,7 +715,7 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
                /* warning!!!! We are retrieving the virtual ptr in the sw_data
                 * field as a 32bit value. Will not work on 64bit machines
                 */
-               page = (struct page *)GET_SW_DATA0(desc);
+               page = (struct page *)GET_SW_DATA0(ndesc);
 
                if (likely(dma_buff && buf_len && page)) {
                        dma_unmap_page(netcp->dev, dma_buff, PAGE_SIZE,
index d8e5747ff4e32e9bf0c221e88345fd27c60b0e5f..264d4af0bf69278f5ee50e804c9ccf7225fb5782 100644 (file)
@@ -1006,17 +1006,18 @@ static int ppp_unit_register(struct ppp *ppp, int unit, bool ifname_is_set)
        if (!ifname_is_set)
                snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ppp->file.index);
 
+       mutex_unlock(&pn->all_ppp_mutex);
+
        ret = register_netdevice(ppp->dev);
        if (ret < 0)
                goto err_unit;
 
        atomic_inc(&ppp_unit_count);
 
-       mutex_unlock(&pn->all_ppp_mutex);
-
        return 0;
 
 err_unit:
+       mutex_lock(&pn->all_ppp_mutex);
        unit_put(&pn->units_idr, ppp->file.index);
 err:
        mutex_unlock(&pn->all_ppp_mutex);
index 4f4a842a1c9cb8ac3397b329854a0fc7bd2f6aa3..a8ec589d1359a86614e9ed829b91fd145494cd00 100644 (file)
@@ -611,6 +611,14 @@ static void tun_queue_purge(struct tun_file *tfile)
        skb_queue_purge(&tfile->sk.sk_error_queue);
 }
 
+static void tun_cleanup_tx_array(struct tun_file *tfile)
+{
+       if (tfile->tx_array.ring.queue) {
+               skb_array_cleanup(&tfile->tx_array);
+               memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));
+       }
+}
+
 static void __tun_detach(struct tun_file *tfile, bool clean)
 {
        struct tun_file *ntfile;
@@ -657,8 +665,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                            tun->dev->reg_state == NETREG_REGISTERED)
                                unregister_netdevice(tun->dev);
                }
-               if (tun)
-                       skb_array_cleanup(&tfile->tx_array);
+               tun_cleanup_tx_array(tfile);
                sock_put(&tfile->sk);
        }
 }
@@ -700,11 +707,13 @@ static void tun_detach_all(struct net_device *dev)
                /* Drop read queue */
                tun_queue_purge(tfile);
                sock_put(&tfile->sk);
+               tun_cleanup_tx_array(tfile);
        }
        list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
                tun_enable_queue(tfile);
                tun_queue_purge(tfile);
                sock_put(&tfile->sk);
+               tun_cleanup_tx_array(tfile);
        }
        BUG_ON(tun->numdisabled != 0);
 
@@ -2851,6 +2860,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 
        sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);
 
+       memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));
+
        return 0;
 }
 
index 94c7804903c48eba2ed0496d7d4461e9c38b8c3c..ec56ff29aac4ed9f28e3f984093968da53147ac5 100644 (file)
@@ -2396,6 +2396,7 @@ static int lan78xx_reset(struct lan78xx_net *dev)
                buf = DEFAULT_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
                dev->rx_urb_size = DEFAULT_BURST_CAP_SIZE;
                dev->rx_qlen = 4;
+               dev->tx_qlen = 4;
        }
 
        ret = lan78xx_write_reg(dev, BURST_CAP, buf);
index d51d9abf7986b203350167d6a2fcdcfcddf8b972..0657203ffb9174bac37085613100726f30928a1a 100644 (file)
@@ -606,6 +606,7 @@ enum rtl8152_flags {
        PHY_RESET,
        SCHEDULE_NAPI,
        GREEN_ETHERNET,
+       DELL_TB_RX_AGG_BUG,
 };
 
 /* Define these values to match your device */
@@ -1798,6 +1799,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
                dev_kfree_skb_any(skb);
 
                remain = agg_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
+
+               if (test_bit(DELL_TB_RX_AGG_BUG, &tp->flags))
+                       break;
        }
 
        if (!skb_queue_empty(&skb_head)) {
@@ -4133,6 +4137,9 @@ static void r8153_init(struct r8152 *tp)
        /* rx aggregation */
        ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
        ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
+       if (test_bit(DELL_TB_RX_AGG_BUG, &tp->flags))
+               ocp_data |= RX_AGG_DISABLE;
+
        ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
 
        rtl_tally_reset(tp);
@@ -5207,6 +5214,12 @@ static int rtl8152_probe(struct usb_interface *intf,
                netdev->hw_features &= ~NETIF_F_RXCSUM;
        }
 
+       if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 &&
+           udev->serial && !strcmp(udev->serial, "000001000000")) {
+               dev_info(&udev->dev, "Dell TB16 Dock, disable RX aggregation");
+               set_bit(DELL_TB_RX_AGG_BUG, &tp->flags);
+       }
+
        netdev->ethtool_ops = &ops;
        netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
 
index 6a59d0609d300361a2db89ebc01d658810bb17a3..9be0b051066a23214a2b29a0cac18ef64548427e 100644 (file)
@@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
 
        err = request_firmware(&clm, clm_name, dev);
        if (err) {
-               if (err == -ENOENT) {
-                       brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
-                       return 0;
-               }
-               brcmf_err("request CLM blob file failed (%d)\n", err);
-               return err;
+               brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n",
+                          err);
+               return 0;
        }
 
        chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
index e8189c07b41f6b450f135ef703ec4e01568e311d..f6d4a50f1bdb8a441a6d20a2d1fe7d4f25ce6636 100644 (file)
@@ -489,6 +489,7 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
 
 static spinlock_t hwsim_radio_lock;
 static LIST_HEAD(hwsim_radios);
+static struct workqueue_struct *hwsim_wq;
 static int hwsim_radio_idx;
 
 static struct platform_driver mac80211_hwsim_driver = {
@@ -3120,6 +3121,11 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
        if (info->attrs[HWSIM_ATTR_CHANNELS])
                param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
 
+       if (param.channels > CFG80211_MAX_NUM_DIFFERENT_CHANNELS) {
+               GENL_SET_ERR_MSG(info, "too many channels specified");
+               return -EINVAL;
+       }
+
        if (info->attrs[HWSIM_ATTR_NO_VIF])
                param.no_vif = true;
 
@@ -3342,7 +3348,7 @@ static void remove_user_radios(u32 portid)
                if (entry->destroy_on_close && entry->portid == portid) {
                        list_del(&entry->list);
                        INIT_WORK(&entry->destroy_work, destroy_radio);
-                       schedule_work(&entry->destroy_work);
+                       queue_work(hwsim_wq, &entry->destroy_work);
                }
        }
        spin_unlock_bh(&hwsim_radio_lock);
@@ -3417,7 +3423,7 @@ static void __net_exit hwsim_exit_net(struct net *net)
 
                list_del(&data->list);
                INIT_WORK(&data->destroy_work, destroy_radio);
-               schedule_work(&data->destroy_work);
+               queue_work(hwsim_wq, &data->destroy_work);
        }
        spin_unlock_bh(&hwsim_radio_lock);
 }
@@ -3449,6 +3455,10 @@ static int __init init_mac80211_hwsim(void)
 
        spin_lock_init(&hwsim_radio_lock);
 
+       hwsim_wq = alloc_workqueue("hwsim_wq",WQ_MEM_RECLAIM,0);
+       if (!hwsim_wq)
+               return -ENOMEM;
+
        err = register_pernet_device(&hwsim_net_ops);
        if (err)
                return err;
@@ -3587,8 +3597,11 @@ static void __exit exit_mac80211_hwsim(void)
        hwsim_exit_netlink();
 
        mac80211_hwsim_free();
+       flush_workqueue(hwsim_wq);
+
        unregister_netdev(hwsim_mon);
        platform_driver_unregister(&mac80211_hwsim_driver);
        unregister_pernet_device(&hwsim_net_ops);
+       destroy_workqueue(hwsim_wq);
 }
 module_exit(exit_mac80211_hwsim);
index d53550e612bc1350febf84c891e2a28c24a6ae34..4276ebfff22ba00fd90e8c241cc7edd56deca353 100644 (file)
@@ -451,10 +451,13 @@ static void **nvme_pci_iod_list(struct request *req)
 static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+       int nseg = blk_rq_nr_phys_segments(req);
        unsigned int avg_seg_size;
 
-       avg_seg_size = DIV_ROUND_UP(blk_rq_payload_bytes(req),
-                       blk_rq_nr_phys_segments(req));
+       if (nseg == 0)
+               return false;
+
+       avg_seg_size = DIV_ROUND_UP(blk_rq_payload_bytes(req), nseg);
 
        if (!(dev->ctrl.sgls & ((1 << 0) | (1 << 1))))
                return false;
@@ -722,20 +725,19 @@ static void nvme_pci_sgl_set_seg(struct nvme_sgl_desc *sge,
 }
 
 static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev,
-               struct request *req, struct nvme_rw_command *cmd)
+               struct request *req, struct nvme_rw_command *cmd, int entries)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
-       int length = blk_rq_payload_bytes(req);
        struct dma_pool *pool;
        struct nvme_sgl_desc *sg_list;
        struct scatterlist *sg = iod->sg;
-       int entries = iod->nents, i = 0;
        dma_addr_t sgl_dma;
+       int i = 0;
 
        /* setting the transfer type as SGL */
        cmd->flags = NVME_CMD_SGL_METABUF;
 
-       if (length == sg_dma_len(sg)) {
+       if (entries == 1) {
                nvme_pci_sgl_set_data(&cmd->dptr.sgl, sg);
                return BLK_STS_OK;
        }
@@ -775,13 +777,9 @@ static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev,
                }
 
                nvme_pci_sgl_set_data(&sg_list[i++], sg);
-
-               length -= sg_dma_len(sg);
                sg = sg_next(sg);
-               entries--;
-       } while (length > 0);
+       } while (--entries > 0);
 
-       WARN_ON(entries > 0);
        return BLK_STS_OK;
 }
 
@@ -793,6 +791,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
        enum dma_data_direction dma_dir = rq_data_dir(req) ?
                        DMA_TO_DEVICE : DMA_FROM_DEVICE;
        blk_status_t ret = BLK_STS_IOERR;
+       int nr_mapped;
 
        sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
        iod->nents = blk_rq_map_sg(q, req, iod->sg);
@@ -800,12 +799,13 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
                goto out;
 
        ret = BLK_STS_RESOURCE;
-       if (!dma_map_sg_attrs(dev->dev, iod->sg, iod->nents, dma_dir,
-                               DMA_ATTR_NO_WARN))
+       nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents, dma_dir,
+                       DMA_ATTR_NO_WARN);
+       if (!nr_mapped)
                goto out;
 
        if (iod->use_sgl)
-               ret = nvme_pci_setup_sgls(dev, req, &cmnd->rw);
+               ret = nvme_pci_setup_sgls(dev, req, &cmnd->rw, nr_mapped);
        else
                ret = nvme_pci_setup_prps(dev, req, &cmnd->rw);
 
index b4964b067aecef71008adcedc4e3b20eabceacca..8f6e8e28996d6deb853f30c4fae15ebc334a1f59 100644 (file)
@@ -410,6 +410,10 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
        if (ret)
                return ERR_PTR(-ENODEV);
 
+       /* This phy type handled by the usb-phy subsystem for now */
+       if (of_device_is_compatible(args.np, "usb-nop-xceiv"))
+               return ERR_PTR(-ENODEV);
+
        mutex_lock(&phy_provider_mutex);
        phy_provider = of_phy_provider_lookup(args.np);
        if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
index 58476b728c57e11cd20232f1b43215eb3b2c1e5b..c9406852c3e92e45ad9ff973b8fdda0a6245b291 100644 (file)
@@ -486,15 +486,28 @@ static int sas_queue_reset(struct domain_device *dev, int reset_type,
 
 int sas_eh_abort_handler(struct scsi_cmnd *cmd)
 {
-       int res;
+       int res = TMF_RESP_FUNC_FAILED;
        struct sas_task *task = TO_SAS_TASK(cmd);
        struct Scsi_Host *host = cmd->device->host;
+       struct domain_device *dev = cmd_to_domain_dev(cmd);
        struct sas_internal *i = to_sas_internal(host->transportt);
+       unsigned long flags;
 
        if (!i->dft->lldd_abort_task)
                return FAILED;
 
-       res = i->dft->lldd_abort_task(task);
+       spin_lock_irqsave(host->host_lock, flags);
+       /* We cannot do async aborts for SATA devices */
+       if (dev_is_sata(dev) && !host->host_eh_scheduled) {
+               spin_unlock_irqrestore(host->host_lock, flags);
+               return FAILED;
+       }
+       spin_unlock_irqrestore(host->host_lock, flags);
+
+       if (task)
+               res = i->dft->lldd_abort_task(task);
+       else
+               SAS_DPRINTK("no task to abort\n");
        if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
                return SUCCESS;
 
index d8e4219c2324900c583245407a7c78f20e20325e..71c73766ee22e414f74cc77e8e18ebfadd5ca209 100644 (file)
@@ -32,7 +32,7 @@ config SSB_BLOCKIO
 
 config SSB_PCIHOST_POSSIBLE
        bool
-       depends on SSB && (PCI = y || PCI = SSB)
+       depends on SSB && (PCI = y || PCI = SSB) && PCI_DRIVERS_LEGACY
        default y
 
 config SSB_PCIHOST
index 79375fc115d277f9336e8aa75b0c1846dc093fc9..d67a72dcb92c47865177c2243231572f040c3cf6 100644 (file)
@@ -430,8 +430,11 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                 * safe because the task has stopped executing permanently.
                 */
                if (permitted && (task->flags & PF_DUMPCORE)) {
-                       eip = KSTK_EIP(task);
-                       esp = KSTK_ESP(task);
+                       if (try_get_task_stack(task)) {
+                               eip = KSTK_EIP(task);
+                               esp = KSTK_ESP(task);
+                               put_task_stack(task);
+                       }
                }
        }
 
index 2272ded07496d6044ebe43e930047237bb5f254e..631354acfa7204757a4ec29e74581dc2ee723a13 100644 (file)
 /* Mark a function definition as prohibited from being cloned. */
 #define __noclone      __attribute__((__noclone__, __optimize__("no-tracer")))
 
-#ifdef RANDSTRUCT_PLUGIN
+#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
 #define __randomize_layout __attribute__((randomize_layout))
 #define __no_randomize_layout __attribute__((no_randomize_layout))
 #endif
index 4178d24935477da5c02679ddba8dbadc22a48d2a..5e335b6203f49d429c3c81a158d1bed0830c66b7 100644 (file)
@@ -71,7 +71,7 @@ extern void delayacct_init(void);
 extern void __delayacct_tsk_init(struct task_struct *);
 extern void __delayacct_tsk_exit(struct task_struct *);
 extern void __delayacct_blkio_start(void);
-extern void __delayacct_blkio_end(void);
+extern void __delayacct_blkio_end(struct task_struct *);
 extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
 extern __u64 __delayacct_blkio_ticks(struct task_struct *);
 extern void __delayacct_freepages_start(void);
@@ -122,10 +122,10 @@ static inline void delayacct_blkio_start(void)
                __delayacct_blkio_start();
 }
 
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
 {
        if (current->delays)
-               __delayacct_blkio_end();
+               __delayacct_blkio_end(p);
        delayacct_clear_flag(DELAYACCT_PF_BLKIO);
 }
 
@@ -169,7 +169,7 @@ static inline void delayacct_tsk_free(struct task_struct *tsk)
 {}
 static inline void delayacct_blkio_start(void)
 {}
-static inline void delayacct_blkio_end(void)
+static inline void delayacct_blkio_end(struct task_struct *p)
 {}
 static inline int delayacct_add_tsk(struct taskstats *d,
                                        struct task_struct *tsk)
index 1f509d072026d3d62a9e3701ed72bd5ab2d5b5c4..a0610427e168d6fc924a9a5074e920d0939d47e3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/kernel.h>
 #include <linux/completion.h>
 #include <linux/pci.h>
+#include <linux/irq.h>
 #include <linux/spinlock_types.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
@@ -1231,7 +1232,23 @@ enum {
 static inline const struct cpumask *
 mlx5_get_vector_affinity(struct mlx5_core_dev *dev, int vector)
 {
-       return pci_irq_get_affinity(dev->pdev, MLX5_EQ_VEC_COMP_BASE + vector);
+       const struct cpumask *mask;
+       struct irq_desc *desc;
+       unsigned int irq;
+       int eqn;
+       int err;
+
+       err = mlx5_vector2eqn(dev, vector, &eqn, &irq);
+       if (err)
+               return NULL;
+
+       desc = irq_to_desc(irq);
+#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
+       mask = irq_data_get_effective_affinity_mask(&desc->irq_data);
+#else
+       mask = desc->irq_common_data.affinity;
+#endif
+       return mask;
 }
 
 #endif /* MLX5_DRIVER_H */
index d44ec5f41d4a04c72b25b4db1d6fb0217f8f1fa1..1391a82da98e21ab942a130a4b81e2f0504c5dc9 100644 (file)
@@ -1027,8 +1027,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         log_max_wq_sz[0x5];
 
        u8         nic_vport_change_event[0x1];
-       u8         disable_local_lb[0x1];
-       u8         reserved_at_3e2[0x9];
+       u8         disable_local_lb_uc[0x1];
+       u8         disable_local_lb_mc[0x1];
+       u8         reserved_at_3e3[0x8];
        u8         log_max_vlan_list[0x5];
        u8         reserved_at_3f0[0x3];
        u8         log_max_current_mc_list[0x5];
index 49b4257ce1ea6abc8b188d67e0c48e739859a259..f3075d6c7e8229c999ab650537f1e3b11e1f457b 100644 (file)
@@ -85,7 +85,7 @@ struct netlink_ext_ack {
  * to the lack of an output buffer.)
  */
 #define NL_SET_ERR_MSG(extack, msg) do {               \
-       static const char __msg[] = (msg);              \
+       static const char __msg[] = msg;                \
        struct netlink_ext_ack *__extack = (extack);    \
                                                        \
        if (__extack)                                   \
@@ -101,7 +101,7 @@ struct netlink_ext_ack {
 } while (0)
 
 #define NL_SET_ERR_MSG_ATTR(extack, attr, msg) do {    \
-       static const char __msg[] = (msg);              \
+       static const char __msg[] = msg;                \
        struct netlink_ext_ack *__extack = (extack);    \
                                                        \
        if (__extack) {                                 \
index 6866df4f31b59da506d56b3db29501a56d813635..d72b2e7dd500ea5224a3afa330f478b3475e0a4e 100644 (file)
@@ -174,6 +174,15 @@ static inline int ptr_ring_produce_bh(struct ptr_ring *r, void *ptr)
  * if they dereference the pointer - see e.g. PTR_RING_PEEK_CALL.
  * If ring is never resized, and if the pointer is merely
  * tested, there's no need to take the lock - see e.g.  __ptr_ring_empty.
+ * However, if called outside the lock, and if some other CPU
+ * consumes ring entries at the same time, the value returned
+ * is not guaranteed to be correct.
+ * In this case - to avoid incorrectly detecting the ring
+ * as empty - the CPU consuming the ring entries is responsible
+ * for either consuming all ring entries until the ring is empty,
+ * or synchronizing with some other CPU and causing it to
+ * execute __ptr_ring_peek and/or consume the ring enteries
+ * after the synchronization point.
  */
 static inline void *__ptr_ring_peek(struct ptr_ring *r)
 {
@@ -182,10 +191,7 @@ static inline void *__ptr_ring_peek(struct ptr_ring *r)
        return NULL;
 }
 
-/* Note: callers invoking this in a loop must use a compiler barrier,
- * for example cpu_relax(). Callers must take consumer_lock
- * if the ring is ever resized - see e.g. ptr_ring_empty.
- */
+/* See __ptr_ring_peek above for locking rules. */
 static inline bool __ptr_ring_empty(struct ptr_ring *r)
 {
        return !__ptr_ring_peek(r);
index bae807eb2933f9391d42c3d0dd73d98928b91a98..853291714ae0b9a11682c87815efe0abc2ce2377 100644 (file)
 #else
 #define MODULE_RANDSTRUCT_PLUGIN
 #endif
+#ifdef RETPOLINE
+#define MODULE_VERMAGIC_RETPOLINE "retpoline "
+#else
+#define MODULE_VERMAGIC_RETPOLINE ""
+#endif
 
 #define VERMAGIC_STRING                                                \
        UTS_RELEASE " "                                                 \
        MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT                     \
        MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS       \
        MODULE_ARCH_VERMAGIC                                            \
-       MODULE_RANDSTRUCT_PLUGIN
+       MODULE_RANDSTRUCT_PLUGIN                                        \
+       MODULE_VERMAGIC_RETPOLINE
 
index dc8cd47f883b8bbb5f1e6875c4d9471920729c36..977aabfcdc03bfe85602fce1becd15f579993f3d 100644 (file)
@@ -20,6 +20,9 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32
 
 static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
 {
+       if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+               key = INADDR_ANY;
+
        return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev);
 }
 
index cb4d92b79cd932eda4e178861d8345683b329bdb..fb94a8bd8ab54d6ffe722da48436030be637cf70 100644 (file)
@@ -815,6 +815,8 @@ struct cfg80211_csa_settings {
        u8 count;
 };
 
+#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
+
 /**
  * struct iface_combination_params - input parameters for interface combinations
  *
index 83a3e47d5845b99fa61799a15b29e7247d478c72..becf86aa4ac6bc92e8078247a1c912323b63b131 100644 (file)
@@ -179,6 +179,7 @@ struct Qdisc_ops {
        const struct Qdisc_class_ops    *cl_ops;
        char                    id[IFNAMSIZ];
        int                     priv_size;
+       unsigned int            static_flags;
 
        int                     (*enqueue)(struct sk_buff *skb,
                                           struct Qdisc *sch,
@@ -444,6 +445,7 @@ void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
                               unsigned int len);
 struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
                          const struct Qdisc_ops *ops);
+void qdisc_free(struct Qdisc *qdisc);
 struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
                                const struct Qdisc_ops *ops, u32 parentid);
 void __qdisc_calculate_pkt_len(struct sk_buff *skb,
index 936cfc5cab7df843439c493655460640c3d4f07b..9185e53a743cea0a19554c5e62cb1841e2d58e70 100644 (file)
@@ -170,7 +170,7 @@ static inline bool tls_is_pending_open_record(struct tls_context *tls_ctx)
 
 static inline void tls_err_abort(struct sock *sk)
 {
-       sk->sk_err = -EBADMSG;
+       sk->sk_err = EBADMSG;
        sk->sk_error_report(sk);
 }
 
index 4265d7f9e1f22da2a3b352cf13d2bf930f530c5d..dcfab5e3b55c1f909bbea35196f92a17665ce16d 100644 (file)
@@ -363,7 +363,6 @@ enum ovs_tunnel_key_attr {
        OVS_TUNNEL_KEY_ATTR_IPV6_SRC,           /* struct in6_addr src IPv6 address. */
        OVS_TUNNEL_KEY_ATTR_IPV6_DST,           /* struct in6_addr dst IPv6 address. */
        OVS_TUNNEL_KEY_ATTR_PAD,
-       OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,        /* be32 ERSPAN index. */
        __OVS_TUNNEL_KEY_ATTR_MAX
 };
 
index aaa319848e7d57422225aa99055b574dc904e36d..ab94d304a634a7ea96e2e9c5b806bfe8dfb6dd90 100644 (file)
@@ -56,7 +56,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
        u32 elem_size, index_mask, max_entries;
        bool unpriv = !capable(CAP_SYS_ADMIN);
        struct bpf_array *array;
-       u64 array_size;
+       u64 array_size, mask64;
 
        /* check sanity of attributes */
        if (attr->max_entries == 0 || attr->key_size != 4 ||
@@ -74,13 +74,25 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
        elem_size = round_up(attr->value_size, 8);
 
        max_entries = attr->max_entries;
-       index_mask = roundup_pow_of_two(max_entries) - 1;
 
-       if (unpriv)
+       /* On 32 bit archs roundup_pow_of_two() with max_entries that has
+        * upper most bit set in u32 space is undefined behavior due to
+        * resulting 1U << 32, so do it manually here in u64 space.
+        */
+       mask64 = fls_long(max_entries - 1);
+       mask64 = 1ULL << mask64;
+       mask64 -= 1;
+
+       index_mask = mask64;
+       if (unpriv) {
                /* round up array size to nearest power of 2,
                 * since cpu will speculate within index_mask limits
                 */
                max_entries = index_mask + 1;
+               /* Check for overflows. */
+               if (max_entries < attr->max_entries)
+                       return ERR_PTR(-E2BIG);
+       }
 
        array_size = sizeof(*array);
        if (percpu)
index 51ec2dda7f08c6c90af084589bb6d80662c77d12..7949e8b8f94e9cc196e0449214493ccce61b0903 100644 (file)
@@ -956,7 +956,7 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
                DST = tmp;
                CONT;
        ALU_MOD_X:
-               if (unlikely(SRC == 0))
+               if (unlikely((u32)SRC == 0))
                        return 0;
                tmp = (u32) DST;
                DST = do_div(tmp, (u32) SRC);
@@ -975,7 +975,7 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
                DST = div64_u64(DST, SRC);
                CONT;
        ALU_DIV_X:
-               if (unlikely(SRC == 0))
+               if (unlikely((u32)SRC == 0))
                        return 0;
                tmp = (u32) DST;
                do_div(tmp, (u32) SRC);
index b414d6b2d47070505f3a60fcd8b58478b293d2ad..13551e62350148942949006100a1b66b71b7b8e8 100644 (file)
@@ -978,6 +978,13 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
        return __is_pointer_value(env->allow_ptr_leaks, cur_regs(env) + regno);
 }
 
+static bool is_ctx_reg(struct bpf_verifier_env *env, int regno)
+{
+       const struct bpf_reg_state *reg = cur_regs(env) + regno;
+
+       return reg->type == PTR_TO_CTX;
+}
+
 static int check_pkt_ptr_alignment(struct bpf_verifier_env *env,
                                   const struct bpf_reg_state *reg,
                                   int off, int size, bool strict)
@@ -1258,6 +1265,12 @@ static int check_xadd(struct bpf_verifier_env *env, int insn_idx, struct bpf_ins
                return -EACCES;
        }
 
+       if (is_ctx_reg(env, insn->dst_reg)) {
+               verbose(env, "BPF_XADD stores into R%d context is not allowed\n",
+                       insn->dst_reg);
+               return -EACCES;
+       }
+
        /* check whether atomic_add can read the memory */
        err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
                               BPF_SIZE(insn->code), BPF_READ, -1);
@@ -1882,17 +1895,13 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 
        dst_reg = &regs[dst];
 
-       if (WARN_ON_ONCE(known && (smin_val != smax_val))) {
-               print_verifier_state(env, env->cur_state);
-               verbose(env,
-                       "verifier internal error: known but bad sbounds\n");
-               return -EINVAL;
-       }
-       if (WARN_ON_ONCE(known && (umin_val != umax_val))) {
-               print_verifier_state(env, env->cur_state);
-               verbose(env,
-                       "verifier internal error: known but bad ubounds\n");
-               return -EINVAL;
+       if ((known && (smin_val != smax_val || umin_val != umax_val)) ||
+           smin_val > smax_val || umin_val > umax_val) {
+               /* Taint dst register if offset had invalid bounds derived from
+                * e.g. dead branches.
+                */
+               __mark_reg_unknown(dst_reg);
+               return 0;
        }
 
        if (BPF_CLASS(insn->code) != BPF_ALU64) {
@@ -2084,6 +2093,15 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
        src_known = tnum_is_const(src_reg.var_off);
        dst_known = tnum_is_const(dst_reg->var_off);
 
+       if ((src_known && (smin_val != smax_val || umin_val != umax_val)) ||
+           smin_val > smax_val || umin_val > umax_val) {
+               /* Taint dst register if offset had invalid bounds derived from
+                * e.g. dead branches.
+                */
+               __mark_reg_unknown(dst_reg);
+               return 0;
+       }
+
        if (!src_known &&
            opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
                __mark_reg_unknown(dst_reg);
@@ -2493,6 +2511,11 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        return -EINVAL;
                }
 
+               if (opcode == BPF_ARSH && BPF_CLASS(insn->code) != BPF_ALU64) {
+                       verbose(env, "BPF_ARSH not supported for 32 bit ALU\n");
+                       return -EINVAL;
+               }
+
                if ((opcode == BPF_LSH || opcode == BPF_RSH ||
                     opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
                        int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;
@@ -3988,6 +4011,12 @@ static int do_check(struct bpf_verifier_env *env)
                        if (err)
                                return err;
 
+                       if (is_ctx_reg(env, insn->dst_reg)) {
+                               verbose(env, "BPF_ST stores into R%d context is not allowed\n",
+                                       insn->dst_reg);
+                               return -EACCES;
+                       }
+
                        /* check that memory (dst_reg + off) is writeable */
                        err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
                                               BPF_SIZE(insn->code), BPF_WRITE,
@@ -4440,6 +4469,24 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
        int i, cnt, delta = 0;
 
        for (i = 0; i < insn_cnt; i++, insn++) {
+               if (insn->code == (BPF_ALU | BPF_MOD | BPF_X) ||
+                   insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
+                       /* due to JIT bugs clear upper 32-bits of src register
+                        * before div/mod operation
+                        */
+                       insn_buf[0] = BPF_MOV32_REG(insn->src_reg, insn->src_reg);
+                       insn_buf[1] = *insn;
+                       cnt = 2;
+                       new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
+                       if (!new_prog)
+                               return -ENOMEM;
+
+                       delta    += cnt - 1;
+                       env->prog = prog = new_prog;
+                       insn      = new_prog->insnsi + i + delta;
+                       continue;
+               }
+
                if (insn->code != (BPF_JMP | BPF_CALL))
                        continue;
 
@@ -4472,7 +4519,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                         */
                        map_ptr = env->insn_aux_data[i + delta].map_ptr;
                        if (map_ptr == BPF_MAP_PTR_POISON) {
-                               verbose(env, "tail_call obusing map_ptr\n");
+                               verbose(env, "tail_call abusing map_ptr\n");
                                return -EINVAL;
                        }
                        if (!map_ptr->unpriv_array)
index 2cf06c274e4ca6cc66194f4ce0fcb9ad0ad82f88..7e4c4453811967e80250464bd91633e957549375 100644 (file)
@@ -4447,6 +4447,7 @@ static struct cftype cgroup_base_files[] = {
        },
        {
                .name = "cgroup.threads",
+               .flags = CFTYPE_NS_DELEGATABLE,
                .release = cgroup_procs_release,
                .seq_start = cgroup_threads_start,
                .seq_next = cgroup_procs_next,
index 4a1c33416b6a2daa8f1a0ecd5641b613fc281983..e2764d767f186eb7965b514b7d9636659608dcf5 100644 (file)
@@ -51,16 +51,16 @@ void __delayacct_tsk_init(struct task_struct *tsk)
  * Finish delay accounting for a statistic using its timestamps (@start),
  * accumalator (@total) and @count
  */
-static void delayacct_end(u64 *start, u64 *total, u32 *count)
+static void delayacct_end(spinlock_t *lock, u64 *start, u64 *total, u32 *count)
 {
        s64 ns = ktime_get_ns() - *start;
        unsigned long flags;
 
        if (ns > 0) {
-               spin_lock_irqsave(&current->delays->lock, flags);
+               spin_lock_irqsave(lock, flags);
                *total += ns;
                (*count)++;
-               spin_unlock_irqrestore(&current->delays->lock, flags);
+               spin_unlock_irqrestore(lock, flags);
        }
 }
 
@@ -69,17 +69,25 @@ void __delayacct_blkio_start(void)
        current->delays->blkio_start = ktime_get_ns();
 }
 
-void __delayacct_blkio_end(void)
+/*
+ * We cannot rely on the `current` macro, as we haven't yet switched back to
+ * the process being woken.
+ */
+void __delayacct_blkio_end(struct task_struct *p)
 {
-       if (current->delays->flags & DELAYACCT_PF_SWAPIN)
-               /* Swapin block I/O */
-               delayacct_end(&current->delays->blkio_start,
-                       &current->delays->swapin_delay,
-                       &current->delays->swapin_count);
-       else    /* Other block I/O */
-               delayacct_end(&current->delays->blkio_start,
-                       &current->delays->blkio_delay,
-                       &current->delays->blkio_count);
+       struct task_delay_info *delays = p->delays;
+       u64 *total;
+       u32 *count;
+
+       if (p->delays->flags & DELAYACCT_PF_SWAPIN) {
+               total = &delays->swapin_delay;
+               count = &delays->swapin_count;
+       } else {
+               total = &delays->blkio_delay;
+               count = &delays->blkio_count;
+       }
+
+       delayacct_end(&delays->lock, &delays->blkio_start, total, count);
 }
 
 int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
@@ -153,8 +161,10 @@ void __delayacct_freepages_start(void)
 
 void __delayacct_freepages_end(void)
 {
-       delayacct_end(&current->delays->freepages_start,
-                       &current->delays->freepages_delay,
-                       &current->delays->freepages_count);
+       delayacct_end(
+               &current->delays->lock,
+               &current->delays->freepages_start,
+               &current->delays->freepages_delay,
+               &current->delays->freepages_count);
 }
 
index 57d0b3657e16b90268fa3396668bb62e6e54d287..8c5424dd59244f0a7f95dea339048f3bdfffaaba 100644 (file)
@@ -1878,6 +1878,9 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
        struct futex_q *this, *next;
        DEFINE_WAKE_Q(wake_q);
 
+       if (nr_wake < 0 || nr_requeue < 0)
+               return -EINVAL;
+
        /*
         * When PI not supported: return -ENOSYS if requeue_pi is true,
         * consequently the compiler knows requeue_pi is always false past
@@ -2294,21 +2297,17 @@ static void unqueue_me_pi(struct futex_q *q)
        spin_unlock(q->lock_ptr);
 }
 
-/*
- * Fixup the pi_state owner with the new owner.
- *
- * Must be called with hash bucket lock held and mm->sem held for non
- * private futexes.
- */
 static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
-                               struct task_struct *newowner)
+                               struct task_struct *argowner)
 {
-       u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
        struct futex_pi_state *pi_state = q->pi_state;
        u32 uval, uninitialized_var(curval), newval;
-       struct task_struct *oldowner;
+       struct task_struct *oldowner, *newowner;
+       u32 newtid;
        int ret;
 
+       lockdep_assert_held(q->lock_ptr);
+
        raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
 
        oldowner = pi_state->owner;
@@ -2317,11 +2316,17 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
                newtid |= FUTEX_OWNER_DIED;
 
        /*
-        * We are here either because we stole the rtmutex from the
-        * previous highest priority waiter or we are the highest priority
-        * waiter but have failed to get the rtmutex the first time.
+        * We are here because either:
+        *
+        *  - we stole the lock and pi_state->owner needs updating to reflect
+        *    that (@argowner == current),
+        *
+        * or:
+        *
+        *  - someone stole our lock and we need to fix things to point to the
+        *    new owner (@argowner == NULL).
         *
-        * We have to replace the newowner TID in the user space variable.
+        * Either way, we have to replace the TID in the user space variable.
         * This must be atomic as we have to preserve the owner died bit here.
         *
         * Note: We write the user space value _before_ changing the pi_state
@@ -2334,6 +2339,42 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
         * in the PID check in lookup_pi_state.
         */
 retry:
+       if (!argowner) {
+               if (oldowner != current) {
+                       /*
+                        * We raced against a concurrent self; things are
+                        * already fixed up. Nothing to do.
+                        */
+                       ret = 0;
+                       goto out_unlock;
+               }
+
+               if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
+                       /* We got the lock after all, nothing to fix. */
+                       ret = 0;
+                       goto out_unlock;
+               }
+
+               /*
+                * Since we just failed the trylock; there must be an owner.
+                */
+               newowner = rt_mutex_owner(&pi_state->pi_mutex);
+               BUG_ON(!newowner);
+       } else {
+               WARN_ON_ONCE(argowner != current);
+               if (oldowner == current) {
+                       /*
+                        * We raced against a concurrent self; things are
+                        * already fixed up. Nothing to do.
+                        */
+                       ret = 0;
+                       goto out_unlock;
+               }
+               newowner = argowner;
+       }
+
+       newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
+
        if (get_futex_value_locked(&uval, uaddr))
                goto handle_fault;
 
@@ -2434,15 +2475,28 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
                 * Got the lock. We might not be the anticipated owner if we
                 * did a lock-steal - fix up the PI-state in that case:
                 *
-                * We can safely read pi_state->owner without holding wait_lock
-                * because we now own the rt_mutex, only the owner will attempt
-                * to change it.
+                * Speculative pi_state->owner read (we don't hold wait_lock);
+                * since we own the lock pi_state->owner == current is the
+                * stable state, anything else needs more attention.
                 */
                if (q->pi_state->owner != current)
                        ret = fixup_pi_state_owner(uaddr, q, current);
                goto out;
        }
 
+       /*
+        * If we didn't get the lock; check if anybody stole it from us. In
+        * that case, we need to fix up the uval to point to them instead of
+        * us, otherwise bad things happen. [10]
+        *
+        * Another speculative read; pi_state->owner == current is unstable
+        * but needs our attention.
+        */
+       if (q->pi_state->owner == current) {
+               ret = fixup_pi_state_owner(uaddr, q, NULL);
+               goto out;
+       }
+
        /*
         * Paranoia check. If we did not take the lock, then we should not be
         * the owner of the rt_mutex.
index 6f3dba6e4e9e14332dfb02039dd720f84d0348b0..65cc0cb984e6aef64211da9ff693b4dc67968103 100644 (file)
@@ -1290,6 +1290,19 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
        return ret;
 }
 
+static inline int __rt_mutex_slowtrylock(struct rt_mutex *lock)
+{
+       int ret = try_to_take_rt_mutex(lock, current, NULL);
+
+       /*
+        * try_to_take_rt_mutex() sets the lock waiters bit
+        * unconditionally. Clean this up.
+        */
+       fixup_rt_mutex_waiters(lock);
+
+       return ret;
+}
+
 /*
  * Slow path try-lock function:
  */
@@ -1312,13 +1325,7 @@ static inline int rt_mutex_slowtrylock(struct rt_mutex *lock)
         */
        raw_spin_lock_irqsave(&lock->wait_lock, flags);
 
-       ret = try_to_take_rt_mutex(lock, current, NULL);
-
-       /*
-        * try_to_take_rt_mutex() sets the lock waiters bit
-        * unconditionally. Clean this up.
-        */
-       fixup_rt_mutex_waiters(lock);
+       ret = __rt_mutex_slowtrylock(lock);
 
        raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
 
@@ -1505,6 +1512,11 @@ int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
        return rt_mutex_slowtrylock(lock);
 }
 
+int __sched __rt_mutex_futex_trylock(struct rt_mutex *lock)
+{
+       return __rt_mutex_slowtrylock(lock);
+}
+
 /**
  * rt_mutex_timed_lock - lock a rt_mutex interruptible
  *                     the timeout structure is provided
index 124e98ca0b174153d14f3c0ddf49109ea8cb8960..68686b3ec3c17cb199a72300f06e2904640ff189 100644 (file)
@@ -148,6 +148,7 @@ extern bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock,
                                 struct rt_mutex_waiter *waiter);
 
 extern int rt_mutex_futex_trylock(struct rt_mutex *l);
+extern int __rt_mutex_futex_trylock(struct rt_mutex *l);
 
 extern void rt_mutex_futex_unlock(struct rt_mutex *lock);
 extern bool __rt_mutex_futex_unlock(struct rt_mutex *lock,
index 644fa2e3d993b5ef1bd1c57e4286168daadf14ff..a7bf32aabfda7369dc79036104aa6fe2fded3829 100644 (file)
@@ -2056,7 +2056,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
        p->state = TASK_WAKING;
 
        if (p->in_iowait) {
-               delayacct_blkio_end();
+               delayacct_blkio_end(p);
                atomic_dec(&task_rq(p)->nr_iowait);
        }
 
@@ -2069,7 +2069,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 #else /* CONFIG_SMP */
 
        if (p->in_iowait) {
-               delayacct_blkio_end();
+               delayacct_blkio_end(p);
                atomic_dec(&task_rq(p)->nr_iowait);
        }
 
@@ -2122,7 +2122,7 @@ static void try_to_wake_up_local(struct task_struct *p, struct rq_flags *rf)
 
        if (!task_on_rq_queued(p)) {
                if (p->in_iowait) {
-                       delayacct_blkio_end();
+                       delayacct_blkio_end(p);
                        atomic_dec(&rq->nr_iowait);
                }
                ttwu_activate(rq, p, ENQUEUE_WAKEUP | ENQUEUE_NOCLOCK);
index 89a9e1b4264a07a9a6d69e37759c27ced8b4de37..0bcf00e3ce482b17392e30904decf86d459c4928 100644 (file)
@@ -1696,7 +1696,7 @@ void run_local_timers(void)
        hrtimer_run_queues();
        /* Raise the softirq only if required. */
        if (time_before(jiffies, base->clk)) {
-               if (!IS_ENABLED(CONFIG_NO_HZ_COMMON) || !base->nohz_active)
+               if (!IS_ENABLED(CONFIG_NO_HZ_COMMON))
                        return;
                /* CPU is awake, so check the deferrable base. */
                base++;
index 904c952ac3833bdfd0e017dff437d26f4c545e3d..f54dc62b599ccbdd5d8246c2a370bd3b01b7960a 100644 (file)
@@ -355,7 +355,7 @@ config PROFILE_ANNOTATED_BRANCHES
          on if you need to profile the system's use of these macros.
 
 config PROFILE_ALL_BRANCHES
-       bool "Profile all if conditionals"
+       bool "Profile all if conditionals" if !FORTIFY_SOURCE
        select TRACE_BRANCH_PROFILING
        help
          This tracer profiles all branch conditions. Every if ()
index 9ab18995ff1ebeea0e862f48b43f64924c87e127..5af2842dea962944b8960f2f74dab5a08bfa1b39 100644 (file)
@@ -2534,29 +2534,58 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
  * The lock and unlock are done within a preempt disable section.
  * The current_context per_cpu variable can only be modified
  * by the current task between lock and unlock. But it can
- * be modified more than once via an interrupt. There are four
- * different contexts that we need to consider.
+ * be modified more than once via an interrupt. To pass this
+ * information from the lock to the unlock without having to
+ * access the 'in_interrupt()' functions again (which do show
+ * a bit of overhead in something as critical as function tracing,
+ * we use a bitmask trick.
  *
- *  Normal context.
- *  SoftIRQ context
- *  IRQ context
- *  NMI context
+ *  bit 0 =  NMI context
+ *  bit 1 =  IRQ context
+ *  bit 2 =  SoftIRQ context
+ *  bit 3 =  normal context.
  *
- * If for some reason the ring buffer starts to recurse, we
- * only allow that to happen at most 4 times (one for each
- * context). If it happens 5 times, then we consider this a
- * recusive loop and do not let it go further.
+ * This works because this is the order of contexts that can
+ * preempt other contexts. A SoftIRQ never preempts an IRQ
+ * context.
+ *
+ * When the context is determined, the corresponding bit is
+ * checked and set (if it was set, then a recursion of that context
+ * happened).
+ *
+ * On unlock, we need to clear this bit. To do so, just subtract
+ * 1 from the current_context and AND it to itself.
+ *
+ * (binary)
+ *  101 - 1 = 100
+ *  101 & 100 = 100 (clearing bit zero)
+ *
+ *  1010 - 1 = 1001
+ *  1010 & 1001 = 1000 (clearing bit 1)
+ *
+ * The least significant bit can be cleared this way, and it
+ * just so happens that it is the same bit corresponding to
+ * the current context.
  */
 
 static __always_inline int
 trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer)
 {
-       if (cpu_buffer->current_context >= 4)
+       unsigned int val = cpu_buffer->current_context;
+       unsigned long pc = preempt_count();
+       int bit;
+
+       if (!(pc & (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
+               bit = RB_CTX_NORMAL;
+       else
+               bit = pc & NMI_MASK ? RB_CTX_NMI :
+                       pc & HARDIRQ_MASK ? RB_CTX_IRQ : RB_CTX_SOFTIRQ;
+
+       if (unlikely(val & (1 << bit)))
                return 1;
 
-       cpu_buffer->current_context++;
-       /* Interrupts must see this update */
-       barrier();
+       val |= (1 << bit);
+       cpu_buffer->current_context = val;
 
        return 0;
 }
@@ -2564,9 +2593,7 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer)
 static __always_inline void
 trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer)
 {
-       /* Don't let the dec leak out */
-       barrier();
-       cpu_buffer->current_context--;
+       cpu_buffer->current_context &= cpu_buffer->current_context - 1;
 }
 
 /**
index ec0f9aa4e1516bd7fe2ee17b6b12ff27a81d1482..1b87157edbff7c42a0884a3c0f8c0fa46c9d78ee 100644 (file)
@@ -2213,6 +2213,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)
 {
        struct trace_event_call *call, *p;
        const char *last_system = NULL;
+       bool first = false;
        int last_i;
        int i;
 
@@ -2220,15 +2221,28 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)
        list_for_each_entry_safe(call, p, &ftrace_events, list) {
                /* events are usually grouped together with systems */
                if (!last_system || call->class->system != last_system) {
+                       first = true;
                        last_i = 0;
                        last_system = call->class->system;
                }
 
+               /*
+                * Since calls are grouped by systems, the likelyhood that the
+                * next call in the iteration belongs to the same system as the
+                * previous call is high. As an optimization, we skip seaching
+                * for a map[] that matches the call's system if the last call
+                * was from the same system. That's what last_i is for. If the
+                * call has the same system as the previous call, then last_i
+                * will be the index of the first map[] that has a matching
+                * system.
+                */
                for (i = last_i; i < len; i++) {
                        if (call->class->system == map[i]->system) {
                                /* Save the first system if need be */
-                               if (!last_i)
+                               if (first) {
                                        last_i = i;
+                                       first = false;
+                               }
                                update_event_printk(call, map[i]);
                        }
                }
index 43d18cb46308385865d14ce40906c4646d378063..f699122dab321793bffa596da732d793d23d379b 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/moduleparam.h>
 #include <linux/uaccess.h>
 #include <linux/sched/isolation.h>
+#include <linux/nmi.h>
 
 #include "workqueue_internal.h"
 
@@ -4463,6 +4464,12 @@ void show_workqueue_state(void)
                        if (pwq->nr_active || !list_empty(&pwq->delayed_works))
                                show_pwq(pwq);
                        spin_unlock_irqrestore(&pwq->pool->lock, flags);
+                       /*
+                        * We could be printing a lot from atomic context, e.g.
+                        * sysrq-t -> show_workqueue_state(). Avoid triggering
+                        * hard lockup.
+                        */
+                       touch_nmi_watchdog();
                }
        }
 
@@ -4490,6 +4497,12 @@ void show_workqueue_state(void)
                pr_cont("\n");
        next_pool:
                spin_unlock_irqrestore(&pool->lock, flags);
+               /*
+                * We could be printing a lot from atomic context, e.g.
+                * sysrq-t -> show_workqueue_state(). Avoid triggering
+                * hard lockup.
+                */
+               touch_nmi_watchdog();
        }
 
        rcu_read_unlock_sched();
index ca5674cbaff2b65c4e51086e5922fbbd274f2cfa..793004608332cdbcca68bee01b1c31f8e8ef6170 100644 (file)
@@ -2857,8 +2857,11 @@ int do_swap_page(struct vm_fault *vmf)
        int ret = 0;
        bool vma_readahead = swap_use_vma_readahead();
 
-       if (vma_readahead)
+       if (vma_readahead) {
                page = swap_readahead_detect(vmf, &swap_ra);
+               swapcache = page;
+       }
+
        if (!pte_unmap_same(vma->vm_mm, vmf->pmd, vmf->pte, vmf->orig_pte)) {
                if (page)
                        put_page(page);
@@ -2889,9 +2892,12 @@ int do_swap_page(struct vm_fault *vmf)
 
 
        delayacct_set_flag(DELAYACCT_PF_SWAPIN);
-       if (!page)
+       if (!page) {
                page = lookup_swap_cache(entry, vma_readahead ? vma : NULL,
                                         vmf->address);
+               swapcache = page;
+       }
+
        if (!page) {
                struct swap_info_struct *si = swp_swap_info(entry);
 
index 8592543a0f1599b1ab0c95620ae8ad45e67b7760..270a8219ccd03b0099c48bd267075a7b0d8eadd6 100644 (file)
@@ -616,7 +616,6 @@ static void init_early_allocated_pages(void)
 {
        pg_data_t *pgdat;
 
-       drain_all_pages(NULL);
        for_each_online_pgdat(pgdat)
                init_zones_in_node(pgdat);
 }
index 325c56043007d89886203626a2a139f1ab8fc52a..086a4abdfa7cfcfad4934eb52613f4fe57723eb2 100644 (file)
@@ -543,3 +543,7 @@ static void p9_trans_xen_exit(void)
        return xenbus_unregister_driver(&xen_9pfs_front_driver);
 }
 module_exit(p9_trans_xen_exit);
+
+MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
+MODULE_DESCRIPTION("Xen Transport for 9P");
+MODULE_LICENSE("GPL");
index 003b2d6d655f3914b8edfc02acde16f57010183a..4d7f988a3130d6544fcd4c96df751328395ecdc7 100644 (file)
@@ -721,20 +721,16 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 
-       if (WARN_ONCE(dev->type != ARPHRD_CAN ||
-                     skb->len != CAN_MTU ||
-                     cfd->len > CAN_MAX_DLEN,
-                     "PF_CAN: dropped non conform CAN skbuf: "
-                     "dev type %d, len %d, datalen %d\n",
-                     dev->type, skb->len, cfd->len))
-               goto drop;
+       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU ||
+                    cfd->len > CAN_MAX_DLEN)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, datalen %d\n",
+                            dev->type, skb->len, cfd->len);
+               kfree_skb(skb);
+               return NET_RX_DROP;
+       }
 
        can_receive(skb, dev);
        return NET_RX_SUCCESS;
-
-drop:
-       kfree_skb(skb);
-       return NET_RX_DROP;
 }
 
 static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
@@ -742,20 +738,16 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 
-       if (WARN_ONCE(dev->type != ARPHRD_CAN ||
-                     skb->len != CANFD_MTU ||
-                     cfd->len > CANFD_MAX_DLEN,
-                     "PF_CAN: dropped non conform CAN FD skbuf: "
-                     "dev type %d, len %d, datalen %d\n",
-                     dev->type, skb->len, cfd->len))
-               goto drop;
+       if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU ||
+                    cfd->len > CANFD_MAX_DLEN)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN FD skbuf: dev type %d, len %d, datalen %d\n",
+                            dev->type, skb->len, cfd->len);
+               kfree_skb(skb);
+               return NET_RX_DROP;
+       }
 
        can_receive(skb, dev);
        return NET_RX_SUCCESS;
-
-drop:
-       kfree_skb(skb);
-       return NET_RX_DROP;
 }
 
 /*
index d339ef170df60282c8812b63148c479820b3008f..1c0eb436671f3b1bafc378e8c2b5e47ff79a5db3 100644 (file)
@@ -458,6 +458,10 @@ static int bpf_convert_filter(struct sock_filter *prog, int len,
                            convert_bpf_extensions(fp, &insn))
                                break;
 
+                       if (fp->code == (BPF_ALU | BPF_DIV | BPF_X) ||
+                           fp->code == (BPF_ALU | BPF_MOD | BPF_X))
+                               *insn++ = BPF_MOV32_REG(BPF_REG_X, BPF_REG_X);
+
                        *insn = BPF_RAW_INSN(fp->code, BPF_REG_A, BPF_REG_X, 0, fp->k);
                        break;
 
index 15ce300637650e17fcab7e378b20fe7972686d46..544bddf08e13c7f6e47aadc737244c9ba5af56b2 100644 (file)
@@ -976,8 +976,8 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 out_good:
        ret = true;
 
-       key_control->thoff = (u16)nhoff;
 out:
+       key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen);
        key_basic->n_proto = proto;
        key_basic->ip_proto = ip_proto;
 
@@ -985,7 +985,6 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
 out_bad:
        ret = false;
-       key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen);
        goto out;
 }
 EXPORT_SYMBOL(__skb_flow_dissect);
index d1f5fe986edda5ff886575be0eea0b361e2be7ff..7f831711b6e03d63fe12f3a7dfec85f18f531c15 100644 (file)
@@ -532,7 +532,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
        if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
                nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
 
-       hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+       hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
 
        if (n->parms->dead) {
                rc = ERR_PTR(-EINVAL);
@@ -544,7 +544,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
             n1 != NULL;
             n1 = rcu_dereference_protected(n1->next,
                        lockdep_is_held(&tbl->lock))) {
-               if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
+               if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
                        if (want_ref)
                                neigh_hold(n1);
                        rc = n1;
index a8d7c5a9fb0523db487e8e51a43dadc192046b1f..6c231b43974d93c213f3e51cfd40a1dceddf48ee 100644 (file)
@@ -223,11 +223,16 @@ static bool arp_key_eq(const struct neighbour *neigh, const void *pkey)
 
 static int arp_constructor(struct neighbour *neigh)
 {
-       __be32 addr = *(__be32 *)neigh->primary_key;
+       __be32 addr;
        struct net_device *dev = neigh->dev;
        struct in_device *in_dev;
        struct neigh_parms *parms;
+       u32 inaddr_any = INADDR_ANY;
 
+       if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+               memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len);
+
+       addr = *(__be32 *)neigh->primary_key;
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
        if (!in_dev) {
index d57aa64fa7c7d44307e6ecf9bf401c0a8ea21b87..61fe6e4d23fcb8d3cd2689566afa17c0952410b8 100644 (file)
@@ -981,6 +981,7 @@ static int esp_init_state(struct xfrm_state *x)
 
                switch (encap->encap_type) {
                default:
+                       err = -EINVAL;
                        goto error;
                case UDP_ENCAP_ESPINUDP:
                        x->props.header_len += sizeof(struct udphdr);
index f8b918c766b0af1e572ed895dcf2435af92016a9..b1338e576d00389db8b6ce2383550e9aa22a4399 100644 (file)
@@ -38,7 +38,8 @@ static struct sk_buff **esp4_gro_receive(struct sk_buff **head,
        __be32 spi;
        int err;
 
-       skb_pull(skb, offset);
+       if (!pskb_pull(skb, offset))
+               return NULL;
 
        if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
                goto out;
index 43b69af242e18d640db1bff451d2ee229fc5e08f..4e153b23bceca1b8f6071febf4bb0df8cca7f12f 100644 (file)
@@ -2762,6 +2762,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                if (err == 0 && rt->dst.error)
                        err = -rt->dst.error;
        } else {
+               fl4.flowi4_iif = LOOPBACK_IFINDEX;
                rt = ip_route_output_key_hash_rcu(net, &fl4, &res, skb);
                err = 0;
                if (IS_ERR(rt))
index a902ff8f59be3ed7e1f28afc234a0e56eca4e684..1a7f00cd4803b7d37160bfe8a161510b25d1ab89 100644 (file)
@@ -890,13 +890,12 @@ static int esp6_init_state(struct xfrm_state *x)
                        x->props.header_len += IPV4_BEET_PHMAXLEN +
                                               (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
                break;
+       default:
        case XFRM_MODE_TRANSPORT:
                break;
        case XFRM_MODE_TUNNEL:
                x->props.header_len += sizeof(struct ipv6hdr);
                break;
-       default:
-               goto error;
        }
 
        align = ALIGN(crypto_aead_blocksize(aead), 4);
index 333a478aa1610441ce08e3ac82e92d3b48e3222d..dd9627490c7ca22bda9fe3cca13b72c60f6865de 100644 (file)
@@ -60,7 +60,8 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
        int nhoff;
        int err;
 
-       skb_pull(skb, offset);
+       if (!pskb_pull(skb, offset))
+               return NULL;
 
        if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
                goto out;
index 9dcc3924a97561d689a1fd8862742d9543339dd2..217683d40f129e1414e9c36ceadc5ec8e71d6a86 100644 (file)
@@ -1226,8 +1226,14 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
                }
 
                if (!rcu_access_pointer(fn->leaf)) {
-                       atomic_inc(&rt->rt6i_ref);
-                       rcu_assign_pointer(fn->leaf, rt);
+                       if (fn->fn_flags & RTN_TL_ROOT) {
+                               /* put back null_entry for root node */
+                               rcu_assign_pointer(fn->leaf,
+                                           info->nl_net->ipv6.ip6_null_entry);
+                       } else {
+                               atomic_inc(&rt->rt6i_ref);
+                               rcu_assign_pointer(fn->leaf, rt);
+                       }
                }
                fn = sn;
        }
index 772695960890893f9ab7862cf64728b783f5bb96..873549228ccb733c76186666ad5671f74ae259a0 100644 (file)
@@ -337,11 +337,12 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net,
 
        nt->dev = dev;
        nt->net = dev_net(dev);
-       ip6gre_tnl_link_config(nt, 1);
 
        if (register_netdevice(dev) < 0)
                goto failed_free;
 
+       ip6gre_tnl_link_config(nt, 1);
+
        /* Can use a lockless transmit, unless we generate output sequences */
        if (!(nt->parms.o_flags & TUNNEL_SEQ))
                dev->features |= NETIF_F_LLTX;
@@ -1303,7 +1304,6 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
 
 static int ip6gre_tap_init(struct net_device *dev)
 {
-       struct ip6_tnl *tunnel;
        int ret;
 
        ret = ip6gre_tunnel_init_common(dev);
@@ -1312,10 +1312,6 @@ static int ip6gre_tap_init(struct net_device *dev)
 
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
-       tunnel = netdev_priv(dev);
-
-       ip6gre_tnl_link_config(tunnel, 1);
-
        return 0;
 }
 
@@ -1408,12 +1404,16 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
 
        nt->dev = dev;
        nt->net = dev_net(dev);
-       ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]);
 
        err = register_netdevice(dev);
        if (err)
                goto out;
 
+       ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]);
+
+       if (tb[IFLA_MTU])
+               ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+
        dev_hold(dev);
        ip6gre_tunnel_link(ign, nt);
 
index 688ba5f7516b37c87b879036dce781bdcfa01739..4f7d8de56611472575862d50b9fd18f677d36e43 100644 (file)
@@ -1206,14 +1206,16 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
        v6_cork->tclass = ipc6->tclass;
        if (rt->dst.flags & DST_XFRM_TUNNEL)
                mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
-                     rt->dst.dev->mtu : dst_mtu(&rt->dst);
+                     READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst);
        else
                mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
-                     rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+                     READ_ONCE(rt->dst.dev->mtu) : dst_mtu(rt->dst.path);
        if (np->frag_size < mtu) {
                if (np->frag_size)
                        mtu = np->frag_size;
        }
+       if (mtu < IPV6_MIN_MTU)
+               return -EINVAL;
        cork->base.fragsize = mtu;
        if (dst_allfrag(rt->dst.path))
                cork->base.flags |= IPCORK_ALLFRAG;
@@ -1733,6 +1735,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
        cork.base.flags = 0;
        cork.base.addr = 0;
        cork.base.opt = NULL;
+       cork.base.dst = NULL;
        v6_cork.opt = NULL;
        err = ip6_setup_cork(sk, &cork, &v6_cork, ipc6, rt, fl6);
        if (err) {
index 3dffb892d52cf191f53e282bff9fb65594605476..7e2e7188e7f4a28aa45c26848364ab0c297161a2 100644 (file)
@@ -401,6 +401,11 @@ static int verify_address_len(const void *p)
 #endif
        int len;
 
+       if (sp->sadb_address_len <
+           DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family),
+                        sizeof(uint64_t)))
+               return -EINVAL;
+
        switch (addr->sa_family) {
        case AF_INET:
                len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t));
@@ -511,6 +516,9 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void *
                uint16_t ext_type;
                int ext_len;
 
+               if (len < sizeof(*ehdr))
+                       return -EINVAL;
+
                ext_len  = ehdr->sadb_ext_len;
                ext_len *= sizeof(uint64_t);
                ext_type = ehdr->sadb_ext_type;
@@ -2194,8 +2202,10 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
                return PTR_ERR(out_skb);
 
        err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
-       if (err < 0)
+       if (err < 0) {
+               kfree_skb(out_skb);
                return err;
+       }
 
        out_hdr = (struct sadb_msg *) out_skb->data;
        out_hdr->sadb_msg_version = PF_KEY_V2;
index 79cc1bf36e4af7d2c70575e56203a482ba2dca97..84a4e4c3be4b9738ed9277a09d217327137588f8 100644 (file)
@@ -2384,13 +2384,14 @@ int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
                                                   struct nlmsghdr *,
                                                   struct netlink_ext_ack *))
 {
-       struct netlink_ext_ack extack = {};
+       struct netlink_ext_ack extack;
        struct nlmsghdr *nlh;
        int err;
 
        while (skb->len >= nlmsg_total_size(0)) {
                int msglen;
 
+               memset(&extack, 0, sizeof(extack));
                nlh = nlmsg_hdr(skb);
                err = 0;
 
index 624ea74353dd3ba403ccedc822f1c9574982e709..f143908b651dffc38cdbe9ef1d5235015ff08b6a 100644 (file)
@@ -49,7 +49,6 @@
 #include <net/mpls.h>
 #include <net/vxlan.h>
 #include <net/tun_proto.h>
-#include <net/erspan.h>
 
 #include "flow_netlink.h"
 
@@ -334,8 +333,7 @@ size_t ovs_tun_key_attr_size(void)
                 * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
                 */
                + nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
-               + nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_DST */
-               + nla_total_size(4);   /* OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS */
+               + nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
 }
 
 static size_t ovs_nsh_key_attr_size(void)
@@ -402,7 +400,6 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
                                                .next = ovs_vxlan_ext_key_lens },
        [OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = sizeof(struct in6_addr) },
        [OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = sizeof(struct in6_addr) },
-       [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS]   = { .len = sizeof(u32) },
 };
 
 static const struct ovs_len_tbl
@@ -634,33 +631,6 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
        return 0;
 }
 
-static int erspan_tun_opt_from_nlattr(const struct nlattr *attr,
-                                     struct sw_flow_match *match, bool is_mask,
-                                     bool log)
-{
-       unsigned long opt_key_offset;
-       struct erspan_metadata opts;
-
-       BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
-
-       memset(&opts, 0, sizeof(opts));
-       opts.index = nla_get_be32(attr);
-
-       /* Index has only 20-bit */
-       if (ntohl(opts.index) & ~INDEX_MASK) {
-               OVS_NLERR(log, "ERSPAN index number %x too large.",
-                         ntohl(opts.index));
-               return -EINVAL;
-       }
-
-       SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), is_mask);
-       opt_key_offset = TUN_METADATA_OFFSET(sizeof(opts));
-       SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, &opts, sizeof(opts),
-                                 is_mask);
-
-       return 0;
-}
-
 static int ip_tun_from_nlattr(const struct nlattr *attr,
                              struct sw_flow_match *match, bool is_mask,
                              bool log)
@@ -768,19 +738,6 @@ static int ip_tun_from_nlattr(const struct nlattr *attr,
                        break;
                case OVS_TUNNEL_KEY_ATTR_PAD:
                        break;
-               case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
-                       if (opts_type) {
-                               OVS_NLERR(log, "Multiple metadata blocks provided");
-                               return -EINVAL;
-                       }
-
-                       err = erspan_tun_opt_from_nlattr(a, match, is_mask, log);
-                       if (err)
-                               return err;
-
-                       tun_flags |= TUNNEL_ERSPAN_OPT;
-                       opts_type = type;
-                       break;
                default:
                        OVS_NLERR(log, "Unknown IP tunnel attribute %d",
                                  type);
@@ -905,10 +862,6 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb,
                else if (output->tun_flags & TUNNEL_VXLAN_OPT &&
                         vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
                        return -EMSGSIZE;
-               else if (output->tun_flags & TUNNEL_ERSPAN_OPT &&
-                        nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
-                                     ((struct erspan_metadata *)tun_opts)->index))
-                       return -EMSGSIZE;
        }
 
        return 0;
@@ -2533,8 +2486,6 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
                        break;
                case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
                        break;
-               case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
-                       break;
                }
        };
 
index 8d78e7f4ecc33082517aaab5767a30c119f49dc0..a62586e2dbdb91e4a04226a410035e0cde94b91d 100644 (file)
@@ -183,10 +183,17 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
        return 0;
 }
 
+static u32 cls_bpf_flags(u32 flags)
+{
+       return flags & CLS_BPF_SUPPORTED_GEN_FLAGS;
+}
+
 static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
                           struct cls_bpf_prog *oldprog)
 {
-       if (prog && oldprog && prog->gen_flags != oldprog->gen_flags)
+       if (prog && oldprog &&
+           cls_bpf_flags(prog->gen_flags) !=
+           cls_bpf_flags(oldprog->gen_flags))
                return -EINVAL;
 
        if (prog && tc_skip_hw(prog->gen_flags))
index 0f1eab99ff4edb6e7e27f4b4b34552b5ee996cbf..52529b7f8d963ef952b71c086c52ab1588b1d106 100644 (file)
@@ -1063,17 +1063,6 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
        }
 
        if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
-               if (qdisc_is_percpu_stats(sch)) {
-                       sch->cpu_bstats =
-                               netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
-                       if (!sch->cpu_bstats)
-                               goto err_out4;
-
-                       sch->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
-                       if (!sch->cpu_qstats)
-                               goto err_out4;
-               }
-
                if (tca[TCA_STAB]) {
                        stab = qdisc_get_stab(tca[TCA_STAB]);
                        if (IS_ERR(stab)) {
@@ -1115,7 +1104,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
                ops->destroy(sch);
 err_out3:
        dev_put(dev);
-       kfree((char *) sch - sch->padded);
+       qdisc_free(sch);
 err_out2:
        module_put(ops->owner);
 err_out:
@@ -1123,8 +1112,6 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
        return NULL;
 
 err_out4:
-       free_percpu(sch->cpu_bstats);
-       free_percpu(sch->cpu_qstats);
        /*
         * Any broken qdiscs that would require a ops->reset() here?
         * The qdisc was never in action so it shouldn't be necessary.
index 661c7144b53af048b3a65484777910e2d60f25aa..cac003fddf3e5d54e8af29af4f69b80bbd7dc331 100644 (file)
@@ -633,6 +633,19 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        qdisc_skb_head_init(&sch->q);
        spin_lock_init(&sch->q.lock);
 
+       if (ops->static_flags & TCQ_F_CPUSTATS) {
+               sch->cpu_bstats =
+                       netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
+               if (!sch->cpu_bstats)
+                       goto errout1;
+
+               sch->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
+               if (!sch->cpu_qstats) {
+                       free_percpu(sch->cpu_bstats);
+                       goto errout1;
+               }
+       }
+
        spin_lock_init(&sch->busylock);
        lockdep_set_class(&sch->busylock,
                          dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
@@ -642,6 +655,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
                          dev->qdisc_running_key ?: &qdisc_running_key);
 
        sch->ops = ops;
+       sch->flags = ops->static_flags;
        sch->enqueue = ops->enqueue;
        sch->dequeue = ops->dequeue;
        sch->dev_queue = dev_queue;
@@ -649,6 +663,8 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        refcount_set(&sch->refcnt, 1);
 
        return sch;
+errout1:
+       kfree(p);
 errout:
        return ERR_PTR(err);
 }
@@ -698,7 +714,7 @@ void qdisc_reset(struct Qdisc *qdisc)
 }
 EXPORT_SYMBOL(qdisc_reset);
 
-static void qdisc_free(struct Qdisc *qdisc)
+void qdisc_free(struct Qdisc *qdisc)
 {
        if (qdisc_is_percpu_stats(qdisc)) {
                free_percpu(qdisc->cpu_bstats);
index fc1286f499c1462ab29c5054f734237788974e0e..003e1b063447d2504ea886f1fd11dce8e446b38a 100644 (file)
@@ -66,7 +66,6 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
 {
        struct ingress_sched_data *q = qdisc_priv(sch);
        struct net_device *dev = qdisc_dev(sch);
-       int err;
 
        net_inc_ingress_queue();
 
@@ -76,13 +75,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
        q->block_info.chain_head_change = clsact_chain_head_change;
        q->block_info.chain_head_change_priv = &q->miniqp;
 
-       err = tcf_block_get_ext(&q->block, sch, &q->block_info);
-       if (err)
-               return err;
-
-       sch->flags |= TCQ_F_CPUSTATS;
-
-       return 0;
+       return tcf_block_get_ext(&q->block, sch, &q->block_info);
 }
 
 static void ingress_destroy(struct Qdisc *sch)
@@ -121,6 +114,7 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
        .cl_ops         =       &ingress_class_ops,
        .id             =       "ingress",
        .priv_size      =       sizeof(struct ingress_sched_data),
+       .static_flags   =       TCQ_F_CPUSTATS,
        .init           =       ingress_init,
        .destroy        =       ingress_destroy,
        .dump           =       ingress_dump,
@@ -192,13 +186,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
        q->egress_block_info.chain_head_change = clsact_chain_head_change;
        q->egress_block_info.chain_head_change_priv = &q->miniqp_egress;
 
-       err = tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info);
-       if (err)
-               return err;
-
-       sch->flags |= TCQ_F_CPUSTATS;
-
-       return 0;
+       return tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info);
 }
 
 static void clsact_destroy(struct Qdisc *sch)
@@ -225,6 +213,7 @@ static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
        .cl_ops         =       &clsact_class_ops,
        .id             =       "clsact",
        .priv_size      =       sizeof(struct clsact_sched_data),
+       .static_flags   =       TCQ_F_CPUSTATS,
        .init           =       clsact_init,
        .destroy        =       clsact_destroy,
        .dump           =       ingress_dump,
index 3b18085e3b10253f3f81be7a6747b50ef9357db2..5d4c15bf66d26219415596598a1f72d29b63a798 100644 (file)
@@ -826,6 +826,7 @@ static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp)
        case AF_INET:
                if (!__ipv6_only_sock(sctp_opt2sk(sp)))
                        return 1;
+               /* fallthru */
        default:
                return 0;
        }
index 7d67feeeffc1e758ae4be4ef1ddaea23276d1f5e..c4ec99b2015002b273071e6fb1ec3c59c9f61154 100644 (file)
@@ -918,9 +918,9 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
                        break;
 
                case SCTP_CID_ABORT:
-                       if (sctp_test_T_bit(chunk)) {
+                       if (sctp_test_T_bit(chunk))
                                packet->vtag = asoc->c.my_vtag;
-                       }
+                       /* fallthru */
                /* The following chunks are "response" chunks, i.e.
                 * they are generated in response to something we
                 * received.  If we are sending these, then we can
index 9b01e994f66108a12abc31f452482f1de8749d84..039fcb618c34985f5b2a337d6a0876bca24b28da 100644 (file)
@@ -85,7 +85,7 @@
 static int sctp_writeable(struct sock *sk);
 static void sctp_wfree(struct sk_buff *skb);
 static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
-                               size_t msg_len, struct sock **orig_sk);
+                               size_t msg_len);
 static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p);
 static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
 static int sctp_wait_for_accept(struct sock *sk, long timeo);
@@ -335,16 +335,14 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
        if (len < sizeof (struct sockaddr))
                return NULL;
 
+       if (!opt->pf->af_supported(addr->sa.sa_family, opt))
+               return NULL;
+
        /* V4 mapped address are really of AF_INET family */
        if (addr->sa.sa_family == AF_INET6 &&
-           ipv6_addr_v4mapped(&addr->v6.sin6_addr)) {
-               if (!opt->pf->af_supported(AF_INET, opt))
-                       return NULL;
-       } else {
-               /* Does this PF support this AF? */
-               if (!opt->pf->af_supported(addr->sa.sa_family, opt))
-                       return NULL;
-       }
+           ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&
+           !opt->pf->af_supported(AF_INET, opt))
+               return NULL;
 
        /* If we get this far, af is valid. */
        af = sctp_get_af_specific(addr->sa.sa_family);
@@ -1883,8 +1881,14 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
                 */
                if (sinit) {
                        if (sinit->sinit_num_ostreams) {
-                               asoc->c.sinit_num_ostreams =
-                                       sinit->sinit_num_ostreams;
+                               __u16 outcnt = sinit->sinit_num_ostreams;
+
+                               asoc->c.sinit_num_ostreams = outcnt;
+                               /* outcnt has been changed, so re-init stream */
+                               err = sctp_stream_init(&asoc->stream, outcnt, 0,
+                                                      GFP_KERNEL);
+                               if (err)
+                                       goto out_free;
                        }
                        if (sinit->sinit_max_instreams) {
                                asoc->c.sinit_max_instreams =
@@ -1971,7 +1975,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
        timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
        if (!sctp_wspace(asoc)) {
                /* sk can be changed by peel off when waiting for buf. */
-               err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len, &sk);
+               err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
                if (err) {
                        if (err == -ESRCH) {
                                /* asoc is already dead. */
@@ -8016,12 +8020,12 @@ void sctp_sock_rfree(struct sk_buff *skb)
 
 /* Helper function to wait for space in the sndbuf.  */
 static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
-                               size_t msg_len, struct sock **orig_sk)
+                               size_t msg_len)
 {
        struct sock *sk = asoc->base.sk;
-       int err = 0;
        long current_timeo = *timeo_p;
        DEFINE_WAIT(wait);
+       int err = 0;
 
        pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc,
                 *timeo_p, msg_len);
@@ -8050,17 +8054,13 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
                release_sock(sk);
                current_timeo = schedule_timeout(current_timeo);
                lock_sock(sk);
-               if (sk != asoc->base.sk) {
-                       release_sock(sk);
-                       sk = asoc->base.sk;
-                       lock_sock(sk);
-               }
+               if (sk != asoc->base.sk)
+                       goto do_error;
 
                *timeo_p = current_timeo;
        }
 
 out:
-       *orig_sk = sk;
        finish_wait(&asoc->wait, &wait);
 
        /* Release the association's refcnt.  */
index 507017fe0f1b5263f819411388240ef64cab935d..9036d8756e731ab02d75a520c489728cee621faf 100644 (file)
@@ -1880,36 +1880,38 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
 
        if (strcmp(name, tipc_bclink_name) == 0) {
                err = tipc_nl_add_bc_link(net, &msg);
-               if (err) {
-                       nlmsg_free(msg.skb);
-                       return err;
-               }
+               if (err)
+                       goto err_free;
        } else {
                int bearer_id;
                struct tipc_node *node;
                struct tipc_link *link;
 
                node = tipc_node_find_by_name(net, name, &bearer_id);
-               if (!node)
-                       return -EINVAL;
+               if (!node) {
+                       err = -EINVAL;
+                       goto err_free;
+               }
 
                tipc_node_read_lock(node);
                link = node->links[bearer_id].link;
                if (!link) {
                        tipc_node_read_unlock(node);
-                       nlmsg_free(msg.skb);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto err_free;
                }
 
                err = __tipc_nl_add_link(net, &msg, link, 0);
                tipc_node_read_unlock(node);
-               if (err) {
-                       nlmsg_free(msg.skb);
-                       return err;
-               }
+               if (err)
+                       goto err_free;
        }
 
        return genlmsg_reply(msg.skb, info);
+
+err_free:
+       nlmsg_free(msg.skb);
+       return err;
 }
 
 int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
index e07ee3ae002300932f8fd41a907cee2fc042738f..736719c8314e83e0c0fca2dabed30a1535fbfdcb 100644 (file)
@@ -367,8 +367,10 @@ static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,
 
        crypto_info = &ctx->crypto_send;
        /* Currently we don't support set crypto info more than one time */
-       if (TLS_CRYPTO_INFO_READY(crypto_info))
+       if (TLS_CRYPTO_INFO_READY(crypto_info)) {
+               rc = -EBUSY;
                goto out;
+       }
 
        rc = copy_from_user(crypto_info, optval, sizeof(*crypto_info));
        if (rc) {
@@ -386,7 +388,7 @@ static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,
        case TLS_CIPHER_AES_GCM_128: {
                if (optlen != sizeof(struct tls12_crypto_info_aes_gcm_128)) {
                        rc = -EINVAL;
-                       goto out;
+                       goto err_crypto_info;
                }
                rc = copy_from_user(crypto_info + 1, optval + sizeof(*crypto_info),
                                    optlen - sizeof(*crypto_info));
@@ -398,7 +400,7 @@ static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,
        }
        default:
                rc = -EINVAL;
-               goto out;
+               goto err_crypto_info;
        }
 
        /* currently SW is default, we will have ethtool in future */
@@ -454,6 +456,15 @@ static int tls_init(struct sock *sk)
        struct tls_context *ctx;
        int rc = 0;
 
+       /* The TLS ulp is currently supported only for TCP sockets
+        * in ESTABLISHED state.
+        * Supporting sockets in LISTEN state will require us
+        * to modify the accept implementation to clone rather then
+        * share the ulp context.
+        */
+       if (sk->sk_state != TCP_ESTABLISHED)
+               return -ENOTSUPP;
+
        /* allocate tls context */
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
index 73d19210dd497193ff545ee15305113e6090f731..61f394d369bf86d69c44b84950632cd5c3519905 100644 (file)
@@ -391,7 +391,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 
        while (msg_data_left(msg)) {
                if (sk->sk_err) {
-                       ret = sk->sk_err;
+                       ret = -sk->sk_err;
                        goto send_end;
                }
 
@@ -544,7 +544,7 @@ int tls_sw_sendpage(struct sock *sk, struct page *page,
                size_t copy, required_size;
 
                if (sk->sk_err) {
-                       ret = sk->sk_err;
+                       ret = -sk->sk_err;
                        goto sendpage_end;
                }
 
@@ -681,18 +681,17 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
        }
        default:
                rc = -EINVAL;
-               goto out;
+               goto free_priv;
        }
 
        ctx->prepend_size = TLS_HEADER_SIZE + nonce_size;
        ctx->tag_size = tag_size;
        ctx->overhead_size = ctx->prepend_size + ctx->tag_size;
        ctx->iv_size = iv_size;
-       ctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
-                         GFP_KERNEL);
+       ctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE, GFP_KERNEL);
        if (!ctx->iv) {
                rc = -ENOMEM;
-               goto out;
+               goto free_priv;
        }
        memcpy(ctx->iv, gcm_128_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
        memcpy(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
@@ -740,7 +739,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
 
        rc = crypto_aead_setauthsize(sw_ctx->aead_send, ctx->tag_size);
        if (!rc)
-               goto out;
+               return 0;
 
 free_aead:
        crypto_free_aead(sw_ctx->aead_send);
@@ -751,6 +750,9 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
 free_iv:
        kfree(ctx->iv);
        ctx->iv = NULL;
+free_priv:
+       kfree(ctx->priv_ctx);
+       ctx->priv_ctx = NULL;
 out:
        return rc;
 }
index fdde0d98fde16296daf841c2ac102fc20ca2cd5c..a6f3cac8c640e4cdb0eb4fb9d3c77bf3fd352576 100644 (file)
@@ -439,6 +439,8 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
                if (rv)
                        goto use_default_name;
        } else {
+               int rv;
+
 use_default_name:
                /* NOTE:  This is *probably* safe w/out holding rtnl because of
                 * the restrictions on phy names.  Probably this call could
@@ -446,7 +448,11 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
                 * phyX.  But, might should add some locking and check return
                 * value, and use a different name if this one exists?
                 */
-               dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
+               rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
+               if (rv < 0) {
+                       kfree(rdev);
+                       return NULL;
+               }
        }
 
        INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
index d2f7e8b8a097c00c0cf6da78f8a1e4d55600296b..eaff636169c220f7ca0218911cdbe4b711b150a0 100644 (file)
@@ -507,8 +507,6 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
                       struct wireless_dev *wdev);
 
-#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
-
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
 #define CFG80211_DEV_WARN_ON(cond)     WARN_ON(cond)
 #else
index 2b3dbcd40e46390debf84f4a127b23f185e76b39..542a4fc0a8d77cfecf82b95851c7e49609652472 100644 (file)
@@ -2618,12 +2618,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
                const u8 *ssid_ie;
                if (!wdev->current_bss)
                        break;
+               rcu_read_lock();
                ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
                                               WLAN_EID_SSID);
-               if (!ssid_ie)
-                       break;
-               if (nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
-                       goto nla_put_failure_locked;
+               if (ssid_ie &&
+                   nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
+                       goto nla_put_failure_rcu_locked;
+               rcu_read_unlock();
                break;
                }
        default:
@@ -2635,6 +2636,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
        genlmsg_end(msg, hdr);
        return 0;
 
+ nla_put_failure_rcu_locked:
+       rcu_read_unlock();
  nla_put_failure_locked:
        wdev_unlock(wdev);
  nla_put_failure:
@@ -9806,7 +9809,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
         */
        if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
            rdev->ops->get_station) {
-               struct station_info sinfo;
+               struct station_info sinfo = {};
                u8 *mac_addr;
 
                mac_addr = wdev->current_bss->pub.bssid;
index 78e71b0390be90bc16655d380fa6869391c52729..7b42f0bacfd843481adb1648c24a5f87c4395b1a 100644 (file)
@@ -1769,8 +1769,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
        if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
                return;
 
-       chan_before.center_freq = chan->center_freq;
-       chan_before.flags = chan->flags;
+       chan_before = *chan;
 
        if (chan->flags & IEEE80211_CHAN_NO_IR) {
                chan->flags &= ~IEEE80211_CHAN_NO_IR;
index 7ca04a7de85ae469348449c3f74ddedbec198e8c..05186a47878fe93b87807130b00d978d3a6d9bc5 100644 (file)
@@ -1254,8 +1254,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
-       /* we are under RTNL - globally locked - so can use a static struct */
-       static struct station_info sinfo;
+       struct station_info sinfo = {};
        u8 addr[ETH_ALEN];
        int err;
 
index 3f6f6f8c9fa5224e75c1b62f299f217da172d370..5b2409746ae0a14c491cc8dfd316facc5cd67347 100644 (file)
@@ -518,7 +518,7 @@ int xfrm_trans_queue(struct sk_buff *skb,
                return -ENOBUFS;
 
        XFRM_TRANS_SKB_CB(skb)->finish = finish;
-       skb_queue_tail(&trans->queue, skb);
+       __skb_queue_tail(&trans->queue, skb);
        tasklet_schedule(&trans->tasklet);
        return 0;
 }
index 70aa5cb0c659d54eacb85f92dc95b2db17bfe1d0..bd6b0e7a0ee41f246ea15c57353b1a8d86054f4c 100644 (file)
@@ -609,7 +609,8 @@ static void xfrm_hash_rebuild(struct work_struct *work)
 
        /* re-insert all policies by order of creation */
        list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
-               if (xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) {
+               if (policy->walk.dead ||
+                   xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) {
                        /* skip socket policies */
                        continue;
                }
@@ -974,8 +975,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
        }
        if (!cnt)
                err = -ESRCH;
-       else
-               xfrm_policy_cache_flush();
 out:
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
        return err;
@@ -1743,6 +1742,8 @@ void xfrm_policy_cache_flush(void)
        bool found = 0;
        int cpu;
 
+       might_sleep();
+
        local_bh_disable();
        rcu_read_lock();
        for_each_possible_cpu(cpu) {
@@ -2062,8 +2063,11 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
        if (num_xfrms <= 0)
                goto make_dummy_bundle;
 
+       local_bh_disable();
        xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family,
-                                                 xflo->dst_orig);
+                                             xflo->dst_orig);
+       local_bh_enable();
+
        if (IS_ERR(xdst)) {
                err = PTR_ERR(xdst);
                if (err != -EAGAIN)
@@ -2150,9 +2154,12 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
                                goto no_transform;
                        }
 
+                       local_bh_disable();
                        xdst = xfrm_resolve_and_create_bundle(
                                        pols, num_pols, fl,
                                        family, dst_orig);
+                       local_bh_enable();
+
                        if (IS_ERR(xdst)) {
                                xfrm_pols_put(pols, num_pols);
                                err = PTR_ERR(xdst);
index 500b3391f474b96fe273060ff8eae16f1e23f3c2..42995741263386852b61a6a72a23669f4d134b5b 100644 (file)
@@ -313,13 +313,14 @@ xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
        if ((type && !try_module_get(type->owner)))
                type = NULL;
 
+       rcu_read_unlock();
+
        if (!type && try_load) {
                request_module("xfrm-offload-%d-%d", family, proto);
                try_load = 0;
                goto retry;
        }
 
-       rcu_read_unlock();
        return type;
 }
 
@@ -1534,8 +1535,12 @@ int xfrm_state_update(struct xfrm_state *x)
        err = -EINVAL;
        spin_lock_bh(&x1->lock);
        if (likely(x1->km.state == XFRM_STATE_VALID)) {
-               if (x->encap && x1->encap)
+               if (x->encap && x1->encap &&
+                   x->encap->encap_type == x1->encap->encap_type)
                        memcpy(x1->encap, x->encap, sizeof(*x1->encap));
+               else if (x->encap || x1->encap)
+                       goto fail;
+
                if (x->coaddr && x1->coaddr) {
                        memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
                }
@@ -1552,6 +1557,8 @@ int xfrm_state_update(struct xfrm_state *x)
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
        }
+
+fail:
        spin_unlock_bh(&x1->lock);
 
        xfrm_state_put(x1);
index cb8997ed01497ccebdfded3aef8ccdd401fa8482..47cddf32aeba025f2741dbc7f48d596f4f6653fa 100644 (file)
@@ -265,12 +265,18 @@ else
 objtool_args += $(call cc-ifversion, -lt, 0405, --no-unreachable)
 endif
 
+ifdef CONFIG_MODVERSIONS
+objtool_o = $(@D)/.tmp_$(@F)
+else
+objtool_o = $(@)
+endif
+
 # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
 # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
 # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
 cmd_objtool = $(if $(patsubst y%,, \
        $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
-       $(__objtool_obj) $(objtool_args) "$(@)";)
+       $(__objtool_obj) $(objtool_args) "$(objtool_o)";)
 objtool_obj = $(if $(patsubst y%,, \
        $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
        $(__objtool_obj))
@@ -286,16 +292,16 @@ objtool_dep = $(objtool_obj)                                      \
 define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
        $(call cmd_and_fixdep,cc_o_c)                                     \
-       $(cmd_modversions_c)                                              \
        $(cmd_checkdoc)                                                   \
        $(call echo-cmd,objtool) $(cmd_objtool)                           \
+       $(cmd_modversions_c)                                              \
        $(call echo-cmd,record_mcount) $(cmd_record_mcount)
 endef
 
 define rule_as_o_S
        $(call cmd_and_fixdep,as_o_S)                                     \
-       $(cmd_modversions_S)                                              \
-       $(call echo-cmd,objtool) $(cmd_objtool)
+       $(call echo-cmd,objtool) $(cmd_objtool)                           \
+       $(cmd_modversions_S)
 endef
 
 # List module undefined symbols (or empty line if not enabled)
index 438120da1361002833a2014b1ca3fb02cc0aa539..5ea07109933043888b802c9252205c7da3b7705c 100755 (executable)
@@ -59,6 +59,14 @@ disas() {
                ${CROSS_COMPILE}strip $1.o
        fi
 
+       if [ "$ARCH" = "arm64" ]; then
+               if [ $width -eq 4 ]; then
+                       type=inst
+               fi
+
+               ${CROSS_COMPILE}strip $1.o
+       fi
+
        ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
                grep -v "/tmp\|Disassembly\|\.text\|^$" > $1.dis 2>&1
 }
index 1bf949c43b76cd5fb2647c556f8522cc7446e956..f6ab3ccf698ff4e4279e959829eb3e87da8cb2bc 100644 (file)
@@ -96,6 +96,8 @@ def get_thread_info(task):
         thread_info_addr = task.address + ia64_task_size
         thread_info = thread_info_addr.cast(thread_info_ptr_type)
     else:
+        if task.type.fields()[0].type == thread_info_type.get_type():
+            return task['thread_info']
         thread_info = task['stack'].cast(thread_info_ptr_type)
     return thread_info.dereference()
 
index db7894bb028ccc6ca941c45c4a7e37602ec1228d..faa67861cbc17e1ff7a9e409f76c717179d22370 100644 (file)
@@ -560,7 +560,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
 {
        u_int64_t n = (u_int64_t) a * b;
        if (c == 0) {
-               snd_BUG_ON(!n);
                *r = 0;
                return UINT_MAX;
        }
index 6e22eea72654e6ce2208500fa7329fc1c2aedf35..d0191340458114761a6c9969605f17585b51b610 100644 (file)
@@ -221,6 +221,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
        rwlock_init(&client->ports_lock);
        mutex_init(&client->ports_mutex);
        INIT_LIST_HEAD(&client->ports_list_head);
+       mutex_init(&client->ioctl_mutex);
 
        /* find free slot in the client table */
        spin_lock_irqsave(&clients_lock, flags);
@@ -2130,7 +2131,9 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
        }
 
+       mutex_lock(&client->ioctl_mutex);
        err = handler->func(client, &buf);
+       mutex_unlock(&client->ioctl_mutex);
        if (err >= 0) {
                /* Some commands includes a bug in 'dir' field. */
                if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT ||
index c6614254ef8af2f56b68193dc4ce4d35d49b3773..0611e1e0ed5ba01e053ac3a53c5f09ae681e02a2 100644 (file)
@@ -61,6 +61,7 @@ struct snd_seq_client {
        struct list_head ports_list_head;
        rwlock_t ports_lock;
        struct mutex ports_mutex;
+       struct mutex ioctl_mutex;
        int convert32;          /* convert 32->64bit */
 
        /* output pool */
index 80bbadc83721447754392238118eee98484616b6..d6e079f4ec09d29624a05d3a18413e55910f0cf6 100644 (file)
@@ -408,6 +408,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
        /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
 
        /* codec SSID */
+       SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122),
        SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
        SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
        SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
index 8fd2d9c62c96ce53a78dced9d0cd3529961978a9..9aafc6c861329d0c2cb4aeb45c11acb722662520 100644 (file)
@@ -6196,6 +6196,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
        SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
        SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
+       SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
index 24460155c82c9b2305a2484d037be9017a00becb..c1c338661699788c8189becaab8465ed1bdcd775 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "elf.h"
 #include "warn.h"
@@ -358,7 +359,8 @@ struct elf *elf_open(const char *name, int flags)
 
        elf->fd = open(name, flags);
        if (elf->fd == -1) {
-               perror("open");
+               fprintf(stderr, "objtool: Can't open '%s': %s\n",
+                       name, strerror(errno));
                goto err;
        }
 
index b51017404c62d0dc8198afdf035016f6e5e2fd0b..5ed4175c4ff87c4a31fd2c179861d00c164c89b7 100644 (file)
@@ -272,6 +272,46 @@ static struct bpf_test tests[] = {
                .errstr = "invalid bpf_ld_imm64 insn",
                .result = REJECT,
        },
+       {
+               "arsh32 on imm",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 5),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "BPF_ARSH not supported for 32 bit ALU",
+       },
+       {
+               "arsh32 on reg",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_MOV64_IMM(BPF_REG_1, 5),
+                       BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "BPF_ARSH not supported for 32 bit ALU",
+       },
+       {
+               "arsh64 on imm",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_ALU64_IMM(BPF_ARSH, BPF_REG_0, 5),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
+       {
+               "arsh64 on reg",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_MOV64_IMM(BPF_REG_1, 5),
+                       BPF_ALU64_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
        {
                "no bpf_exit",
                .insns = {
@@ -2552,6 +2592,29 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        },
+       {
+               "context stores via ST",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_1, offsetof(struct __sk_buff, mark), 0),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "BPF_ST stores into R1 context is not allowed",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
+       {
+               "context stores via XADD",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_1,
+                                    BPF_REG_0, offsetof(struct __sk_buff, mark), 0),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "BPF_XADD stores into R1 context is not allowed",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
        {
                "direct packet access: test1",
                .insns = {
@@ -4272,7 +4335,8 @@ static struct bpf_test tests[] = {
                .fixup_map1 = { 2 },
                .errstr_unpriv = "R2 leaks addr into mem",
                .result_unpriv = REJECT,
-               .result = ACCEPT,
+               .result = REJECT,
+               .errstr = "BPF_XADD stores into R1 context is not allowed",
        },
        {
                "leak pointer into ctx 2",
@@ -4286,7 +4350,8 @@ static struct bpf_test tests[] = {
                },
                .errstr_unpriv = "R10 leaks addr into mem",
                .result_unpriv = REJECT,
-               .result = ACCEPT,
+               .result = REJECT,
+               .errstr = "BPF_XADD stores into R1 context is not allowed",
        },
        {
                "leak pointer into ctx 3",
@@ -6667,7 +6732,7 @@ static struct bpf_test tests[] = {
                        BPF_JMP_IMM(BPF_JA, 0, 0, -7),
                },
                .fixup_map1 = { 4 },
-               .errstr = "unbounded min value",
+               .errstr = "R0 invalid mem access 'inv'",
                .result = REJECT,
        },
        {
@@ -8568,6 +8633,127 @@ static struct bpf_test tests[] = {
                .prog_type = BPF_PROG_TYPE_XDP,
                .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
        },
+       {
+               "check deducing bounds from const, 1",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 1, 0),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R0 tried to subtract pointer from scalar",
+       },
+       {
+               "check deducing bounds from const, 2",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 1, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_JMP_IMM(BPF_JSLE, BPF_REG_0, 1, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
+       {
+               "check deducing bounds from const, 3",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSLE, BPF_REG_0, 0, 0),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R0 tried to subtract pointer from scalar",
+       },
+       {
+               "check deducing bounds from const, 4",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSLE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
+       {
+               "check deducing bounds from const, 5",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 1),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R0 tried to subtract pointer from scalar",
+       },
+       {
+               "check deducing bounds from const, 6",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R0 tried to subtract pointer from scalar",
+       },
+       {
+               "check deducing bounds from const, 7",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, ~0),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 0),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+                                   offsetof(struct __sk_buff, mark)),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "dereference of modified ctx ptr",
+       },
+       {
+               "check deducing bounds from const, 8",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, ~0),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 1),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+                                   offsetof(struct __sk_buff, mark)),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "dereference of modified ctx ptr",
+       },
+       {
+               "check deducing bounds from const, 9",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 0),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R0 tried to subtract pointer from scalar",
+       },
+       {
+               "check deducing bounds from const, 10",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSLE, BPF_REG_0, 0, 0),
+                       /* Marks reg as unknown. */
+                       BPF_ALU64_IMM(BPF_NEG, BPF_REG_0, 0),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "math between ctx pointer and register with unbounded min value is not allowed",
+       },
        {
                "bpf_exit with invalid return code. test1",
                .insns = {