Merge tag 'block-5.8-2020-06-19' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 19 Jun 2020 20:11:26 +0000 (13:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 19 Jun 2020 20:11:26 +0000 (13:11 -0700)
Pull block fixes from Jens Axboe:

 - Use import_uuid() where appropriate (Andy)

 - bcache fixes (Coly, Mauricio, Zhiqiang)

 - blktrace sparse warnings fix (Jan)

 - blktrace concurrent setup fix (Luis)

 - blkdev_get use-after-free fix (Jason)

 - Ensure all blk-mq maps are updated (Weiping)

 - Loop invalidate bdev fix (Zheng)

* tag 'block-5.8-2020-06-19' of git://git.kernel.dk/linux-block:
  block: make function 'kill_bdev' static
  loop: replace kill_bdev with invalidate_bdev
  partitions/ldm: Replace uuid_copy() with import_uuid() where it makes sense
  block: update hctx map when use multiple maps
  blktrace: Avoid sparse warnings when assigning q->blk_trace
  blktrace: break out of blktrace setup on concurrent calls
  block: Fix use-after-free in blkdev_get()
  trace/events/block.h: drop kernel-doc for dropped function parameter
  blk-mq: Remove redundant 'return' statement
  bcache: pr_info() format clean up in bcache_device_init()
  bcache: use delayed kworker fo asynchronous devices registration
  bcache: check and adjust logical block size for backing devices
  bcache: fix potential deadlock problem in btree_gc_coalesce

265 files changed:
Documentation/arm64/sve.rst
Documentation/filesystems/dax.txt
Documentation/filesystems/ext4/verity.rst
Documentation/gpu/amdgpu.rst
Documentation/sh/index.rst
MAINTAINERS
arch/arm/kernel/ftrace.c
arch/arm/kernel/kgdb.c
arch/arm/kernel/traps.c
arch/arm/mm/alignment.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/Makefile
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/insn.c
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/traps.c
arch/arm64/mm/init.c
arch/arm64/mm/mmu.c
arch/csky/kernel/ftrace.c
arch/ia64/include/asm/sections.h
arch/ia64/kernel/ftrace.c
arch/ia64/kernel/unwind_i.h
arch/mips/kernel/kprobes.c
arch/nds32/kernel/ftrace.c
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/kgdb.c
arch/parisc/kernel/process.c
arch/parisc/lib/memcpy.c
arch/powerpc/include/asm/sections.h
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/kvm/book3s_64_mmu_radix.c
arch/powerpc/lib/inst.c
arch/powerpc/oprofile/backtrace.c
arch/powerpc/perf/callchain_32.c
arch/powerpc/perf/callchain_64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/sysdev/fsl_pci.c
arch/riscv/kernel/ftrace.c
arch/riscv/kernel/kgdb.c
arch/riscv/kernel/patch.c
arch/riscv/kernel/traps.c
arch/s390/kernel/ftrace.c
arch/s390/mm/fault.c
arch/sh/kernel/ftrace.c
arch/sh/kernel/traps.c
arch/um/kernel/maccess.c
arch/x86/include/asm/ptrace.h
arch/x86/kernel/dumpstack.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/probe_roms.c
arch/x86/kernel/traps.c
arch/x86/mm/fault.c
arch/x86/mm/init_32.c
arch/x86/mm/maccess.c
arch/x86/pci/pcbios.c
arch/x86/purgatory/Makefile
arch/x86/xen/enlighten_pv.c
block/partitions/ldm.h
drivers/amba/tegra-ahb.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/sata_rcar.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_protocol.h
drivers/block/rbd.c
drivers/char/mem.c
drivers/crypto/chelsio/chcr_crypto.h
drivers/dio/dio.c
drivers/dma/milbeaut-hdmac.c
drivers/dma/milbeaut-xdmac.c
drivers/dma/moxart-dma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/ti/edma.c
drivers/dma/ti/k3-udma.c
drivers/dma/timb_dma.c
drivers/firewire/core-cdev.c
drivers/firewire/core-transaction.c
drivers/firewire/core.h
drivers/firewire/nosy.c
drivers/firewire/ohci.c
drivers/firmware/dmi-sysfs.c
drivers/firmware/google/memconsole-coreboot.c
drivers/firmware/google/vpd.c
drivers/firmware/iscsi_ibft.c
drivers/firmware/pcdp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/display/dc/dsc/Makefile
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/selftest_hangcheck.c
drivers/gpu/drm/i915/gt/selftest_lrc.c
drivers/gpu/drm/i915/gt/selftest_mocs.c
drivers/gpu/drm/i915/gt/selftest_ring.c [new file with mode: 0644]
drivers/gpu/drm/i915/gt/selftest_rps.c
drivers/gpu/drm/i915/gt/selftest_timeline.c
drivers/gpu/drm/i915/gt/selftest_workarounds.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_priolist_types.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
drivers/hwtracing/stm/policy.c
drivers/hwtracing/stm/stm.h
drivers/input/serio/hp_sdc.c
drivers/media/usb/pwc/pwc.h
drivers/mfd/mt6360-core.c
drivers/misc/kgdbts.c
drivers/net/bareudp.c
drivers/net/can/peak_canfd/peak_pciefd_main.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/mediatek/mtk_star_emac.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/xilinx/xilinx_axienet.h
drivers/oprofile/cpu_buffer.h
drivers/phy/samsung/phy-samsung-usb2.h
drivers/rapidio/rio-scan.c
drivers/soc/ti/knav_qmss.h
drivers/video/fbdev/hpfb.c
drivers/w1/w1_netlink.h
fs/afs/dir.c
fs/afs/dir_silly.c
fs/afs/file.c
fs/afs/flock.c
fs/afs/fs_operation.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/misc.c
fs/afs/write.c
fs/afs/yfsclient.c
fs/aio.c
fs/ext4/Makefile
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/ext4/verity.c
fs/ext4/xattr.c
fs/ext4/xattr.h
fs/ext4/xattr_hurd.c [new file with mode: 0644]
fs/jbd2/journal.c
fs/jffs2/nodelist.h
fs/jffs2/summary.h
fs/proc/kcore.c
fs/squashfs/squashfs_fs.h
include/drm/drm_displayid.h
include/keys/encrypted-type.h
include/keys/rxrpc-type.h
include/linux/can/skb.h
include/linux/cb710.h
include/linux/ceph/libceph.h
include/linux/compiler_types.h
include/linux/dmaengine.h
include/linux/fscache-cache.h
include/linux/jbd2.h
include/linux/kexec.h
include/linux/kprobes.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/overflow.h
include/linux/sctp.h
include/linux/tifm.h
include/linux/uaccess.h
include/net/netfilter/nf_flow_table.h
include/net/tc_act/tc_ct.h
include/uapi/linux/fs.h
include/uapi/linux/xattr.h
kernel/debug/debug_core.c
kernel/debug/gdbstub.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_support.c
kernel/dma/Kconfig
kernel/dma/pool.c
kernel/kthread.c
kernel/trace/bpf_trace.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.h
kernel/workqueue.c
lib/test_lockup.c
lib/test_objagg.c
mm/debug.c
mm/maccess.c
mm/rodata_test.c
mm/slub.c
net/ceph/ceph_common.c
net/ceph/osd_client.c
net/ipv4/tcp_input.c
net/ipv6/mcast.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/rds/ib.h
net/sched/act_ct.c
samples/mei/mei-amt-version.c
scripts/decode_stacktrace.sh
security/integrity/integrity.h
sound/soc/sof/probe.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/unistd.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fcntl.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/stat.h
tools/include/uapi/linux/vhost.h
tools/lib/traceevent/event-parse.c
tools/perf/Makefile.config
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/trace/beauty/statx.c
tools/perf/util/bpf-prologue.c
tools/perf/util/parse-events.y
tools/perf/util/pmu.h
tools/perf/util/probe-event.c
tools/perf/util/probe-file.c
tools/perf/util/stat-display.c
tools/testing/nvdimm/test/nfit_test.h

index 5689c74..bfd55f4 100644 (file)
@@ -186,7 +186,7 @@ prctl(PR_SVE_SET_VL, unsigned long arg)
 
     flags:
 
-       PR_SVE_SET_VL_INHERIT
+       PR_SVE_VL_INHERIT
 
            Inherit the current vector length across execve().  Otherwise, the
            vector length is reset to the system default at execve().  (See
@@ -247,7 +247,7 @@ prctl(PR_SVE_GET_VL)
 
     The following flag may be OR-ed into the result:
 
-       PR_SVE_SET_VL_INHERIT
+       PR_SVE_VL_INHERIT
 
            Vector length will be inherited across execve().
 
@@ -393,7 +393,7 @@ The regset data starts with struct user_sve_header, containing:
 * At every execve() call, the new vector length of the new process is set to
   the system default vector length, unless
 
-    * PR_SVE_SET_VL_INHERIT (or equivalently SVE_PT_VL_INHERIT) is set for the
+    * PR_SVE_VL_INHERIT (or equivalently SVE_PT_VL_INHERIT) is set for the
       calling thread, or
 
     * a deferred vector length change is pending, established via the
index 8e26707..8fdb78f 100644 (file)
@@ -25,7 +25,7 @@ size when creating the filesystem.
 Currently 3 filesystems support DAX: ext2, ext4 and xfs.  Enabling DAX on them
 is different.
 
-Enabling DAX on ext4 and ext2
+Enabling DAX on ext2
 -----------------------------
 
 When mounting the filesystem, use the "-o dax" option on the command line or
@@ -33,8 +33,8 @@ add 'dax' to the options in /etc/fstab.  This works to enable DAX on all files
 within the filesystem.  It is equivalent to the '-o dax=always' behavior below.
 
 
-Enabling DAX on xfs
--------------------
+Enabling DAX on xfs and ext4
+----------------------------
 
 Summary
 -------
index 3e4c0ee..e99ff3f 100644 (file)
@@ -39,3 +39,6 @@ is encrypted as well as the data itself.
 
 Verity files cannot have blocks allocated past the end of the verity
 metadata.
+
+Verity and DAX are not compatible and attempts to set both of these flags
+on a file will fail.
index 4cc7432..1711235 100644 (file)
@@ -197,11 +197,14 @@ pp_power_profile_mode
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
    :doc: pp_power_profile_mode
 
-busy_percent
-~~~~~~~~~~~~
+*_busy_percent
+~~~~~~~~~~~~~~
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-   :doc: busy_percent
+   :doc: gpu_busy_percent
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+   :doc: mem_busy_percent
 
 GPU Product Information
 =======================
index bc8db7b..0bd405a 100644 (file)
@@ -16,18 +16,6 @@ Store Queue API
 .. kernel-doc:: arch/sh/kernel/cpu/sh4/sq.c
    :export:
 
-SH-5
-----
-
-TLB Interfaces
-~~~~~~~~~~~~~~
-
-.. kernel-doc:: arch/sh/mm/tlb-sh5.c
-   :internal:
-
-.. kernel-doc:: arch/sh/include/asm/tlb_64.h
-   :internal:
-
 Machine Specific Interfaces
 ===========================
 
index 68f21d4..301330e 100644 (file)
@@ -11369,14 +11369,6 @@ L:     dmaengine@vger.kernel.org
 S:     Supported
 F:     drivers/dma/at_xdmac.c
 
-MICROSEMI ETHERNET SWITCH DRIVER
-M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
-M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
-L:     netdev@vger.kernel.org
-S:     Supported
-F:     drivers/net/ethernet/mscc/
-F:     include/soc/mscc/ocelot*
-
 MICROSEMI MIPS SOCS
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
 M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
@@ -12335,6 +12327,18 @@ M:     Peter Zijlstra <peterz@infradead.org>
 S:     Supported
 F:     tools/objtool/
 
+OCELOT ETHERNET SWITCH DRIVER
+M:     Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
+M:     Vladimir Oltean <vladimir.oltean@nxp.com>
+M:     Claudiu Manoil <claudiu.manoil@nxp.com>
+M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/dsa/ocelot/*
+F:     drivers/net/ethernet/mscc/
+F:     include/soc/mscc/ocelot*
+F:     net/dsa/tag_ocelot.c
+
 OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
 M:     Frederic Barrat <fbarrat@linux.ibm.com>
 M:     Andrew Donnellan <ajd@linux.ibm.com>
@@ -14534,7 +14538,7 @@ F:      Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt
 F:     drivers/i2c/busses/i2c-emev2.c
 
 RENESAS ETHERNET DRIVERS
-R:     Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+R:     Sergei Shtylyov <sergei.shtylyov@gmail.com>
 L:     netdev@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
 F:     Documentation/devicetree/bindings/net/renesas,*.txt
@@ -18254,14 +18258,6 @@ S:     Maintained
 F:     drivers/input/serio/userio.c
 F:     include/uapi/linux/userio.h
 
-VITESSE FELIX ETHERNET SWITCH DRIVER
-M:     Vladimir Oltean <vladimir.oltean@nxp.com>
-M:     Claudiu Manoil <claudiu.manoil@nxp.com>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/dsa/ocelot/*
-F:     net/dsa/tag_ocelot.c
-
 VIVID VIRTUAL VIDEO DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
index 10499d4..9a79ef6 100644 (file)
@@ -84,7 +84,8 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
                old = __opcode_to_mem_arm(old);
 
        if (validate) {
-               if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+               if (copy_from_kernel_nofault(&replaced, (void *)pc,
+                               MCOUNT_INSN_SIZE))
                        return -EFAULT;
 
                if (replaced != old)
index 6a95b92..7bd30c0 100644 (file)
@@ -236,7 +236,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        /* patch_text() only supports int-sized breakpoints */
        BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE);
 
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
index 65a3b1e..17d5a78 100644 (file)
@@ -396,7 +396,7 @@ int is_valid_bugaddr(unsigned long pc)
        u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
 #endif
 
-       if (probe_kernel_address((unsigned *)pc, bkpt))
+       if (get_kernel_nofault(bkpt, (void *)pc))
                return 0;
 
        return bkpt == insn;
index 84718ed..81a627e 100644 (file)
@@ -774,7 +774,7 @@ static int alignment_get_arm(struct pt_regs *regs, u32 *ip, u32 *inst)
        if (user_mode(regs))
                fault = get_user(instr, ip);
        else
-               fault = probe_kernel_address(ip, instr);
+               fault = get_kernel_nofault(instr, ip);
 
        *inst = __mem_to_opcode_arm(instr);
 
@@ -789,7 +789,7 @@ static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst)
        if (user_mode(regs))
                fault = get_user(instr, ip);
        else
-               fault = probe_kernel_address(ip, instr);
+               fault = get_kernel_nofault(instr, ip);
 
        *inst = __mem_to_opcode_thumb16(instr);
 
index 31380da..4ae2419 100644 (file)
@@ -1630,6 +1630,8 @@ config ARM64_BTI_KERNEL
        depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
        depends on !CC_IS_GCC || GCC_VERSION >= 100100
+       # https://reviews.llvm.org/rGb8ae3fdfa579dbf366b1bb1cbfdbf8c51db7fa55
+       depends on !CC_IS_CLANG || CLANG_VERSION >= 100001
        depends on !(CC_IS_CLANG && GCOV_KERNEL)
        depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
        help
index cdf7ec0..265c446 100644 (file)
@@ -8,21 +8,6 @@ config PID_IN_CONTEXTIDR
          instructions during context switch. Say Y here only if you are
          planning to use hardware trace tools with this kernel.
 
-config ARM64_RANDOMIZE_TEXT_OFFSET
-       bool "Randomize TEXT_OFFSET at build time"
-       help
-         Say Y here if you want the image load offset (AKA TEXT_OFFSET)
-         of the kernel to be randomized at build-time. When selected,
-         this option will cause TEXT_OFFSET to be randomized upon any
-         build of the kernel, and the offset will be reflected in the
-         text_offset field of the resulting Image. This can be used to
-         fuzz-test bootloaders which respect text_offset.
-
-         This option is intended for bootloader and/or kernel testing
-         only. Bootloaders must make no assumptions regarding the value
-         of TEXT_OFFSET and platforms must not require a specific
-         value.
-
 config DEBUG_EFI
        depends on EFI && DEBUG_INFO
        bool "UEFI debugging"
index 76359cf..a0d94d0 100644 (file)
@@ -121,13 +121,7 @@ endif
 head-y         := arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
-ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
-TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
-                int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
-                rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
-else
 TEXT_OFFSET := 0x0
-endif
 
 ifeq ($(CONFIG_KASAN_SW_TAGS), y)
 KASAN_SHADOW_SCALE_SHIFT := 4
index 6dbd267..758e2d1 100644 (file)
@@ -416,7 +416,7 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
        __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
 
 #define pgprot_nx(prot) \
-       __pgprot_modify(prot, 0, PTE_PXN)
+       __pgprot_modify(prot, PTE_MAYBE_GP, PTE_PXN)
 
 /*
  * Mark the prot value as uncacheable and unbufferable.
index 35cb5e6..55c8f3e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/bug.h>
 #include <linux/cache.h>
 #include <linux/compat.h>
+#include <linux/compiler.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -119,10 +120,20 @@ struct fpsimd_last_state_struct {
 static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
 
 /* Default VL for tasks that don't set it explicitly: */
-static int sve_default_vl = -1;
+static int __sve_default_vl = -1;
+
+static int get_sve_default_vl(void)
+{
+       return READ_ONCE(__sve_default_vl);
+}
 
 #ifdef CONFIG_ARM64_SVE
 
+static void set_sve_default_vl(int val)
+{
+       WRITE_ONCE(__sve_default_vl, val);
+}
+
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
 int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
@@ -338,13 +349,13 @@ static unsigned int find_supported_vector_length(unsigned int vl)
        return sve_vl_from_vq(__bit_to_vq(bit));
 }
 
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL)
 
 static int sve_proc_do_default_vl(struct ctl_table *table, int write,
                                  void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret;
-       int vl = sve_default_vl;
+       int vl = get_sve_default_vl();
        struct ctl_table tmp_table = {
                .data = &vl,
                .maxlen = sizeof(vl),
@@ -361,7 +372,7 @@ static int sve_proc_do_default_vl(struct ctl_table *table, int write,
        if (!sve_vl_valid(vl))
                return -EINVAL;
 
-       sve_default_vl = find_supported_vector_length(vl);
+       set_sve_default_vl(find_supported_vector_length(vl));
        return 0;
 }
 
@@ -383,9 +394,9 @@ static int __init sve_sysctl_init(void)
        return 0;
 }
 
-#else /* ! CONFIG_SYSCTL */
+#else /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 static int __init sve_sysctl_init(void) { return 0; }
-#endif /* ! CONFIG_SYSCTL */
+#endif /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 
 #define ZREG(sve_state, vq, n) ((char *)(sve_state) +          \
        (SVE_SIG_ZREG_OFFSET(vq, n) - SVE_SIG_REGS_OFFSET))
@@ -868,7 +879,7 @@ void __init sve_setup(void)
         * For the default VL, pick the maximum supported value <= 64.
         * VL == 64 is guaranteed not to grow the signal frame.
         */
-       sve_default_vl = find_supported_vector_length(64);
+       set_sve_default_vl(find_supported_vector_length(64));
 
        bitmap_andnot(tmp_map, sve_vq_partial_map, sve_vq_map,
                      SVE_VQ_MAX);
@@ -889,7 +900,7 @@ void __init sve_setup(void)
        pr_info("SVE: maximum available vector length %u bytes per vector\n",
                sve_max_vl);
        pr_info("SVE: default vector length %u bytes per vector\n",
-               sve_default_vl);
+               get_sve_default_vl());
 
        /* KVM decides whether to support mismatched systems. Just warn here: */
        if (sve_max_virtualisable_vl < sve_max_vl)
@@ -1029,13 +1040,13 @@ void fpsimd_flush_thread(void)
                 * vector length configured: no kernel task can become a user
                 * task without an exec and hence a call to this function.
                 * By the time the first call to this function is made, all
-                * early hardware probing is complete, so sve_default_vl
+                * early hardware probing is complete, so __sve_default_vl
                 * should be valid.
                 * If a bug causes this to go wrong, we make some noise and
                 * try to fudge thread.sve_vl to a safe value here.
                 */
                vl = current->thread.sve_vl_onexec ?
-                       current->thread.sve_vl_onexec : sve_default_vl;
+                       current->thread.sve_vl_onexec : get_sve_default_vl();
 
                if (WARN_ON(!sve_vl_valid(vl)))
                        vl = SVE_VL_MIN;
index 0b727ed..af234a1 100644 (file)
@@ -730,6 +730,27 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
                return 0;
 }
 
+static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+                            struct pt_regs *regs)
+{
+       int step = is_default_overflow_handler(wp);
+       struct arch_hw_breakpoint *info = counter_arch_bp(wp);
+
+       info->trigger = addr;
+
+       /*
+        * If we triggered a user watchpoint from a uaccess routine, then
+        * handle the stepping ourselves since userspace really can't help
+        * us with this.
+        */
+       if (!user_mode(regs) && info->ctrl.privilege == AARCH64_BREAKPOINT_EL0)
+               step = 1;
+       else
+               perf_bp_event(wp, regs);
+
+       return step;
+}
+
 static int watchpoint_handler(unsigned long addr, unsigned int esr,
                              struct pt_regs *regs)
 {
@@ -739,7 +760,6 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
        u64 val;
        struct perf_event *wp, **slots;
        struct debug_info *debug_info;
-       struct arch_hw_breakpoint *info;
        struct arch_hw_breakpoint_ctrl ctrl;
 
        slots = this_cpu_ptr(wp_on_reg);
@@ -777,25 +797,13 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
                if (dist != 0)
                        continue;
 
-               info = counter_arch_bp(wp);
-               info->trigger = addr;
-               perf_bp_event(wp, regs);
-
-               /* Do we need to handle the stepping? */
-               if (is_default_overflow_handler(wp))
-                       step = 1;
+               step = watchpoint_report(wp, addr, regs);
        }
-       if (min_dist > 0 && min_dist != -1) {
-               /* No exact match found. */
-               wp = slots[closest_match];
-               info = counter_arch_bp(wp);
-               info->trigger = addr;
-               perf_bp_event(wp, regs);
 
-               /* Do we need to handle the stepping? */
-               if (is_default_overflow_handler(wp))
-                       step = 1;
-       }
+       /* No exact match found? */
+       if (min_dist > 0 && min_dist != -1)
+               step = watchpoint_report(slots[closest_match], addr, regs);
+
        rcu_read_unlock();
 
        if (!step)
index 684d871..a107375 100644 (file)
@@ -135,7 +135,7 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
        int ret;
        __le32 val;
 
-       ret = probe_kernel_read(&val, addr, AARCH64_INSN_SIZE);
+       ret = copy_from_kernel_nofault(&val, addr, AARCH64_INSN_SIZE);
        if (!ret)
                *insnp = le32_to_cpu(val);
 
@@ -151,7 +151,7 @@ static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
        raw_spin_lock_irqsave(&patch_lock, flags);
        waddr = patch_map(addr, FIX_TEXT_POKE0);
 
-       ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);
+       ret = copy_to_kernel_nofault(waddr, &insn, AARCH64_INSN_SIZE);
 
        patch_unmap(FIX_TEXT_POKE0);
        raw_spin_unlock_irqrestore(&patch_lock, flags);
index 522e6f5..361a114 100644 (file)
@@ -219,8 +219,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
                                        MEMBLOCK_NONE, &start, &end, NULL)
                nr_ranges++;
 
-       cmem = kmalloc(sizeof(struct crash_mem) +
-                       sizeof(struct crash_mem_range) * nr_ranges, GFP_KERNEL);
+       cmem = kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL);
        if (!cmem)
                return -ENOMEM;
 
index 50cc30a..47f651d 100644 (file)
@@ -376,7 +376,7 @@ static int call_undef_hook(struct pt_regs *regs)
 
        if (!user_mode(regs)) {
                __le32 instr_le;
-               if (probe_kernel_address((__force __le32 *)pc, instr_le))
+               if (get_kernel_nofault(instr_le, (__force __le32 *)pc))
                        goto exit;
                instr = le32_to_cpu(instr_le);
        } else if (compat_thumb_mode(regs)) {
@@ -813,6 +813,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
                handler[reason], smp_processor_id(), esr,
                esr_get_class_string(esr));
 
+       __show_regs(regs);
        local_daif_mask();
        panic("bad mode");
 }
index e631e64..1e93cfc 100644 (file)
@@ -404,11 +404,6 @@ void __init arm64_memblock_init(void)
        high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
 
        dma_contiguous_reserve(arm64_dma32_phys_limit);
-
-#ifdef CONFIG_ARM64_4K_PAGES
-       hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
-#endif
-
 }
 
 void __init bootmem_init(void)
@@ -424,6 +419,16 @@ void __init bootmem_init(void)
        min_low_pfn = min;
 
        arm64_numa_init();
+
+       /*
+        * must be done after arm64_numa_init() which calls numa_init() to
+        * initialize node_online_map that gets used in hugetlb_cma_reserve()
+        * while allocating required CMA size across online nodes.
+        */
+#ifdef CONFIG_ARM64_4K_PAGES
+       hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
+#endif
+
        /*
         * Sparsemem tries to allocate bootmem in memory_present(), so must be
         * done after the fixed reservations.
index 990929c..1df25f2 100644 (file)
@@ -723,6 +723,7 @@ int kern_addr_valid(unsigned long addr)
        pmd_t *pmdp, pmd;
        pte_t *ptep, pte;
 
+       addr = arch_kasan_reset_tag(addr);
        if ((((long)addr) >> VA_BITS) != -1UL)
                return 0;
 
index 3c425b8..b4a7ec1 100644 (file)
@@ -72,7 +72,8 @@ static int ftrace_check_current_nop(unsigned long hook)
        uint16_t olds[7];
        unsigned long hook_pos = hook - 2;
 
-       if (probe_kernel_read((void *)olds, (void *)hook_pos, sizeof(nops)))
+       if (copy_from_kernel_nofault((void *)olds, (void *)hook_pos,
+                       sizeof(nops)))
                return -EFAULT;
 
        if (memcmp((void *)nops, (void *)olds, sizeof(nops))) {
@@ -97,7 +98,7 @@ static int ftrace_modify_code(unsigned long hook, unsigned long target,
 
        make_jbsr(target, hook, call, nolr);
 
-       ret = probe_kernel_write((void *)hook_pos, enable ? call : nops,
+       ret = copy_to_kernel_nofault((void *)hook_pos, enable ? call : nops,
                                 sizeof(nops));
        if (ret)
                return -EPERM;
index cea15f2..3a033d2 100644 (file)
@@ -35,7 +35,7 @@ static inline void *dereference_function_descriptor(void *ptr)
        struct fdesc *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->ip, p))
+       if (!get_kernel_nofault(p, (void *)&desc->ip))
                ptr = p;
        return ptr;
 }
index cee411e..b2ab2d5 100644 (file)
@@ -108,7 +108,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
                goto skip_check;
 
        /* read the text we want to modify */
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure it is what we expect it to be */
@@ -117,7 +117,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
 
 skip_check:
        /* replace the text with the new text */
-       if (probe_kernel_write(((void *)ip), new_code, MCOUNT_INSN_SIZE))
+       if (copy_to_kernel_nofault(((void *)ip), new_code, MCOUNT_INSN_SIZE))
                return -EPERM;
        flush_icache_range(ip, ip + MCOUNT_INSN_SIZE);
 
@@ -129,7 +129,7 @@ static int ftrace_make_nop_check(struct dyn_ftrace *rec, unsigned long addr)
        unsigned char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE];
        unsigned long ip = rec->ip;
 
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
        if (rec->flags & FTRACE_FL_CONVERTED) {
                struct ftrace_call_insn *call_insn, *tmp_call;
index 67994a7..1dd57ba 100644 (file)
@@ -42,7 +42,7 @@ enum unw_register_index {
 
 struct unw_info_block {
        u64 header;
-       u64 desc[0];            /* unwind descriptors */
+       u64 desc[];             /* unwind descriptors */
        /* personality routine and language-specific data follow behind descriptors */
 };
 
index 6cfae24..d043c2f 100644 (file)
@@ -86,9 +86,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
                goto out;
        }
 
-       if ((probe_kernel_read(&prev_insn, p->addr - 1,
-                               sizeof(mips_instruction)) == 0) &&
-                               insn_has_delayslot(prev_insn)) {
+       if (copy_from_kernel_nofault(&prev_insn, p->addr - 1,
+                       sizeof(mips_instruction)) == 0 &&
+           insn_has_delayslot(prev_insn)) {
                pr_notice("Kprobes for branch delayslot are not supported\n");
                ret = -EINVAL;
                goto out;
index 22ab77e..3763b3f 100644 (file)
@@ -131,13 +131,14 @@ static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
        unsigned long orig_insn[3];
 
        if (validate) {
-               if (probe_kernel_read(orig_insn, (void *)pc, MCOUNT_INSN_SIZE))
+               if (copy_from_kernel_nofault(orig_insn, (void *)pc,
+                               MCOUNT_INSN_SIZE))
                        return -EFAULT;
                if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
                        return -EINVAL;
        }
 
-       if (probe_kernel_write((void *)pc, new_insn, MCOUNT_INSN_SIZE))
+       if (copy_to_kernel_nofault((void *)pc, new_insn, MCOUNT_INSN_SIZE))
                return -EPERM;
 
        return 0;
index b836fc6..1df0f67 100644 (file)
@@ -172,7 +172,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        ip = (void *)(rec->ip + 4 - size);
 
-       ret = probe_kernel_read(insn, ip, size);
+       ret = copy_from_kernel_nofault(insn, ip, size);
        if (ret)
                return ret;
 
index 664278d..c4554ac 100644 (file)
@@ -154,8 +154,8 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
-       int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
-                               BREAK_INSTR_SIZE);
+       int ret = copy_from_kernel_nofault(bpt->saved_instr,
+                       (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
        if (ret)
                return ret;
 
index 230a642..b7abb12 100644 (file)
@@ -293,7 +293,7 @@ void *dereference_function_descriptor(void *ptr)
        Elf64_Fdesc *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->addr, p))
+       if (!get_kernel_nofault(p, (void *)&desc->addr))
                ptr = p;
        return ptr;
 }
index 94a9fe2..4b75388 100644 (file)
@@ -57,7 +57,7 @@ void * memcpy(void * dst,const void *src, size_t count)
 EXPORT_SYMBOL(raw_copy_in_user);
 EXPORT_SYMBOL(memcpy);
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        if ((unsigned long)unsafe_src < PAGE_SIZE)
                return false;
index d198717..324d7b2 100644 (file)
@@ -85,7 +85,7 @@ static inline void *dereference_function_descriptor(void *ptr)
        struct ppc64_opd_entry *desc = ptr;
        void *p;
 
-       if (!probe_kernel_address(&desc->funcaddr, p))
+       if (!get_kernel_nofault(p, (void *)&desc->funcaddr))
                ptr = p;
        return ptr;
 }
index 652b285..4090802 100644 (file)
@@ -421,7 +421,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        unsigned int instr;
        struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;
 
-       err = probe_kernel_address(addr, instr);
+       err = get_kernel_nofault(instr, (unsigned *) addr);
        if (err)
                return err;
 
index 6f96f65..9cc792a 100644 (file)
@@ -289,7 +289,7 @@ int kprobe_handler(struct pt_regs *regs)
        if (!p) {
                unsigned int instr;
 
-               if (probe_kernel_address(addr, instr))
+               if (get_kernel_nofault(instr, addr))
                        goto no_kprobe;
 
                if (instr != BREAKPOINT_INSTRUCTION) {
index f4c2fa1..ae2b188 100644 (file)
@@ -756,7 +756,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
 
        stub = (struct ppc64_stub_entry *)addr;
 
-       if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
+       if (copy_from_kernel_nofault(&magic, &stub->magic,
+                       sizeof(magic))) {
                pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
                return -EFAULT;
        }
@@ -766,7 +767,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
                return -EFAULT;
        }
 
-       if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
+       if (copy_from_kernel_nofault(&funcdata, &stub->funcdata,
+                       sizeof(funcdata))) {
                pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
                 return -EFAULT;
        }
index 7bb7faf..30955a0 100644 (file)
@@ -1271,7 +1271,7 @@ static void show_instructions(struct pt_regs *regs)
 #endif
 
                if (!__kernel_text_address(pc) ||
-                   probe_kernel_address((const void *)pc, instr)) {
+                   get_kernel_nofault(instr, (const void *)pc)) {
                        pr_cont("XXXXXXXX ");
                } else {
                        if (regs->nip == pc)
@@ -1305,7 +1305,8 @@ void show_user_instructions(struct pt_regs *regs)
                for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) {
                        int instr;
 
-                       if (probe_user_read(&instr, (void __user *)pc, sizeof(instr))) {
+                       if (copy_from_user_nofault(&instr, (void __user *)pc,
+                                       sizeof(instr))) {
                                seq_buf_printf(&s, "XXXXXXXX ");
                                continue;
                        }
index 5e39962..c1fede6 100644 (file)
@@ -226,7 +226,7 @@ __ftrace_make_nop(struct module *mod,
        unsigned long ip = rec->ip;
        unsigned long tramp;
 
-       if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure that that this is still a 24bit jump */
@@ -249,7 +249,7 @@ __ftrace_make_nop(struct module *mod,
        pr_devel("ip:%lx jumps to %lx", ip, tramp);
 
        /* Find where the trampoline jumps to */
-       if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
+       if (copy_from_kernel_nofault(jmp, (void *)tramp, sizeof(jmp))) {
                pr_err("Failed to read %lx\n", tramp);
                return -EFAULT;
        }
index 3cb0c98..e738ea6 100644 (file)
@@ -64,9 +64,9 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
        isync();
 
        if (is_load)
-               ret = probe_user_read(to, (const void __user *)from, n);
+               ret = copy_from_user_nofault(to, (const void __user *)from, n);
        else
-               ret = probe_user_write((void __user *)to, from, n);
+               ret = copy_to_user_nofault((void __user *)to, from, n);
 
        /* switch the pid first to avoid running host with unallocated pid */
        if (quadrant == 1 && pid != old_pid)
index aedfd6e..9cc17eb 100644 (file)
@@ -15,11 +15,11 @@ int probe_user_read_inst(struct ppc_inst *inst,
        unsigned int val, suffix;
        int err;
 
-       err = probe_user_read(&val, nip, sizeof(val));
+       err = copy_from_user_nofault(&val, nip, sizeof(val));
        if (err)
                return err;
        if (get_op(val) == OP_PREFIX) {
-               err = probe_user_read(&suffix, (void __user *)nip + 4, 4);
+               err = copy_from_user_nofault(&suffix, (void __user *)nip + 4, 4);
                *inst = ppc_inst_prefix(val, suffix);
        } else {
                *inst = ppc_inst(val);
@@ -33,11 +33,11 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
        unsigned int val, suffix;
        int err;
 
-       err = probe_kernel_read(&val, src, sizeof(val));
+       err = copy_from_kernel_nofault(&val, src, sizeof(val));
        if (err)
                return err;
        if (get_op(val) == OP_PREFIX) {
-               err = probe_kernel_read(&suffix, (void *)src + 4, 4);
+               err = copy_from_kernel_nofault(&suffix, (void *)src + 4, 4);
                *inst = ppc_inst_prefix(val, suffix);
        } else {
                *inst = ppc_inst(val);
@@ -51,7 +51,7 @@ int probe_user_read_inst(struct ppc_inst *inst,
        unsigned int val;
        int err;
 
-       err = probe_user_read(&val, nip, sizeof(val));
+       err = copy_from_user_nofault(&val, nip, sizeof(val));
        if (!err)
                *inst = ppc_inst(val);
 
@@ -64,7 +64,7 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
        unsigned int val;
        int err;
 
-       err = probe_kernel_read(&val, src, sizeof(val));
+       err = copy_from_kernel_nofault(&val, src, sizeof(val));
        if (!err)
                *inst = ppc_inst(val);
 
index 6f347fa..9db7ada 100644 (file)
@@ -33,7 +33,8 @@ static unsigned int user_getsp32(unsigned int sp, int is_first)
         * which means that we've done all that we can do from
         * interrupt context.
         */
-       if (probe_user_read(stack_frame, (void __user *)p, sizeof(stack_frame)))
+       if (copy_from_user_nofault(stack_frame, (void __user *)p,
+                       sizeof(stack_frame)))
                return 0;
 
        if (!is_first)
@@ -51,7 +52,8 @@ static unsigned long user_getsp64(unsigned long sp, int is_first)
 {
        unsigned long stack_frame[3];
 
-       if (probe_user_read(stack_frame, (void __user *)sp, sizeof(stack_frame)))
+       if (copy_from_user_nofault(stack_frame, (void __user *)sp,
+                       sizeof(stack_frame)))
                return 0;
 
        if (!is_first)
index f7d888d..542e68b 100644 (file)
@@ -44,7 +44,7 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
            ((unsigned long)ptr & 3))
                return -EFAULT;
 
-       rc = probe_user_read(ret, ptr, sizeof(*ret));
+       rc = copy_from_user_nofault(ret, ptr, sizeof(*ret));
 
        if (IS_ENABLED(CONFIG_PPC64) && rc)
                return read_user_stack_slow(ptr, ret, 4);
index 814d1c2..fa2a1b8 100644 (file)
@@ -50,7 +50,7 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
            ((unsigned long)ptr & 7))
                return -EFAULT;
 
-       if (!probe_user_read(ret, ptr, sizeof(*ret)))
+       if (!copy_from_user_nofault(ret, ptr, sizeof(*ret)))
                return 0;
 
        return read_user_stack_slow(ptr, ret, 8);
index 13b9dd5..cd6a742 100644 (file)
@@ -418,14 +418,16 @@ static __u64 power_pmu_bhrb_to(u64 addr)
        __u64 target;
 
        if (is_kernel_addr(addr)) {
-               if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
+               if (copy_from_kernel_nofault(&instr, (void *)addr,
+                               sizeof(instr)))
                        return 0;
 
                return branch_target((struct ppc_inst *)&instr);
        }
 
        /* Userspace: need copy instruction here then translate it */
-       if (probe_user_read(&instr, (unsigned int __user *)addr, sizeof(instr)))
+       if (copy_from_user_nofault(&instr, (unsigned int __user *)addr,
+                       sizeof(instr)))
                return 0;
 
        target = branch_target((struct ppc_inst *)&instr);
index 4a8874b..040b9d0 100644 (file)
@@ -1066,10 +1066,10 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs)
 
        if (is_in_pci_mem_space(addr)) {
                if (user_mode(regs))
-                       ret = probe_user_read(&inst, (void __user *)regs->nip,
-                                             sizeof(inst));
+                       ret = copy_from_user_nofault(&inst,
+                                       (void __user *)regs->nip, sizeof(inst));
                else
-                       ret = probe_kernel_address((void *)regs->nip, inst);
+                       ret = get_kernel_nofault(inst, (void *)regs->nip);
 
                if (!ret && mcheck_handle_load(regs, inst)) {
                        regs->nip += 4;
index 0839661..2ff63d0 100644 (file)
@@ -38,7 +38,8 @@ static int ftrace_check_current_call(unsigned long hook_pos,
         * Read the text we want to modify;
         * return must be -EFAULT on read error
         */
-       if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)hook_pos,
+                       MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /*
index f16ade8..c3275f4 100644 (file)
@@ -62,7 +62,7 @@ int get_step_address(struct pt_regs *regs, unsigned long *next_addr)
        unsigned int rs1_num, rs2_num;
        int op_code;
 
-       if (probe_kernel_address((void *)pc, op_code))
+       if (get_kernel_nofault(op_code, (void *)pc))
                return -EINVAL;
        if ((op_code & __INSN_LENGTH_MASK) != __INSN_LENGTH_GE_32) {
                if (is_c_jalr_insn(op_code) || is_c_jr_insn(op_code)) {
@@ -146,14 +146,14 @@ int do_single_step(struct pt_regs *regs)
                return error;
 
        /* Store the op code in the stepped address */
-       error = probe_kernel_address((void *)addr, stepped_opcode);
+       error = get_kernel_nofault(stepped_opcode, (void *)addr);
        if (error)
                return error;
 
        stepped_address = addr;
 
        /* Replace the op code with the break instruction */
-       error = probe_kernel_write((void *)stepped_address,
+       error = copy_to_kernel_nofault((void *)stepped_address,
                                   arch_kgdb_ops.gdb_bpt_instr,
                                   BREAK_INSTR_SIZE);
        /* Flush and return */
@@ -173,7 +173,7 @@ int do_single_step(struct pt_regs *regs)
 static void undo_single_step(struct pt_regs *regs)
 {
        if (stepped_opcode != 0) {
-               probe_kernel_write((void *)stepped_address,
+               copy_to_kernel_nofault((void *)stepped_address,
                                   (void *)&stepped_opcode, BREAK_INSTR_SIZE);
                flush_icache_range(stepped_address,
                                   stepped_address + BREAK_INSTR_SIZE);
index d4a64df..3fe7a52 100644 (file)
@@ -63,7 +63,7 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
 
        waddr = patch_map(addr, FIX_TEXT_POKE0);
 
-       ret = probe_kernel_write(waddr, insn, len);
+       ret = copy_to_kernel_nofault(waddr, insn, len);
 
        patch_unmap(FIX_TEXT_POKE0);
 
@@ -76,7 +76,7 @@ NOKPROBE_SYMBOL(patch_insn_write);
 #else
 static int patch_insn_write(void *addr, const void *insn, size_t len)
 {
-       return probe_kernel_write(addr, insn, len);
+       return copy_to_kernel_nofault(addr, insn, len);
 }
 NOKPROBE_SYMBOL(patch_insn_write);
 #endif /* CONFIG_MMU */
index ecec177..7d95cce 100644 (file)
@@ -137,7 +137,7 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
 {
        bug_insn_t insn;
 
-       if (probe_kernel_address((bug_insn_t *)pc, insn))
+       if (get_kernel_nofault(insn, (bug_insn_t *)pc))
                return 0;
 
        return GET_INSN_LENGTH(insn);
@@ -165,7 +165,7 @@ int is_valid_bugaddr(unsigned long pc)
 
        if (pc < VMALLOC_START)
                return 0;
-       if (probe_kernel_address((bug_insn_t *)pc, insn))
+       if (get_kernel_nofault(insn, (bug_insn_t *)pc))
                return 0;
        if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
                return (insn == __BUG_INSN_32);
index 44e01dd..b388e87 100644 (file)
@@ -83,7 +83,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 {
        struct ftrace_insn orig, new, old;
 
-       if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
+       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
                return -EFAULT;
        if (addr == MCOUNT_ADDR) {
                /* Initial code replacement */
@@ -105,7 +105,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
        struct ftrace_insn orig, new, old;
 
-       if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
+       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
                return -EFAULT;
        /* Replace nop with an ftrace call. */
        ftrace_generate_nop_insn(&orig);
index 6a24751..d53c2e2 100644 (file)
@@ -105,7 +105,7 @@ static int bad_address(void *p)
 {
        unsigned long dummy;
 
-       return probe_kernel_address((unsigned long *)p, dummy);
+       return get_kernel_nofault(dummy, (unsigned long *)p);
 }
 
 static void dump_pagetable(unsigned long asce, unsigned long address)
index 1b04270..0646c59 100644 (file)
@@ -119,7 +119,7 @@ static void ftrace_mod_code(void)
         * But if one were to fail, then they all should, and if one were
         * to succeed, then they all should.
         */
-       mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
+       mod_code_status = copy_to_kernel_nofault(mod_code_ip, mod_code_newcode,
                                             MCOUNT_INSN_SIZE);
 
        /* if we fail, then kill any new writers */
@@ -203,7 +203,7 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
         */
 
        /* read the text we want to modify */
-       if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        /* Make sure it is what we expect it to be */
@@ -268,7 +268,7 @@ static int ftrace_mod(unsigned long ip, unsigned long old_addr,
 {
        unsigned char code[MCOUNT_INSN_SIZE];
 
-       if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+       if (copy_from_kernel_nofault(code, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
        if (old_addr != __raw_readl((unsigned long *)code))
index a330254..9c3d32b 100644 (file)
@@ -118,7 +118,7 @@ int is_valid_bugaddr(unsigned long addr)
 
        if (addr < PAGE_OFFSET)
                return 0;
-       if (probe_kernel_address((insn_size_t *)addr, opcode))
+       if (get_kernel_nofault(opcode, (insn_size_t *)addr))
                return 0;
        if (opcode == TRAPA_BUG_OPCODE)
                return 1;
index e929c09..8ccd568 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/kernel.h>
 #include <os.h>
 
-bool probe_kernel_read_allowed(const void *src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *src, size_t size)
 {
        void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE);
 
index ebedeab..255b2dd 100644 (file)
@@ -278,7 +278,7 @@ static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs
 }
 
 /* To avoid include hell, we can't include uaccess.h */
-extern long probe_kernel_read(void *dst, const void *src, size_t size);
+extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
 
 /**
  * regs_get_kernel_stack_nth() - get Nth entry of the stack
@@ -298,7 +298,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
 
        addr = regs_get_kernel_stack_nth_addr(regs, n);
        if (addr) {
-               ret = probe_kernel_read(&val, addr, sizeof(val));
+               ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
                if (!ret)
                        return val;
        }
index 456511b..b037cfa 100644 (file)
@@ -106,7 +106,7 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
        bad_ip = user_mode(regs) &&
                __chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
 
-       if (bad_ip || probe_kernel_read(opcodes, (u8 *)prologue,
+       if (bad_ip || copy_from_kernel_nofault(opcodes, (u8 *)prologue,
                                        OPCODE_BUFSIZE)) {
                printk("%sCode: Bad RIP value.\n", loglvl);
        } else {
index c84d28e..5150456 100644 (file)
@@ -86,7 +86,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code)
         * sure what we read is what we expected it to be before modifying it.
         */
        /* read the text we want to modify */
-       if (probe_kernel_read(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
+       if (copy_from_kernel_nofault(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
                WARN_ON(1);
                return -EFAULT;
        }
@@ -355,7 +355,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
        npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
 
        /* Copy ftrace_caller onto the trampoline memory */
-       ret = probe_kernel_read(trampoline, (void *)start_offset, size);
+       ret = copy_from_kernel_nofault(trampoline, (void *)start_offset, size);
        if (WARN_ON(ret < 0))
                goto fail;
 
@@ -363,13 +363,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        /* The trampoline ends with ret(q) */
        retq = (unsigned long)ftrace_stub;
-       ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+       ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
        if (WARN_ON(ret < 0))
                goto fail;
 
        if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
                ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
-               ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+               ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
                if (WARN_ON(ret < 0))
                        goto fail;
        }
@@ -506,7 +506,7 @@ static void *addr_from_call(void *ptr)
        union text_poke_insn call;
        int ret;
 
-       ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
+       ret = copy_from_kernel_nofault(&call, ptr, CALL_INSN_SIZE);
        if (WARN_ON_ONCE(ret < 0))
                return NULL;
 
index c44fe7d..68acd30 100644 (file)
@@ -732,11 +732,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        int err;
 
        bpt->type = BP_BREAKPOINT;
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
-       err = probe_kernel_write((char *)bpt->bpt_addr,
+       err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
        if (!err)
                return err;
@@ -768,7 +768,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
        return 0;
 
 knl_write:
-       return probe_kernel_write((char *)bpt->bpt_addr,
+       return copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
index 3bafe1b..f09985c 100644 (file)
@@ -243,7 +243,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
         * Fortunately, we know that the original code is the ideal 5-byte
         * long NOP.
         */
-       if (probe_kernel_read(buf, (void *)addr,
+       if (copy_from_kernel_nofault(buf, (void *)addr,
                MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
                return 0UL;
 
@@ -346,7 +346,8 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
                return 0;
 
        /* This can access kernel text if given address is not recovered */
-       if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
+       if (copy_from_kernel_nofault(dest, (void *)recovered_insn,
+                       MAX_INSN_SIZE))
                return 0;
 
        kernel_insn_init(insn, dest, MAX_INSN_SIZE);
index 321c199..7af4c61 100644 (file)
@@ -56,7 +56,7 @@ found:
         * overwritten by jump destination address. In this case, original
         * bytes must be recovered from op->optinsn.copied_insn buffer.
         */
-       if (probe_kernel_read(buf, (void *)addr,
+       if (copy_from_kernel_nofault(buf, (void *)addr,
                MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
                return 0UL;
 
index ee02863..9e1def3 100644 (file)
@@ -94,12 +94,12 @@ static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short
 }
 
 static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
-                      const unsigned char *rom_list)
+                      const void *rom_list)
 {
        unsigned short device;
 
        do {
-               if (probe_kernel_address(rom_list, device) != 0)
+               if (get_kernel_nofault(device, rom_list) != 0)
                        device = 0;
 
                if (device && match_id(pdev, vendor, device))
@@ -119,19 +119,19 @@ static struct resource *find_oprom(struct pci_dev *pdev)
        for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
                struct resource *res = &adapter_rom_resources[i];
                unsigned short offset, vendor, device, list, rev;
-               const unsigned char *rom;
+               const void *rom;
 
                if (res->end == 0)
                        break;
 
                rom = isa_bus_to_virt(res->start);
-               if (probe_kernel_address(rom + 0x18, offset) != 0)
+               if (get_kernel_nofault(offset, rom + 0x18) != 0)
                        continue;
 
-               if (probe_kernel_address(rom + offset + 0x4, vendor) != 0)
+               if (get_kernel_nofault(vendor, rom + offset + 0x4) != 0)
                        continue;
 
-               if (probe_kernel_address(rom + offset + 0x6, device) != 0)
+               if (get_kernel_nofault(device, rom + offset + 0x6) != 0)
                        continue;
 
                if (match_id(pdev, vendor, device)) {
@@ -139,8 +139,8 @@ static struct resource *find_oprom(struct pci_dev *pdev)
                        break;
                }
 
-               if (probe_kernel_address(rom + offset + 0x8, list) == 0 &&
-                   probe_kernel_address(rom + offset + 0xc, rev) == 0 &&
+               if (get_kernel_nofault(list, rom + offset + 0x8) == 0 &&
+                   get_kernel_nofault(rev, rom + offset + 0xc) == 0 &&
                    rev >= 3 && list &&
                    probe_list(pdev, vendor, rom + offset + list)) {
                        oprom = res;
@@ -183,14 +183,14 @@ static int __init romsignature(const unsigned char *rom)
        const unsigned short * const ptr = (const unsigned short *)rom;
        unsigned short sig;
 
-       return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
+       return get_kernel_nofault(sig, ptr) == 0 && sig == ROMSIGNATURE;
 }
 
 static int __init romchecksum(const unsigned char *rom, unsigned long length)
 {
        unsigned char sum, c;
 
-       for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
+       for (sum = 0; length && get_kernel_nofault(c, rom++) == 0; length--)
                sum += c;
        return !length && !sum;
 }
@@ -211,7 +211,7 @@ void __init probe_roms(void)
 
                video_rom_resource.start = start;
 
-               if (probe_kernel_address(rom + 2, c) != 0)
+               if (get_kernel_nofault(c, rom + 2) != 0)
                        continue;
 
                /* 0 < length <= 0x7f * 512, historically */
@@ -249,7 +249,7 @@ void __init probe_roms(void)
                if (!romsignature(rom))
                        continue;
 
-               if (probe_kernel_address(rom + 2, c) != 0)
+               if (get_kernel_nofault(c, rom + 2) != 0)
                        continue;
 
                /* 0 < length <= 0x7f * 512, historically */
index af75109..f9727b9 100644 (file)
@@ -91,7 +91,7 @@ int is_valid_bugaddr(unsigned long addr)
        if (addr < TASK_SIZE_MAX)
                return 0;
 
-       if (probe_kernel_address((unsigned short *)addr, ud))
+       if (get_kernel_nofault(ud, (unsigned short *)addr))
                return 0;
 
        return ud == INSN_UD0 || ud == INSN_UD2;
@@ -488,7 +488,8 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
        u8 insn_buf[MAX_INSN_SIZE];
        struct insn insn;
 
-       if (probe_kernel_read(insn_buf, (void *)regs->ip, MAX_INSN_SIZE))
+       if (copy_from_kernel_nofault(insn_buf, (void *)regs->ip,
+                       MAX_INSN_SIZE))
                return GP_NO_HINT;
 
        kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
index 66be9bd..1ead568 100644 (file)
@@ -99,7 +99,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
                return !instr_lo || (instr_lo>>1) == 1;
        case 0x00:
                /* Prefetch instruction is 0x0F0D or 0x0F18 */
-               if (probe_kernel_address(instr, opcode))
+               if (get_kernel_nofault(opcode, instr))
                        return 0;
 
                *prefetch = (instr_lo == 0xF) &&
@@ -133,7 +133,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
        while (instr < max_instr) {
                unsigned char opcode;
 
-               if (probe_kernel_address(instr, opcode))
+               if (get_kernel_nofault(opcode, instr))
                        break;
 
                instr++;
@@ -301,7 +301,7 @@ static int bad_address(void *p)
 {
        unsigned long dummy;
 
-       return probe_kernel_address((unsigned long *)p, dummy);
+       return get_kernel_nofault(dummy, (unsigned long *)p);
 }
 
 static void dump_pagetable(unsigned long address)
@@ -442,7 +442,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
                return;
        }
 
-       if (probe_kernel_read(&desc, (void *)(gdt->address + offset),
+       if (copy_from_kernel_nofault(&desc, (void *)(gdt->address + offset),
                              sizeof(struct ldttss_desc))) {
                pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
                         name, index);
index bda909e..8b4afad 100644 (file)
@@ -737,7 +737,7 @@ static void __init test_wp_bit(void)
 
        __set_fixmap(FIX_WP_TEST, __pa_symbol(empty_zero_page), PAGE_KERNEL_RO);
 
-       if (probe_kernel_write((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
+       if (copy_to_kernel_nofault((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
                clear_fixmap(FIX_WP_TEST);
                printk(KERN_CONT "Ok.\n");
                return;
index e1d7d74..92ec176 100644 (file)
@@ -9,7 +9,7 @@ static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
        return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
 }
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        unsigned long vaddr = (unsigned long)unsafe_src;
 
@@ -22,7 +22,7 @@ bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
               canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
 }
 #else
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
        return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
 }
index 9c97d81..4f15280 100644 (file)
@@ -302,7 +302,7 @@ static const struct pci_raw_ops *__init pci_find_bios(void)
             check <= (union bios32 *) __va(0xffff0);
             ++check) {
                long sig;
-               if (probe_kernel_address(&check->fields.signature, sig))
+               if (get_kernel_nofault(sig, &check->fields.signature))
                        continue;
 
                if (check->fields.signature != BIOS32_SIGNATURE)
index b04e6e7..088bd76 100644 (file)
@@ -34,6 +34,7 @@ KCOV_INSTRUMENT := n
 PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
 PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
 PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
+PURGATORY_CFLAGS += $(call cc-option,-fno-stack-protector)
 
 # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
 # in turn leaves some undefined symbols like __fentry__ in purgatory and not
index 33b309d..acc49fa 100644 (file)
@@ -386,7 +386,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 
        preempt_disable();
 
-       probe_kernel_read(&dummy, v, 1);
+       copy_from_kernel_nofault(&dummy, v, 1);
 
        if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
                BUG();
index 841580a..d8d6bea 100644 (file)
@@ -93,7 +93,7 @@ struct frag {                         /* VBLK Fragment handling */
        u8              num;            /* Total number of records */
        u8              rec;            /* This is record number n */
        u8              map;            /* Which portions are in use */
-       u8              data[0];
+       u8              data[];
 };
 
 /* In memory LDM database structures. */
index 57d3b2e..0b2c20f 100644 (file)
@@ -120,7 +120,7 @@ static const u32 tegra_ahb_gizmo[] = {
 struct tegra_ahb {
        void __iomem    *regs;
        struct device   *dev;
-       u32             ctx[0];
+       u32             ctx[];
 };
 
 static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
index 69361ec..b1cd4d9 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/workqueue.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
-#include <linux/async.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
 #include <linux/glob.h>
@@ -5778,7 +5777,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
        /* perform each probe asynchronously */
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
-               async_schedule(async_port_probe, ap);
+               ap->cookie = async_schedule(async_port_probe, ap);
        }
 
        return 0;
@@ -5920,11 +5919,11 @@ void ata_host_detach(struct ata_host *host)
 {
        int i;
 
-       /* Ensure ata_port probe has completed */
-       async_synchronize_full();
-
-       for (i = 0; i < host->n_ports; i++)
+       for (i = 0; i < host->n_ports; i++) {
+               /* Ensure ata_port probe has completed */
+               async_synchronize_cookie(host->ports[i]->cookie + 1);
                ata_port_detach(host->ports[i]);
+       }
 
        /* the host is dead now, dissociate ACPI */
        ata_acpi_dissociate(host);
index 435781a..4633608 100644 (file)
@@ -3684,12 +3684,13 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *scmd = qc->scsicmd;
        const u8 *cdb = scmd->cmnd;
-       const u8 *p;
        u8 pg, spg;
        unsigned six_byte, pg_len, hdr_len, bd_len;
        int len;
        u16 fp = (u16)-1;
        u8 bp = 0xff;
+       u8 buffer[64];
+       const u8 *p = buffer;
 
        VPRINTK("ENTER\n");
 
@@ -3723,12 +3724,14 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
        if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
                goto invalid_param_len;
 
-       p = page_address(sg_page(scsi_sglist(scmd)));
-
        /* Move past header and block descriptors.  */
        if (len < hdr_len)
                goto invalid_param_len;
 
+       if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd),
+                              buffer, sizeof(buffer)))
+               goto invalid_param_len;
+
        if (six_byte)
                bd_len = p[3];
        else
index 980aacd..141ac60 100644 (file)
@@ -907,7 +907,7 @@ static int sata_rcar_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(dev);
        if (ret < 0)
-               goto err_pm_disable;
+               goto err_pm_put;
 
        host = ata_host_alloc(dev, 1);
        if (!host) {
@@ -937,7 +937,6 @@ static int sata_rcar_probe(struct platform_device *pdev)
 
 err_pm_put:
        pm_runtime_put(dev);
-err_pm_disable:
        pm_runtime_disable(dev);
        return ret;
 }
@@ -991,8 +990,10 @@ static int sata_rcar_resume(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        if (priv->type == RCAR_GEN3_SATA) {
                sata_rcar_init_module(priv);
@@ -1017,8 +1018,10 @@ static int sata_rcar_restore(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        sata_rcar_setup_port(host);
 
index 14345a8..33d0831 100644 (file)
@@ -620,7 +620,7 @@ struct fifo_buffer {
        unsigned int head_index;
        unsigned int size;
        int total; /* sum of all values */
-       int values[0];
+       int values[];
 };
 extern struct fifo_buffer *fifo_alloc(unsigned int fifo_size);
 
index e6fc5ad..dea59c9 100644 (file)
@@ -271,7 +271,7 @@ struct p_rs_param {
        u32 resync_rate;
 
              /* Since protocol version 88 and higher. */
-       char verify_alg[0];
+       char verify_alg[];
 } __packed;
 
 struct p_rs_param_89 {
@@ -305,7 +305,7 @@ struct p_protocol {
        u32 two_primaries;
 
        /* Since protocol version 87 and higher. */
-       char integrity_alg[0];
+       char integrity_alg[];
 
 } __packed;
 
@@ -360,7 +360,7 @@ struct p_sizes {
        u16         dds_flags; /* use enum dds_flags here. */
 
        /* optional queue_limits if (agreed_features & DRBD_FF_WSAME) */
-       struct o_qlim qlim[0];
+       struct o_qlim qlim[];
 } __packed;
 
 struct p_state {
@@ -409,7 +409,7 @@ struct p_compressed_bm {
         */
        u8 encoding;
 
-       u8 code[0];
+       u8 code[];
 } __packed;
 
 struct p_delay_probe93 {
index 7420648..4f61e92 100644 (file)
@@ -1451,8 +1451,10 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
 static void rbd_osd_format_read(struct ceph_osd_request *osd_req)
 {
        struct rbd_obj_request *obj_request = osd_req->r_priv;
+       struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
+       struct ceph_options *opt = rbd_dev->rbd_client->client->options;
 
-       osd_req->r_flags = CEPH_OSD_FLAG_READ;
+       osd_req->r_flags = CEPH_OSD_FLAG_READ | opt->read_from_replica;
        osd_req->r_snapid = obj_request->img_request->snap_id;
 }
 
index 31cae88..934c92d 100644 (file)
@@ -171,7 +171,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
                        if (!ptr)
                                goto failed;
 
-                       probe = probe_kernel_read(bounce, ptr, sz);
+                       probe = copy_from_kernel_nofault(bounce, ptr, sz);
                        unxlate_dev_mem_ptr(p, ptr);
                        if (probe)
                                goto failed;
index b3fdbdc..31e427e 100644 (file)
@@ -223,7 +223,7 @@ struct chcr_authenc_ctx {
 
 struct __aead_ctx {
        struct chcr_gcm_ctx gcm[0];
-       struct chcr_authenc_ctx authenc[0];
+       struct chcr_authenc_ctx authenc[];
 };
 
 struct chcr_aead_ctx {
@@ -235,7 +235,7 @@ struct chcr_aead_ctx {
        u8 nonce[4];
        u16 hmac_ctrl;
        u16 mayverify;
-       struct  __aead_ctx ctx[0];
+       struct  __aead_ctx ctx[];
 };
 
 struct hmac_ctx {
@@ -247,7 +247,7 @@ struct hmac_ctx {
 struct __crypto_ctx {
        struct hmac_ctx hmacctx[0];
        struct ablk_ctx ablkctx[0];
-       struct chcr_aead_ctx aeadctx[0];
+       struct chcr_aead_ctx aeadctx[];
 };
 
 struct chcr_context {
@@ -257,7 +257,7 @@ struct chcr_context {
        unsigned int  ntxq;
        unsigned int  nrxq;
        struct completion cbc_aes_aio_done;
-       struct __crypto_ctx crypto_ctx[0];
+       struct __crypto_ctx crypto_ctx[];
 };
 
 struct chcr_hctx_per_wr {
index c9aa15f..193b40e 100644 (file)
@@ -135,7 +135,8 @@ int __init dio_find(int deviceid)
                else
                        va = ioremap(pa, PAGE_SIZE);
 
-                if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
+               if (copy_from_kernel_nofault(&i,
+                               (unsigned char *)va + DIO_IDOFF, 1)) {
                        if (scode >= DIOII_SCBASE)
                                iounmap(va);
                         continue;             /* no board present at that select code */
@@ -208,7 +209,8 @@ static int __init dio_init(void)
                else
                        va = ioremap(pa, PAGE_SIZE);
 
-                if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
+               if (copy_from_kernel_nofault(&i,
+                               (unsigned char *)va + DIO_IDOFF, 1)) {
                        if (scode >= DIOII_SCBASE)
                                iounmap(va);
                         continue;              /* no board present at that select code */
index 8853d44..a8cfb59 100644 (file)
@@ -77,7 +77,7 @@ struct milbeaut_hdmac_device {
        struct dma_device ddev;
        struct clk *clk;
        void __iomem *reg_base;
-       struct milbeaut_hdmac_chan channels[0];
+       struct milbeaut_hdmac_chan channels[];
 };
 
 static struct milbeaut_hdmac_chan *
index ab3d2f3..85a5972 100644 (file)
@@ -74,7 +74,7 @@ struct milbeaut_xdmac_chan {
 struct milbeaut_xdmac_device {
        struct dma_device ddev;
        void __iomem *reg_base;
-       struct milbeaut_xdmac_chan channels[0];
+       struct milbeaut_xdmac_chan channels[];
 };
 
 static struct milbeaut_xdmac_chan *
index 4ab493d..347146a 100644 (file)
@@ -127,7 +127,7 @@ struct moxart_desc {
        unsigned int                    dma_cycles;
        struct virt_dma_desc            vd;
        uint8_t                         es;
-       struct moxart_sg                sg[0];
+       struct moxart_sg                sg[];
 };
 
 struct moxart_chan {
index b9f0d96..55fc740 100644 (file)
@@ -225,7 +225,7 @@ struct tegra_dma {
        u32                             global_pause_count;
 
        /* Last member of the structure */
-       struct tegra_dma_channel channels[0];
+       struct tegra_dma_channel channels[];
 };
 
 static inline void tdma_write(struct tegra_dma *tdma, u32 reg, u32 val)
index c4a5c17..35d81bd 100644 (file)
@@ -211,7 +211,7 @@ struct edma_desc {
        u32                             residue;
        u32                             residue_stat;
 
-       struct edma_pset                pset[0];
+       struct edma_pset                pset[];
 };
 
 struct edma_cc;
index 945b7c6..c91e2dc 100644 (file)
@@ -170,7 +170,7 @@ struct udma_desc {
        void *metadata; /* pointer to provided metadata buffer (EPIP, PSdata) */
 
        unsigned int hwdesc_count;
-       struct udma_hwdesc hwdesc[0];
+       struct udma_hwdesc hwdesc[];
 };
 
 enum udma_chan_state {
index 3938269..68e48bf 100644 (file)
@@ -88,7 +88,7 @@ struct timb_dma {
        struct dma_device       dma;
        void __iomem            *membase;
        struct tasklet_struct   tasklet;
-       struct timb_dma_chan    channels[0];
+       struct timb_dma_chan    channels[];
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
index c7ea4f2..fb6c651 100644 (file)
@@ -117,7 +117,7 @@ struct inbound_transaction_resource {
 struct descriptor_resource {
        struct client_resource resource;
        struct fw_descriptor descriptor;
-       u32 data[0];
+       u32 data[];
 };
 
 struct iso_resource {
index 404a035..439d918 100644 (file)
@@ -620,7 +620,7 @@ struct fw_request {
        u32 request_header[4];
        int ack;
        u32 length;
-       u32 data[0];
+       u32 data[];
 };
 
 static void free_response_callback(struct fw_packet *packet,
index 4b0e4ee..71d5f16 100644 (file)
@@ -191,7 +191,7 @@ struct fw_node {
        /* Upper layer specific data. */
        void *data;
 
-       struct fw_node *ports[0];
+       struct fw_node *ports[];
 };
 
 static inline struct fw_node *fw_node_get(struct fw_node *node)
index 6ca2f5a..5fd6a60 100644 (file)
@@ -52,7 +52,7 @@ struct pcl {
 
 struct packet {
        unsigned int length;
-       char data[0];
+       char data[];
 };
 
 struct packet_buffer {
index 3326931..54fdc39 100644 (file)
@@ -111,7 +111,7 @@ struct descriptor_buffer {
        dma_addr_t buffer_bus;
        size_t buffer_size;
        size_t used;
-       struct descriptor buffer[0];
+       struct descriptor buffer[];
 };
 
 struct context {
index b618002..8b8127f 100644 (file)
@@ -262,7 +262,7 @@ struct dmi_system_event_log {
        u8      header_format;
        u8      type_descriptors_supported_count;
        u8      per_log_type_descriptor_length;
-       u8      supported_log_type_descriptos[0];
+       u8      supported_log_type_descriptos[];
 } __packed;
 
 #define DMI_SYSFS_SEL_FIELD(_field) \
index fd7f0fb..d17e4d6 100644 (file)
@@ -21,7 +21,7 @@
 struct cbmem_cons {
        u32 size_dont_access_after_boot;
        u32 cursor;
-       u8  body[0];
+       u8  body[];
 } __packed;
 
 #define CURSOR_MASK ((1 << 28) - 1)
index db08122..d23c5c6 100644 (file)
@@ -32,7 +32,7 @@ struct vpd_cbmem {
        u32 version;
        u32 ro_size;
        u32 rw_size;
-       u8  blob[0];
+       u8  blob[];
 };
 
 struct vpd_section {
index 96758b7..7127a04 100644 (file)
@@ -104,7 +104,7 @@ struct ibft_control {
        u16 tgt0_off;
        u16 nic1_off;
        u16 tgt1_off;
-       u16 expansion[0];
+       u16 expansion[];
 } __attribute__((__packed__));
 
 struct ibft_initiator {
index ce75d1d..e025405 100644 (file)
@@ -103,6 +103,6 @@ struct pcdp {
        u8                      creator_id[4];
        u32                     creator_rev;
        u32                     num_uarts;
-       struct pcdp_uart        uart[0];        /* actual size is num_uarts */
+       struct pcdp_uart        uart[]; /* actual size is num_uarts */
        /* remainder of table is pcdp_device structures */
 } __attribute__((packed));
index 775e389..16596a9 100644 (file)
@@ -696,7 +696,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
  * default power levels, write "r" (reset) to the file to reset them.
  *
  *
- * < For Vega20 >
+ * < For Vega20 and newer ASICs >
  *
  * Reading the file will display:
  *
@@ -1668,7 +1668,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
 }
 
 /**
- * DOC: busy_percent
+ * DOC: gpu_busy_percent
  *
  * The amdgpu driver provides a sysfs API for reading how busy the GPU
  * is as a percentage.  The file gpu_busy_percent is used for this.
index f0587d9..fee6092 100644 (file)
@@ -40,6 +40,7 @@
 #include <drm/drm_file.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_device.h>
+#include <drm/drm_ioctl.h>
 #include <kgd_kfd_interface.h>
 #include <linux/swap.h>
 
@@ -1076,7 +1077,7 @@ static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
 #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
        struct drm_device *ddev = kfd->ddev;
 
-       return devcgroup_check_permission(DEVCG_DEV_CHAR, ddev->driver->major,
+       return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR,
                                          ddev->render->index,
                                          DEVCG_ACC_WRITE | DEVCG_ACC_READ);
 #else
index 3f66868..ea29cf9 100644 (file)
@@ -28,8 +28,6 @@ endif
 endif
 
 CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc_dpi.o := $(dsc_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dsc/dc_dsc.o := $(dsc_ccflags)
 
 DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
 
index 0ea6662..0c7f247 100644 (file)
  * Author: AMD
  */
 
+#include <drm/drm_dsc.h>
 #include "dc_hw_types.h"
 #include "dsc.h"
 #include <drm/drm_dp_helper.h>
 #include "dc.h"
+#include "rc_calc.h"
 
 /* This module's internal functions */
 
@@ -304,22 +306,6 @@ static inline uint32_t dsc_div_by_10_round_up(uint32_t value)
        return (value + 9) / 10;
 }
 
-static inline uint32_t calc_dsc_bpp_x16(uint32_t stream_bandwidth_kbps, uint32_t pix_clk_100hz, uint32_t bpp_increment_div)
-{
-       uint32_t dsc_target_bpp_x16;
-       float f_dsc_target_bpp;
-       float f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
-       uint32_t precision = bpp_increment_div; // bpp_increment_div is actually precision
-
-       f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
-
-       // Round down to the nearest precision stop to bring it into DSC spec range
-       dsc_target_bpp_x16 = (uint32_t)(f_dsc_target_bpp * precision);
-       dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
-
-       return dsc_target_bpp_x16;
-}
-
 /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock
  * and uncompressed bandwidth.
  */
index 03ae159..667afbc 100644 (file)
@@ -23,6 +23,7 @@
  * Authors: AMD
  *
  */
+#include <drm/drm_dsc.h>
 
 #include "os_types.h"
 #include "rc_calc.h"
@@ -40,7 +41,8 @@
        break
 
 
-void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, enum max_min max_min, float bpp)
+static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
+                      enum max_min max_min, float bpp)
 {
        int mode = MODE_SELECT(444, 422, 420);
        int sel = table_hash(mode, bpc, max_min);
@@ -85,7 +87,7 @@ void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, enum ma
        memcpy(qps, table[index].qps, sizeof(qp_set));
 }
 
-double dsc_roundf(double num)
+static double dsc_roundf(double num)
 {
        if (num < 0.0)
                num = num - 0.5;
@@ -95,7 +97,7 @@ double dsc_roundf(double num)
        return (int)(num);
 }
 
-double dsc_ceil(double num)
+static double dsc_ceil(double num)
 {
        double retval = (int)num;
 
@@ -105,7 +107,7 @@ double dsc_ceil(double num)
        return (int)retval;
 }
 
-void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
+static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
 {
        int   *p = ofs;
 
@@ -160,7 +162,7 @@ void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
        }
 }
 
-int median3(int a, int b, int c)
+static int median3(int a, int b, int c)
 {
        if (a > b)
                swap(a, b);
@@ -172,13 +174,25 @@ int median3(int a, int b, int c)
        return b;
 }
 
-void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version)
+static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm,
+                              enum bits_per_comp bpc, u8 drm_bpp,
+                              bool is_navite_422_or_420,
+                              int slice_width, int slice_height,
+                              int minor_version)
 {
+       float bpp;
        float bpp_group;
        float initial_xmit_delay_factor;
        int padding_pixels;
        int i;
 
+       bpp = ((float)drm_bpp / 16.0);
+       /* in native_422 or native_420 modes, the bits_per_pixel is double the
+        * target bpp (the latter is what calc_rc_params expects)
+        */
+       if (is_navite_422_or_420)
+               bpp /= 2.0;
+
        rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
        rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
 
@@ -251,3 +265,128 @@ void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_com
        rc->rc_buf_thresh[13] = 8064;
 }
 
+static u32 _do_bytes_per_pixel_calc(int slice_width, u8 drm_bpp,
+                                   bool is_navite_422_or_420)
+{
+       float bpp;
+       u32 bytes_per_pixel;
+       double d_bytes_per_pixel;
+
+       bpp = ((float)drm_bpp / 16.0);
+       d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
+       // TODO: Make sure the formula for calculating this is precise (ceiling
+       // vs. floor, and at what point they should be applied)
+       if (is_navite_422_or_420)
+               d_bytes_per_pixel /= 2;
+
+       bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
+
+       return bytes_per_pixel;
+}
+
+static u32 _do_calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                               u32 bpp_increment_div)
+{
+       u32 dsc_target_bpp_x16;
+       float f_dsc_target_bpp;
+       float f_stream_bandwidth_100bps;
+       // bpp_increment_div is actually precision
+       u32 precision = bpp_increment_div;
+
+       f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
+       f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
+
+       // Round down to the nearest precision stop to bring it into DSC spec
+       // range
+       dsc_target_bpp_x16 = (u32)(f_dsc_target_bpp * precision);
+       dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
+
+       return dsc_target_bpp_x16;
+}
+
+/**
+ * calc_rc_params - reads the user's cmdline mode
+ * @rc: DC internal DSC parameters
+ * @pps: DRM struct with all required DSC values
+ *
+ * This function expects a drm_dsc_config data struct with all the required DSC
+ * values previously filled out by our driver and based on this information it
+ * computes some of the DSC values.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ */
+void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps)
+{
+       enum colour_mode mode;
+       enum bits_per_comp bpc;
+       bool is_navite_422_or_420;
+       u8 drm_bpp = pps->bits_per_pixel;
+       int slice_width  = pps->slice_width;
+       int slice_height = pps->slice_height;
+
+       mode = pps->convert_rgb ? CM_RGB : (pps->simple_422  ? CM_444 :
+                                          (pps->native_422  ? CM_422 :
+                                           pps->native_420  ? CM_420 : CM_444));
+       bpc = (pps->bits_per_component == 8) ? BPC_8 : (pps->bits_per_component == 10)
+                                            ? BPC_10 : BPC_12;
+
+       is_navite_422_or_420 = pps->native_422 || pps->native_420;
+
+       DC_FP_START();
+       _do_calc_rc_params(rc, mode, bpc, drm_bpp, is_navite_422_or_420,
+                          slice_width, slice_height,
+                          pps->dsc_version_minor);
+       DC_FP_END();
+}
+
+/**
+ * calc_dsc_bytes_per_pixel - calculate bytes per pixel
+ * @pps: DRM struct with all required DSC values
+ *
+ * Based on the information inside drm_dsc_config, this function calculates the
+ * total of bytes per pixel.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ *
+ * Return:
+ * Return the number of bytes per pixel
+ */
+u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps)
+
+{
+       u32 ret;
+       u8 drm_bpp = pps->bits_per_pixel;
+       int slice_width  = pps->slice_width;
+       bool is_navite_422_or_420 = pps->native_422 || pps->native_420;
+
+       DC_FP_START();
+       ret = _do_bytes_per_pixel_calc(slice_width, drm_bpp,
+                                      is_navite_422_or_420);
+       DC_FP_END();
+       return ret;
+}
+
+/**
+ * calc_dsc_bpp_x16 - retrieve the dsc bits per pixel
+ * @stream_bandwidth_kbps:
+ * @pix_clk_100hz:
+ * @bpp_increment_div:
+ *
+ * Calculate the total of bits per pixel for DSC configuration.
+ *
+ * @note This calculation requires float point operation, most of it executes
+ * under kernel_fpu_{begin,end}.
+ */
+u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                    u32 bpp_increment_div)
+{
+       u32 dsc_bpp;
+
+       DC_FP_START();
+       dsc_bpp =  _do_calc_dsc_bpp_x16(stream_bandwidth_kbps, pix_clk_100hz,
+                                       bpp_increment_div);
+       DC_FP_END();
+       return dsc_bpp;
+}
index b6b1f09..21723fa 100644 (file)
@@ -77,7 +77,10 @@ struct qp_entry {
 
 typedef struct qp_entry qp_table[];
 
-void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version);
+void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps);
+u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps);
+u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz,
+                    u32 bpp_increment_div);
 
 #endif
 
index 1f6e63b..ef830ad 100644 (file)
@@ -27,8 +27,6 @@
 #include "dscc_types.h"
 #include "rc_calc.h"
 
-double dsc_ceil(double num);
-
 static void copy_pps_fields(struct drm_dsc_config *to, const struct drm_dsc_config *from)
 {
        to->line_buf_depth           = from->line_buf_depth;
@@ -100,34 +98,13 @@ static void copy_rc_to_cfg(struct drm_dsc_config *dsc_cfg, const struct rc_param
 
 int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params)
 {
-       enum colour_mode  mode = pps->convert_rgb ? CM_RGB :
-                                                       (pps->simple_422  ? CM_444 :
-                                                       (pps->native_422  ? CM_422 :
-                                                       pps->native_420  ? CM_420 : CM_444));
-       enum bits_per_comp bpc = (pps->bits_per_component == 8) ? BPC_8 :
-                                                       (pps->bits_per_component == 10) ? BPC_10 : BPC_12;
-       float            bpp = ((float) pps->bits_per_pixel / 16.0);
-       int              slice_width  = pps->slice_width;
-       int              slice_height = pps->slice_height;
        int              ret;
        struct rc_params rc;
        struct drm_dsc_config   dsc_cfg;
 
-       double d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
-
-       // TODO: Make sure the formula for calculating this is precise (ceiling vs. floor, and at what point they should be applied)
-       if (pps->native_422 || pps->native_420)
-               d_bytes_per_pixel /= 2;
-
-       dsc_params->bytes_per_pixel = (uint32_t)dsc_ceil(d_bytes_per_pixel * 0x10000000);
-
-       /* in native_422 or native_420 modes, the bits_per_pixel is double the target bpp
-        * (the latter is what calc_rc_params expects)
-        */
-       if (pps->native_422 || pps->native_420)
-               bpp /= 2.0;
+       dsc_params->bytes_per_pixel = calc_dsc_bytes_per_pixel(pps);
 
-       calc_rc_params(&rc, mode, bpc, bpp, slice_width, slice_height, pps->dsc_version_minor);
+       calc_rc_params(&rc, pps);
        dsc_params->pps = *pps;
        dsc_params->pps.initial_scale_value = 8 * rc.rc_model_size / (rc.rc_model_size - rc.initial_fullness_offset);
 
index 9431b48..bcfe34e 100644 (file)
@@ -843,7 +843,7 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma,
        pow_buffer_ptr = -1; // reset back to no optimize
        ret = true;
 release:
-       kfree(coeff);
+       kvfree(coeff);
        return ret;
 }
 
@@ -1777,7 +1777,7 @@ bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf,
 
        kfree(rgb_regamma);
 rgb_regamma_alloc_fail:
-       kvfree(rgb_user);
+       kfree(rgb_user);
 rgb_user_alloc_fail:
        return ret;
 }
index 85e5b1e..56923a9 100644 (file)
@@ -239,7 +239,7 @@ static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
 
        switch (dev_id) {
        case 0x67BA:
-       case 0x66B1:
+       case 0x67B1:
                smu_data->power_tune_defaults = &defaults_hawaii_pro;
                break;
        case 0x67B8:
index aa22465..0575a1e 100644 (file)
@@ -2579,14 +2579,14 @@ static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
 
 static void
 tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, int link_clock,
-                               u32 level)
+                               u32 level, enum intel_output_type type)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
        const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations;
        u32 n_entries, val, ln, dpcnt_mask, dpcnt_val;
 
-       if (encoder->type == INTEL_OUTPUT_HDMI) {
+       if (type == INTEL_OUTPUT_HDMI) {
                n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans);
                ddi_translations = tgl_dkl_phy_hdmi_ddi_trans;
        } else {
@@ -2638,7 +2638,7 @@ static void tgl_ddi_vswing_sequence(struct intel_encoder *encoder,
        if (intel_phy_is_combo(dev_priv, phy))
                icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
        else
-               tgl_dkl_phy_ddi_vswing_sequence(encoder, link_clock, level);
+               tgl_dkl_phy_ddi_vswing_sequence(encoder, link_clock, level, type);
 }
 
 static u32 translate_signal_level(struct intel_dp *intel_dp, int signal_levels)
@@ -2987,7 +2987,7 @@ icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port,
                ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
        }
 
-       ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X1_MODE);
+       ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
        ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 
        /* DPPATC */
@@ -3472,7 +3472,9 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
                                          INTEL_OUTPUT_DP_MST);
        enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
 
-       intel_dp_set_infoframes(encoder, false, old_crtc_state, old_conn_state);
+       if (!is_mst)
+               intel_dp_set_infoframes(encoder, false,
+                                       old_crtc_state, old_conn_state);
 
        /*
         * Power down sink before disabling the port, otherwise we end
index d18b406..f29e51c 100644 (file)
@@ -397,6 +397,14 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
         */
        drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
                                     false);
+
+       /*
+        * BSpec 4287: disable DIP after the transcoder is disabled and before
+        * the transcoder clock select is set to none.
+        */
+       if (last_mst_stream)
+               intel_dp_set_infoframes(&intel_dig_port->base, false,
+                                       old_crtc_state, NULL);
        /*
         * From TGL spec: "If multi-stream slave transcoder: Configure
         * Transcoder Clock Select to direct no clock to the transcoder"
index da5b610..8691eb6 100644 (file)
@@ -646,7 +646,7 @@ static int engine_setup_common(struct intel_engine_cs *engine)
 struct measure_breadcrumb {
        struct i915_request rq;
        struct intel_ring ring;
-       u32 cs[1024];
+       u32 cs[2048];
 };
 
 static int measure_breadcrumb_dw(struct intel_context *ce)
@@ -668,6 +668,8 @@ static int measure_breadcrumb_dw(struct intel_context *ce)
 
        frame->ring.vaddr = frame->cs;
        frame->ring.size = sizeof(frame->cs);
+       frame->ring.wrap =
+               BITS_PER_TYPE(frame->ring.size) - ilog2(frame->ring.size);
        frame->ring.effective_size = frame->ring.size;
        intel_ring_update_space(&frame->ring);
        frame->rq.ring = &frame->ring;
index 87e6c5b..7c3d8ef 100644 (file)
@@ -1134,6 +1134,13 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
                        list_move(&rq->sched.link, pl);
                        set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
 
+                       /* Check in case we rollback so far we wrap [size/2] */
+                       if (intel_ring_direction(rq->ring,
+                                                intel_ring_wrap(rq->ring,
+                                                                rq->tail),
+                                                rq->ring->tail) > 0)
+                               rq->context->lrc.desc |= CTX_DESC_FORCE_RESTORE;
+
                        active = rq;
                } else {
                        struct intel_engine_cs *owner = rq->context->engine;
@@ -1498,8 +1505,9 @@ static u64 execlists_update_context(struct i915_request *rq)
         * HW has a tendency to ignore us rewinding the TAIL to the end of
         * an earlier request.
         */
+       GEM_BUG_ON(ce->lrc_reg_state[CTX_RING_TAIL] != rq->ring->tail);
+       prev = rq->ring->tail;
        tail = intel_ring_set_tail(rq->ring, rq->tail);
-       prev = ce->lrc_reg_state[CTX_RING_TAIL];
        if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
                desc |= CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state[CTX_RING_TAIL] = tail;
@@ -1895,7 +1903,8 @@ static void defer_active(struct intel_engine_cs *engine)
 
 static bool
 need_timeslice(const struct intel_engine_cs *engine,
-              const struct i915_request *rq)
+              const struct i915_request *rq,
+              const struct rb_node *rb)
 {
        int hint;
 
@@ -1903,9 +1912,28 @@ need_timeslice(const struct intel_engine_cs *engine,
                return false;
 
        hint = engine->execlists.queue_priority_hint;
+
+       if (rb) {
+               const struct virtual_engine *ve =
+                       rb_entry(rb, typeof(*ve), nodes[engine->id].rb);
+               const struct intel_engine_cs *inflight =
+                       intel_context_inflight(&ve->context);
+
+               if (!inflight || inflight == engine) {
+                       struct i915_request *next;
+
+                       rcu_read_lock();
+                       next = READ_ONCE(ve->request);
+                       if (next)
+                               hint = max(hint, rq_prio(next));
+                       rcu_read_unlock();
+               }
+       }
+
        if (!list_is_last(&rq->sched.link, &engine->active.requests))
                hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
 
+       GEM_BUG_ON(hint >= I915_PRIORITY_UNPREEMPTABLE);
        return hint >= effective_prio(rq);
 }
 
@@ -1977,10 +2005,9 @@ static void set_timeslice(struct intel_engine_cs *engine)
        set_timer_ms(&engine->execlists.timer, duration);
 }
 
-static void start_timeslice(struct intel_engine_cs *engine)
+static void start_timeslice(struct intel_engine_cs *engine, int prio)
 {
        struct intel_engine_execlists *execlists = &engine->execlists;
-       const int prio = queue_prio(execlists);
        unsigned long duration;
 
        if (!intel_engine_has_timeslices(engine))
@@ -2140,7 +2167,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                        __unwind_incomplete_requests(engine);
 
                        last = NULL;
-               } else if (need_timeslice(engine, last) &&
+               } else if (need_timeslice(engine, last, rb) &&
                           timeslice_expired(execlists, last)) {
                        if (i915_request_completed(last)) {
                                tasklet_hi_schedule(&execlists->tasklet);
@@ -2188,7 +2215,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                                 * Even if ELSP[1] is occupied and not worthy
                                 * of timeslices, our queue might be.
                                 */
-                               start_timeslice(engine);
+                               start_timeslice(engine, queue_prio(execlists));
                                return;
                        }
                }
@@ -2223,7 +2250,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                        if (last && !can_merge_rq(last, rq)) {
                                spin_unlock(&ve->base.active.lock);
-                               start_timeslice(engine);
+                               start_timeslice(engine, rq_prio(rq));
                                return; /* leave this for another sibling */
                        }
 
@@ -4739,6 +4766,14 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode)
        return 0;
 }
 
+static void assert_request_valid(struct i915_request *rq)
+{
+       struct intel_ring *ring __maybe_unused = rq->ring;
+
+       /* Can we unwind this request without appearing to go forwards? */
+       GEM_BUG_ON(intel_ring_direction(ring, rq->wa_tail, rq->head) <= 0);
+}
+
 /*
  * Reserve space for 2 NOOPs at the end of each request to be
  * used as a workaround for not being allowed to do lite
@@ -4751,6 +4786,9 @@ static u32 *gen8_emit_wa_tail(struct i915_request *request, u32 *cs)
        *cs++ = MI_NOOP;
        request->wa_tail = intel_ring_offset(request, cs);
 
+       /* Check that entire request is less than half the ring */
+       assert_request_valid(request);
+
        return cs;
 }
 
index 8cda1b7..bdb3241 100644 (file)
@@ -315,3 +315,7 @@ int intel_ring_cacheline_align(struct i915_request *rq)
        GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1));
        return 0;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftest_ring.c"
+#endif
index 90a2b9e..85d2bef 100644 (file)
@@ -178,6 +178,12 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
        wa_write_masked_or(wal, reg, set, set);
 }
 
+static void
+wa_write_clr(struct i915_wa_list *wal, i915_reg_t reg, u32 clr)
+{
+       wa_write_masked_or(wal, reg, clr, 0);
+}
+
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
@@ -686,6 +692,227 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq)
        return 0;
 }
 
+static void
+gen4_gt_workarounds_init(struct drm_i915_private *i915,
+                        struct i915_wa_list *wal)
+{
+       /* WaDisable_RenderCache_OperationalFlush:gen4,ilk */
+       wa_masked_dis(wal, CACHE_MODE_0, RC_OP_FLUSH_ENABLE);
+}
+
+static void
+g4x_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       gen4_gt_workarounds_init(i915, wal);
+
+       /* WaDisableRenderCachePipelinedFlush:g4x,ilk */
+       wa_masked_en(wal, CACHE_MODE_0, CM0_PIPELINED_RENDER_FLUSH_DISABLE);
+}
+
+static void
+ilk_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       g4x_gt_workarounds_init(i915, wal);
+
+       wa_masked_en(wal, _3D_CHICKEN2, _3D_CHICKEN2_WM_READ_PIPELINED);
+}
+
+static void
+snb_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableHiZPlanesWhenMSAAEnabled:snb */
+       wa_masked_en(wal,
+                    _3D_CHICKEN,
+                    _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB);
+
+       /* WaDisable_RenderCache_OperationalFlush:snb */
+       wa_masked_dis(wal, CACHE_MODE_0, RC_OP_FLUSH_ENABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal,
+              GEN6_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       wa_masked_dis(wal, CACHE_MODE_0, CM0_STC_EVICT_DISABLE_LRA_SNB);
+
+       wa_masked_en(wal,
+                    _3D_CHICKEN3,
+                    /* WaStripsFansDisableFastClipPerformanceFix:snb */
+                    _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL |
+                    /*
+                     * Bspec says:
+                     * "This bit must be set if 3DSTATE_CLIP clip mode is set
+                     * to normal and 3DSTATE_SF number of SF output attributes
+                     * is more than 16."
+                     */
+                  _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH);
+}
+
+static void
+ivb_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableEarlyCull:ivb */
+       wa_masked_en(wal, _3D_CHICKEN3, _3D_CHICKEN_SF_DISABLE_OBJEND_CULL);
+
+       /* WaDisablePSDDualDispatchEnable:ivb */
+       if (IS_IVB_GT1(i915))
+               wa_masked_en(wal,
+                            GEN7_HALF_SLICE_CHICKEN1,
+                            GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
+
+       /* WaDisable_RenderCache_OperationalFlush:ivb */
+       wa_masked_dis(wal, CACHE_MODE_0_GEN7, RC_OP_FLUSH_ENABLE);
+
+       /* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
+       wa_masked_dis(wal,
+                     GEN7_COMMON_SLICE_CHICKEN1,
+                     GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode:ivb */
+       wa_write(wal, GEN7_L3CNTLREG1, GEN7_WA_FOR_GEN7_L3_CONTROL);
+       wa_write(wal, GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
+
+       /* WaForceL3Serialization:ivb */
+       wa_write_clr(wal, GEN7_L3SQCREG4, L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
+       /*
+        * WaVSThreadDispatchOverride:ivb,vlv
+        *
+        * This actually overrides the dispatch
+        * mode for all thread types.
+        */
+       wa_write_masked_or(wal, GEN7_FF_THREAD_MODE,
+                          GEN7_FF_SCHED_MASK,
+                          GEN7_FF_TS_SCHED_HW |
+                          GEN7_FF_VS_SCHED_HW |
+                          GEN7_FF_DS_SCHED_HW);
+
+       if (0) { /* causes HiZ corruption on ivb:gt1 */
+               /* enable HiZ Raw Stall Optimization */
+               wa_masked_dis(wal, CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+       }
+
+       /* WaDisable4x2SubspanOptimization:ivb */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+}
+
+static void
+vlv_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* WaDisableEarlyCull:vlv */
+       wa_masked_en(wal, _3D_CHICKEN3, _3D_CHICKEN_SF_DISABLE_OBJEND_CULL);
+
+       /* WaPsdDispatchEnable:vlv */
+       /* WaDisablePSDDualDispatchEnable:vlv */
+       wa_masked_en(wal,
+                    GEN7_HALF_SLICE_CHICKEN1,
+                    GEN7_MAX_PS_THREAD_DEP |
+                    GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
+
+       /* WaDisable_RenderCache_OperationalFlush:vlv */
+       wa_masked_dis(wal, CACHE_MODE_0_GEN7, RC_OP_FLUSH_ENABLE);
+
+       /* WaForceL3Serialization:vlv */
+       wa_write_clr(wal, GEN7_L3SQCREG4, L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
+       /*
+        * WaVSThreadDispatchOverride:ivb,vlv
+        *
+        * This actually overrides the dispatch
+        * mode for all thread types.
+        */
+       wa_write_masked_or(wal,
+                          GEN7_FF_THREAD_MODE,
+                          GEN7_FF_SCHED_MASK,
+                          GEN7_FF_TS_SCHED_HW |
+                          GEN7_FF_VS_SCHED_HW |
+                          GEN7_FF_DS_SCHED_HW);
+
+       /*
+        * BSpec says this must be set, even though
+        * WaDisable4x2SubspanOptimization isn't listed for VLV.
+        */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       /*
+        * WaIncreaseL3CreditsForVLVB0:vlv
+        * This is the hardware default actually.
+        */
+       wa_write(wal, GEN7_L3SQCREG1, VLV_B0_WA_L3SQCREG1_VALUE);
+}
+
+static void
+hsw_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+       /* L3 caching of data atomics doesn't work -- disable it. */
+       wa_write(wal, HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
+
+       wa_add(wal,
+              HSW_ROW_CHICKEN3, 0,
+              _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
+               0 /* XXX does this reg exist? */);
+
+       /* WaVSRefCountFullforceMissDisable:hsw */
+       wa_write_clr(wal, GEN7_FF_THREAD_MODE, GEN7_FF_VS_REF_CNT_FFME);
+
+       wa_masked_dis(wal,
+                     CACHE_MODE_0_GEN7,
+                     /* WaDisable_RenderCache_OperationalFlush:hsw */
+                     RC_OP_FLUSH_ENABLE |
+                     /* enable HiZ Raw Stall Optimization */
+                     HIZ_RAW_STALL_OPT_DISABLE);
+
+       /* WaDisable4x2SubspanOptimization:hsw */
+       wa_masked_en(wal, CACHE_MODE_1, PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
+
+       /*
+        * BSpec recommends 8x4 when MSAA is used,
+        * however in practice 16x4 seems fastest.
+        *
+        * Note that PS/WM thread counts depend on the WIZ hashing
+        * disable bit, which we don't touch here, but it's good
+        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
+        */
+       wa_add(wal, GEN7_GT_MODE, 0,
+              _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
+              GEN6_WIZ_HASHING_16x4);
+
+       /* WaSampleCChickenBitEnable:hsw */
+       wa_masked_en(wal, HALF_SLICE_CHICKEN3, HSW_SAMPLE_C_PERFORMANCE);
+}
+
 static void
 gen9_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
@@ -963,6 +1190,20 @@ gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
                bxt_gt_workarounds_init(i915, wal);
        else if (IS_SKYLAKE(i915))
                skl_gt_workarounds_init(i915, wal);
+       else if (IS_HASWELL(i915))
+               hsw_gt_workarounds_init(i915, wal);
+       else if (IS_VALLEYVIEW(i915))
+               vlv_gt_workarounds_init(i915, wal);
+       else if (IS_IVYBRIDGE(i915))
+               ivb_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 6))
+               snb_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 5))
+               ilk_gt_workarounds_init(i915, wal);
+       else if (IS_G4X(i915))
+               g4x_gt_workarounds_init(i915, wal);
+       else if (IS_GEN(i915, 4))
+               gen4_gt_workarounds_init(i915, wal);
        else if (INTEL_GEN(i915) <= 8)
                return;
        else
index 2b2efff..4aa4cc9 100644 (file)
@@ -310,22 +310,20 @@ static bool wait_until_running(struct hang *h, struct i915_request *rq)
                          1000));
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static int igt_hang_sanitycheck(void *arg)
@@ -473,7 +471,6 @@ static int igt_reset_nop_engine(void *arg)
        for_each_engine(engine, gt, id) {
                unsigned int reset_count, reset_engine_count, count;
                struct intel_context *ce;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
                int err;
 
@@ -485,7 +482,7 @@ static int igt_reset_nop_engine(void *arg)
                reset_engine_count = i915_reset_engine_count(global, engine);
                count = 0;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        int i;
@@ -529,7 +526,7 @@ static int igt_reset_nop_engine(void *arg)
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s(%s): %d resets\n", __func__, engine->name, count);
 
@@ -564,7 +561,6 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
 
        for_each_engine(engine, gt, id) {
                unsigned int reset_count, reset_engine_count;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
 
                if (active && !intel_engine_can_store_dword(engine))
@@ -580,7 +576,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
                reset_count = i915_reset_count(global);
                reset_engine_count = i915_reset_engine_count(global, engine);
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        if (active) {
@@ -632,7 +628,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                if (err)
                        break;
@@ -789,7 +785,6 @@ static int __igt_reset_engines(struct intel_gt *gt,
                struct active_engine threads[I915_NUM_ENGINES] = {};
                unsigned long device = i915_reset_count(global);
                unsigned long count = 0, reported;
-               unsigned long heartbeat;
                IGT_TIMEOUT(end_time);
 
                if (flags & TEST_ACTIVE &&
@@ -832,7 +827,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
 
                yield(); /* start all threads before we begin */
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
                do {
                        struct i915_request *rq = NULL;
@@ -906,7 +901,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
                        }
                } while (time_before(jiffies, end_time));
                clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("i915_reset_engine(%s:%s): %lu resets\n",
                        engine->name, test_name, count);
index 824f99c..924bc01 100644 (file)
@@ -51,22 +51,20 @@ static struct i915_vma *create_scratch(struct intel_gt *gt)
        return vma;
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static bool is_active(struct i915_request *rq)
@@ -224,7 +222,6 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                struct intel_context *ce[2] = {};
                struct i915_request *rq[2];
                struct igt_live_test t;
-               unsigned long saved;
                int n;
 
                if (prio && !intel_engine_has_preemption(engine))
@@ -237,7 +234,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                        err = -EIO;
                        break;
                }
-               engine_heartbeat_disable(engine, &saved);
+               engine_heartbeat_disable(engine);
 
                for (n = 0; n < ARRAY_SIZE(ce); n++) {
                        struct intel_context *tmp;
@@ -345,7 +342,7 @@ err_ce:
                        intel_context_put(ce[n]);
                }
 
-               engine_heartbeat_enable(engine, saved);
+               engine_heartbeat_enable(engine);
                if (igt_live_test_end(&t))
                        err = -EIO;
                if (err)
@@ -466,7 +463,6 @@ static int live_hold_reset(void *arg)
 
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
-               unsigned long heartbeat;
                struct i915_request *rq;
 
                ce = intel_context_create(engine);
@@ -475,7 +471,7 @@ static int live_hold_reset(void *arg)
                        break;
                }
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
                if (IS_ERR(rq)) {
@@ -535,7 +531,7 @@ static int live_hold_reset(void *arg)
                i915_request_put(rq);
 
 out:
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                intel_context_put(ce);
                if (err)
                        break;
@@ -580,10 +576,9 @@ static int live_error_interrupt(void *arg)
 
        for_each_engine(engine, gt, id) {
                const struct error_phase *p;
-               unsigned long heartbeat;
                int err = 0;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                for (p = phases; p->error[0] != GOOD; p++) {
                        struct i915_request *client[ARRAY_SIZE(phases->error)];
@@ -682,7 +677,7 @@ out:
                        }
                }
 
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (err) {
                        intel_gt_set_wedged(gt);
                        return err;
@@ -828,7 +823,7 @@ slice_semaphore_queue(struct intel_engine_cs *outer,
                }
        }
 
-       err = release_queue(outer, vma, n, INT_MAX);
+       err = release_queue(outer, vma, n, I915_PRIORITY_BARRIER);
        if (err)
                goto out;
 
@@ -895,16 +890,14 @@ static int live_timeslice_preempt(void *arg)
                enum intel_engine_id id;
 
                for_each_engine(engine, gt, id) {
-                       unsigned long saved;
-
                        if (!intel_engine_has_preemption(engine))
                                continue;
 
                        memset(vaddr, 0, PAGE_SIZE);
 
-                       engine_heartbeat_disable(engine, &saved);
+                       engine_heartbeat_disable(engine);
                        err = slice_semaphore_queue(engine, vma, count);
-                       engine_heartbeat_enable(engine, saved);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto err_pin;
 
@@ -1009,7 +1002,6 @@ static int live_timeslice_rewind(void *arg)
                enum { X = 1, Z, Y };
                struct i915_request *rq[3] = {};
                struct intel_context *ce;
-               unsigned long heartbeat;
                unsigned long timeslice;
                int i, err = 0;
                u32 *slot;
@@ -1028,7 +1020,7 @@ static int live_timeslice_rewind(void *arg)
                 * Expect execution/evaluation order XZY
                 */
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
 
                slot = memset32(engine->status_page.addr + 1000, 0, 4);
@@ -1122,7 +1114,7 @@ err:
                wmb();
 
                engine->props.timeslice_duration_ms = timeslice;
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                for (i = 0; i < 3; i++)
                        i915_request_put(rq[i]);
                if (igt_flush_test(gt->i915))
@@ -1202,12 +1194,11 @@ static int live_timeslice_queue(void *arg)
                        .priority = I915_USER_PRIORITY(I915_PRIORITY_MAX),
                };
                struct i915_request *rq, *nop;
-               unsigned long saved;
 
                if (!intel_engine_has_preemption(engine))
                        continue;
 
-               engine_heartbeat_disable(engine, &saved);
+               engine_heartbeat_disable(engine);
                memset(vaddr, 0, PAGE_SIZE);
 
                /* ELSP[0]: semaphore wait */
@@ -1284,7 +1275,7 @@ static int live_timeslice_queue(void *arg)
 err_rq:
                i915_request_put(rq);
 err_heartbeat:
-               engine_heartbeat_enable(engine, saved);
+               engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
@@ -1298,6 +1289,121 @@ err_obj:
        return err;
 }
 
+static int live_timeslice_nopreempt(void *arg)
+{
+       struct intel_gt *gt = arg;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       struct igt_spinner spin;
+       int err = 0;
+
+       /*
+        * We should not timeslice into a request that is marked with
+        * I915_REQUEST_NOPREEMPT.
+        */
+       if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
+               return 0;
+
+       if (igt_spinner_init(&spin, gt))
+               return -ENOMEM;
+
+       for_each_engine(engine, gt, id) {
+               struct intel_context *ce;
+               struct i915_request *rq;
+               unsigned long timeslice;
+
+               if (!intel_engine_has_preemption(engine))
+                       continue;
+
+               ce = intel_context_create(engine);
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(ce);
+                       break;
+               }
+
+               engine_heartbeat_disable(engine);
+               timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
+
+               /* Create an unpreemptible spinner */
+
+               rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
+               intel_context_put(ce);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       goto out_heartbeat;
+               }
+
+               i915_request_get(rq);
+               i915_request_add(rq);
+
+               if (!igt_wait_for_spinner(&spin, rq)) {
+                       i915_request_put(rq);
+                       err = -ETIME;
+                       goto out_spin;
+               }
+
+               set_bit(I915_FENCE_FLAG_NOPREEMPT, &rq->fence.flags);
+               i915_request_put(rq);
+
+               /* Followed by a maximum priority barrier (heartbeat) */
+
+               ce = intel_context_create(engine);
+               if (IS_ERR(ce)) {
+                       err = PTR_ERR(rq);
+                       goto out_spin;
+               }
+
+               rq = intel_context_create_request(ce);
+               intel_context_put(ce);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       goto out_spin;
+               }
+
+               rq->sched.attr.priority = I915_PRIORITY_BARRIER;
+               i915_request_get(rq);
+               i915_request_add(rq);
+
+               /*
+                * Wait until the barrier is in ELSP, and we know timeslicing
+                * will have been activated.
+                */
+               if (wait_for_submit(engine, rq, HZ / 2)) {
+                       i915_request_put(rq);
+                       err = -ETIME;
+                       goto out_spin;
+               }
+
+               /*
+                * Since the ELSP[0] request is unpreemptible, it should not
+                * allow the maximum priority barrier through. Wait long
+                * enough to see if it is timesliced in by mistake.
+                */
+               if (i915_request_wait(rq, 0, timeslice_threshold(engine)) >= 0) {
+                       pr_err("%s: I915_PRIORITY_BARRIER request completed, bypassing no-preempt request\n",
+                              engine->name);
+                       err = -EINVAL;
+               }
+               i915_request_put(rq);
+
+out_spin:
+               igt_spinner_end(&spin);
+out_heartbeat:
+               xchg(&engine->props.timeslice_duration_ms, timeslice);
+               engine_heartbeat_enable(engine);
+               if (err)
+                       break;
+
+               if (igt_flush_test(gt->i915)) {
+                       err = -EIO;
+                       break;
+               }
+       }
+
+       igt_spinner_fini(&spin);
+       return err;
+}
+
 static int live_busywait_preempt(void *arg)
 {
        struct intel_gt *gt = arg;
@@ -4153,7 +4259,6 @@ static int reset_virtual_engine(struct intel_gt *gt,
 {
        struct intel_engine_cs *engine;
        struct intel_context *ve;
-       unsigned long *heartbeat;
        struct igt_spinner spin;
        struct i915_request *rq;
        unsigned int n;
@@ -4165,15 +4270,9 @@ static int reset_virtual_engine(struct intel_gt *gt,
         * descendents are not executed while the capture is in progress.
         */
 
-       heartbeat = kmalloc_array(nsibling, sizeof(*heartbeat), GFP_KERNEL);
-       if (!heartbeat)
+       if (igt_spinner_init(&spin, gt))
                return -ENOMEM;
 
-       if (igt_spinner_init(&spin, gt)) {
-               err = -ENOMEM;
-               goto out_free;
-       }
-
        ve = intel_execlists_create_virtual(siblings, nsibling);
        if (IS_ERR(ve)) {
                err = PTR_ERR(ve);
@@ -4181,7 +4280,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
        }
 
        for (n = 0; n < nsibling; n++)
-               engine_heartbeat_disable(siblings[n], &heartbeat[n]);
+               engine_heartbeat_disable(siblings[n]);
 
        rq = igt_spinner_create_request(&spin, ve, MI_ARB_CHECK);
        if (IS_ERR(rq)) {
@@ -4252,13 +4351,11 @@ out_rq:
        i915_request_put(rq);
 out_heartbeat:
        for (n = 0; n < nsibling; n++)
-               engine_heartbeat_enable(siblings[n], heartbeat[n]);
+               engine_heartbeat_enable(siblings[n]);
 
        intel_context_put(ve);
 out_spin:
        igt_spinner_fini(&spin);
-out_free:
-       kfree(heartbeat);
        return err;
 }
 
@@ -4314,6 +4411,7 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
                SUBTEST(live_timeslice_preempt),
                SUBTEST(live_timeslice_rewind),
                SUBTEST(live_timeslice_queue),
+               SUBTEST(live_timeslice_nopreempt),
                SUBTEST(live_busywait_preempt),
                SUBTEST(live_preempt),
                SUBTEST(live_late_preempt),
@@ -4932,9 +5030,7 @@ static int live_lrc_gpr(void *arg)
                return PTR_ERR(scratch);
 
        for_each_engine(engine, gt, id) {
-               unsigned long heartbeat;
-
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
 
                err = __live_lrc_gpr(engine, scratch, false);
                if (err)
@@ -4945,7 +5041,7 @@ static int live_lrc_gpr(void *arg)
                        goto err;
 
 err:
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -5092,10 +5188,9 @@ static int live_lrc_timestamp(void *arg)
         */
 
        for_each_engine(data.engine, gt, id) {
-               unsigned long heartbeat;
                int i, err = 0;
 
-               engine_heartbeat_disable(data.engine, &heartbeat);
+               engine_heartbeat_disable(data.engine);
 
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        struct intel_context *tmp;
@@ -5128,7 +5223,7 @@ static int live_lrc_timestamp(void *arg)
                }
 
 err:
-               engine_heartbeat_enable(data.engine, heartbeat);
+               engine_heartbeat_enable(data.engine);
                for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
                        if (!data.ce[i])
                                break;
index 8831ffe..63f87d8 100644 (file)
@@ -18,6 +18,20 @@ struct live_mocs {
        void *vaddr;
 };
 
+static struct intel_context *mocs_context_create(struct intel_engine_cs *engine)
+{
+       struct intel_context *ce;
+
+       ce = intel_context_create(engine);
+       if (IS_ERR(ce))
+               return ce;
+
+       /* We build large requests to read the registers from the ring */
+       ce->ring = __intel_context_ring_size(SZ_16K);
+
+       return ce;
+}
+
 static int request_add_sync(struct i915_request *rq, int err)
 {
        i915_request_get(rq);
@@ -301,7 +315,7 @@ static int live_mocs_clean(void *arg)
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
 
-               ce = intel_context_create(engine);
+               ce = mocs_context_create(engine);
                if (IS_ERR(ce)) {
                        err = PTR_ERR(ce);
                        break;
@@ -395,7 +409,7 @@ static int live_mocs_reset(void *arg)
        for_each_engine(engine, gt, id) {
                struct intel_context *ce;
 
-               ce = intel_context_create(engine);
+               ce = mocs_context_create(engine);
                if (IS_ERR(ce)) {
                        err = PTR_ERR(ce);
                        break;
diff --git a/drivers/gpu/drm/i915/gt/selftest_ring.c b/drivers/gpu/drm/i915/gt/selftest_ring.c
new file mode 100644 (file)
index 0000000..2a8c534
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright Â© 2020 Intel Corporation
+ */
+
+static struct intel_ring *mock_ring(unsigned long sz)
+{
+       struct intel_ring *ring;
+
+       ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
+       if (!ring)
+               return NULL;
+
+       kref_init(&ring->ref);
+       ring->size = sz;
+       ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(sz);
+       ring->effective_size = sz;
+       ring->vaddr = (void *)(ring + 1);
+       atomic_set(&ring->pin_count, 1);
+
+       intel_ring_update_space(ring);
+
+       return ring;
+}
+
+static void mock_ring_free(struct intel_ring *ring)
+{
+       kfree(ring);
+}
+
+static int check_ring_direction(struct intel_ring *ring,
+                               u32 next, u32 prev,
+                               int expected)
+{
+       int result;
+
+       result = intel_ring_direction(ring, next, prev);
+       if (result < 0)
+               result = -1;
+       else if (result > 0)
+               result = 1;
+
+       if (result != expected) {
+               pr_err("intel_ring_direction(%u, %u):%d != %d\n",
+                      next, prev, result, expected);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int check_ring_step(struct intel_ring *ring, u32 x, u32 step)
+{
+       u32 prev = x, next = intel_ring_wrap(ring, x + step);
+       int err = 0;
+
+       err |= check_ring_direction(ring, next, next,  0);
+       err |= check_ring_direction(ring, prev, prev,  0);
+       err |= check_ring_direction(ring, next, prev,  1);
+       err |= check_ring_direction(ring, prev, next, -1);
+
+       return err;
+}
+
+static int check_ring_offset(struct intel_ring *ring, u32 x, u32 step)
+{
+       int err = 0;
+
+       err |= check_ring_step(ring, x, step);
+       err |= check_ring_step(ring, intel_ring_wrap(ring, x + 1), step);
+       err |= check_ring_step(ring, intel_ring_wrap(ring, x - 1), step);
+
+       return err;
+}
+
+static int igt_ring_direction(void *dummy)
+{
+       struct intel_ring *ring;
+       unsigned int half = 2048;
+       int step, err = 0;
+
+       ring = mock_ring(2 * half);
+       if (!ring)
+               return -ENOMEM;
+
+       GEM_BUG_ON(ring->size != 2 * half);
+
+       /* Precision of wrap detection is limited to ring->size / 2 */
+       for (step = 1; step < half; step <<= 1) {
+               err |= check_ring_offset(ring, 0, step);
+               err |= check_ring_offset(ring, half, step);
+       }
+       err |= check_ring_step(ring, 0, half - 64);
+
+       /* And check unwrapped handling for good measure */
+       err |= check_ring_offset(ring, 0, 2 * half + 64);
+       err |= check_ring_offset(ring, 3 * half, 1);
+
+       mock_ring_free(ring);
+       return err;
+}
+
+int intel_ring_mock_selftests(void)
+{
+       static const struct i915_subtest tests[] = {
+               SUBTEST(igt_ring_direction),
+       };
+
+       return i915_subtests(tests, NULL);
+}
index 6275d69..5049c3d 100644 (file)
 /* Try to isolate the impact of cstates from determing frequency response */
 #define CPU_LATENCY 0 /* -1 to disable pm_qos, 0 to disable cstates */
 
-static unsigned long engine_heartbeat_disable(struct intel_engine_cs *engine)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       unsigned long old;
-
-       old = fetch_and_zero(&engine->props.heartbeat_interval_ms);
+       engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
-
-       return old;
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static void dummy_rps_work(struct work_struct *wrk)
@@ -246,7 +242,6 @@ int live_rps_clock_interval(void *arg)
        intel_gt_check_clock_frequency(gt);
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                u32 cycles;
                u64 dt;
@@ -254,13 +249,13 @@ int live_rps_clock_interval(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
@@ -271,7 +266,7 @@ int live_rps_clock_interval(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -327,7 +322,7 @@ int live_rps_clock_interval(void *arg)
                intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                if (err == 0) {
                        u64 time = intel_gt_pm_interval_to_ns(gt, cycles);
@@ -405,7 +400,6 @@ int live_rps_control(void *arg)
 
        intel_gt_pm_get(gt);
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                ktime_t min_dt, max_dt;
                int f, limit;
@@ -414,7 +408,7 @@ int live_rps_control(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
@@ -430,7 +424,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -440,7 +434,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: could not set minimum frequency [%x], only %x!\n",
                               engine->name, rps->min_freq, read_cagf(rps));
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
@@ -457,7 +451,7 @@ int live_rps_control(void *arg)
                        pr_err("%s: could not restore minimum frequency [%x], only %x!\n",
                               engine->name, rps->min_freq, read_cagf(rps));
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        show_pstate_limits(rps);
                        err = -EINVAL;
                        break;
@@ -472,7 +466,7 @@ int live_rps_control(void *arg)
                min_dt = ktime_sub(ktime_get(), min_dt);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s: range:[%x:%uMHz, %x:%uMHz] limit:[%x:%uMHz], %x:%x response %lluns:%lluns\n",
                        engine->name,
@@ -635,7 +629,6 @@ int live_rps_frequency_cs(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct i915_vma *vma;
                u32 *cancel, *cntr;
@@ -644,14 +637,14 @@ int live_rps_frequency_cs(void *arg)
                        int freq;
                } min, max;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                vma = create_spin_counter(engine,
                                          engine->kernel_context->vm, false,
                                          &cancel, &cntr);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        break;
                }
 
@@ -732,7 +725,7 @@ err_vma:
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -778,7 +771,6 @@ int live_rps_frequency_srm(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct i915_vma *vma;
                u32 *cancel, *cntr;
@@ -787,14 +779,14 @@ int live_rps_frequency_srm(void *arg)
                        int freq;
                } min, max;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                vma = create_spin_counter(engine,
                                          engine->kernel_context->vm, true,
                                          &cancel, &cntr);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        break;
                }
 
@@ -874,7 +866,7 @@ err_vma:
                i915_vma_unpin(vma);
                i915_vma_put(vma);
 
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
                if (igt_flush_test(gt->i915))
                        err = -EIO;
                if (err)
@@ -1066,16 +1058,14 @@ int live_rps_interrupt(void *arg)
        for_each_engine(engine, gt, id) {
                /* Keep the engine busy with a spinner; expect an UP! */
                if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
-                       unsigned long saved_heartbeat;
-
                        intel_gt_pm_wait_for_idle(engine->gt);
                        GEM_BUG_ON(intel_rps_is_active(rps));
 
-                       saved_heartbeat = engine_heartbeat_disable(engine);
+                       engine_heartbeat_disable(engine);
 
                        err = __rps_up_interrupt(rps, engine, &spin);
 
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
 
@@ -1084,15 +1074,13 @@ int live_rps_interrupt(void *arg)
 
                /* Keep the engine awake but idle and check for DOWN */
                if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
-                       unsigned long saved_heartbeat;
-
-                       saved_heartbeat = engine_heartbeat_disable(engine);
+                       engine_heartbeat_disable(engine);
                        intel_rc6_disable(&gt->rc6);
 
                        err = __rps_down_interrupt(rps, engine);
 
                        intel_rc6_enable(&gt->rc6);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        if (err)
                                goto out;
                }
@@ -1168,7 +1156,6 @@ int live_rps_power(void *arg)
        rps->work.func = dummy_rps_work;
 
        for_each_engine(engine, gt, id) {
-               unsigned long saved_heartbeat;
                struct i915_request *rq;
                struct {
                        u64 power;
@@ -1178,13 +1165,13 @@ int live_rps_power(void *arg)
                if (!intel_engine_can_store_dword(engine))
                        continue;
 
-               saved_heartbeat = engine_heartbeat_disable(engine);
+               engine_heartbeat_disable(engine);
 
                rq = igt_spinner_create_request(&spin,
                                                engine->kernel_context,
                                                MI_NOOP);
                if (IS_ERR(rq)) {
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        err = PTR_ERR(rq);
                        break;
                }
@@ -1195,7 +1182,7 @@ int live_rps_power(void *arg)
                        pr_err("%s: RPS spinner did not start\n",
                               engine->name);
                        igt_spinner_end(&spin);
-                       engine_heartbeat_enable(engine, saved_heartbeat);
+                       engine_heartbeat_enable(engine);
                        intel_gt_set_wedged(engine->gt);
                        err = -EIO;
                        break;
@@ -1208,7 +1195,7 @@ int live_rps_power(void *arg)
                min.power = measure_power_at(rps, &min.freq);
 
                igt_spinner_end(&spin);
-               engine_heartbeat_enable(engine, saved_heartbeat);
+               engine_heartbeat_enable(engine);
 
                pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
                        engine->name,
index c2578a0..ef1c350 100644 (file)
@@ -751,22 +751,20 @@ out_free:
        return err;
 }
 
-static void engine_heartbeat_disable(struct intel_engine_cs *engine,
-                                    unsigned long *saved)
+static void engine_heartbeat_disable(struct intel_engine_cs *engine)
 {
-       *saved = engine->props.heartbeat_interval_ms;
        engine->props.heartbeat_interval_ms = 0;
 
        intel_engine_pm_get(engine);
        intel_engine_park_heartbeat(engine);
 }
 
-static void engine_heartbeat_enable(struct intel_engine_cs *engine,
-                                   unsigned long saved)
+static void engine_heartbeat_enable(struct intel_engine_cs *engine)
 {
        intel_engine_pm_put(engine);
 
-       engine->props.heartbeat_interval_ms = saved;
+       engine->props.heartbeat_interval_ms =
+               engine->defaults.heartbeat_interval_ms;
 }
 
 static int live_hwsp_rollover_kernel(void *arg)
@@ -785,10 +783,9 @@ static int live_hwsp_rollover_kernel(void *arg)
                struct intel_context *ce = engine->kernel_context;
                struct intel_timeline *tl = ce->timeline;
                struct i915_request *rq[3] = {};
-               unsigned long heartbeat;
                int i;
 
-               engine_heartbeat_disable(engine, &heartbeat);
+               engine_heartbeat_disable(engine);
                if (intel_gt_wait_for_idle(gt, HZ / 2)) {
                        err = -EIO;
                        goto out;
@@ -839,7 +836,7 @@ static int live_hwsp_rollover_kernel(void *arg)
 out:
                for (i = 0; i < ARRAY_SIZE(rq); i++)
                        i915_request_put(rq[i]);
-               engine_heartbeat_enable(engine, heartbeat);
+               engine_heartbeat_enable(engine);
                if (err)
                        break;
        }
index 5ed3232..3278546 100644 (file)
@@ -623,6 +623,8 @@ err_request:
                                err = -EINVAL;
                                goto out_unpin;
                        }
+               } else {
+                       rsvd = 0;
                }
 
                expect = results[0];
index 4dc601d..284cf07 100644 (file)
@@ -3125,6 +3125,7 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
 
        val = I915_READ(GEN11_DE_HPD_IMR);
        val &= ~hotplug_irqs;
+       val |= ~enabled_irqs & hotplug_irqs;
        I915_WRITE(GEN11_DE_HPD_IMR, val);
        POSTING_READ(GEN11_DE_HPD_IMR);
 
index e991a70..962ded9 100644 (file)
@@ -269,12 +269,48 @@ static bool exclusive_mmio_access(const struct drm_i915_private *i915)
        return IS_GEN(i915, 7);
 }
 
+static void engine_sample(struct intel_engine_cs *engine, unsigned int period_ns)
+{
+       struct intel_engine_pmu *pmu = &engine->pmu;
+       bool busy;
+       u32 val;
+
+       val = ENGINE_READ_FW(engine, RING_CTL);
+       if (val == 0) /* powerwell off => engine idle */
+               return;
+
+       if (val & RING_WAIT)
+               add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
+       if (val & RING_WAIT_SEMAPHORE)
+               add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
+
+       /* No need to sample when busy stats are supported. */
+       if (intel_engine_supports_stats(engine))
+               return;
+
+       /*
+        * While waiting on a semaphore or event, MI_MODE reports the
+        * ring as idle. However, previously using the seqno, and with
+        * execlists sampling, we account for the ring waiting as the
+        * engine being busy. Therefore, we record the sample as being
+        * busy if either waiting or !idle.
+        */
+       busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
+       if (!busy) {
+               val = ENGINE_READ_FW(engine, RING_MI_MODE);
+               busy = !(val & MODE_IDLE);
+       }
+       if (busy)
+               add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
+}
+
 static void
 engines_sample(struct intel_gt *gt, unsigned int period_ns)
 {
        struct drm_i915_private *i915 = gt->i915;
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       unsigned long flags;
 
        if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
                return;
@@ -283,53 +319,17 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns)
                return;
 
        for_each_engine(engine, gt, id) {
-               struct intel_engine_pmu *pmu = &engine->pmu;
-               spinlock_t *mmio_lock;
-               unsigned long flags;
-               bool busy;
-               u32 val;
-
                if (!intel_engine_pm_get_if_awake(engine))
                        continue;
 
-               mmio_lock = NULL;
-               if (exclusive_mmio_access(i915))
-                       mmio_lock = &engine->uncore->lock;
-
-               if (unlikely(mmio_lock))
-                       spin_lock_irqsave(mmio_lock, flags);
-
-               val = ENGINE_READ_FW(engine, RING_CTL);
-               if (val == 0) /* powerwell off => engine idle */
-                       goto skip;
-
-               if (val & RING_WAIT)
-                       add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
-               if (val & RING_WAIT_SEMAPHORE)
-                       add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
-
-               /* No need to sample when busy stats are supported. */
-               if (intel_engine_supports_stats(engine))
-                       goto skip;
-
-               /*
-                * While waiting on a semaphore or event, MI_MODE reports the
-                * ring as idle. However, previously using the seqno, and with
-                * execlists sampling, we account for the ring waiting as the
-                * engine being busy. Therefore, we record the sample as being
-                * busy if either waiting or !idle.
-                */
-               busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
-               if (!busy) {
-                       val = ENGINE_READ_FW(engine, RING_MI_MODE);
-                       busy = !(val & MODE_IDLE);
+               if (exclusive_mmio_access(i915)) {
+                       spin_lock_irqsave(&engine->uncore->lock, flags);
+                       engine_sample(engine, period_ns);
+                       spin_unlock_irqrestore(&engine->uncore->lock, flags);
+               } else {
+                       engine_sample(engine, period_ns);
                }
-               if (busy)
-                       add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
 
-skip:
-               if (unlikely(mmio_lock))
-                       spin_unlock_irqrestore(mmio_lock, flags);
                intel_engine_pm_put_async(engine);
        }
 }
index 5003a71..8aa7866 100644 (file)
@@ -42,7 +42,7 @@ enum {
  * active request.
  */
 #define I915_PRIORITY_UNPREEMPTABLE INT_MAX
-#define I915_PRIORITY_BARRIER INT_MAX
+#define I915_PRIORITY_BARRIER (I915_PRIORITY_UNPREEMPTABLE - 1)
 
 struct i915_priolist {
        struct list_head requests[I915_PRIORITY_COUNT];
index 7717581..06cd1d2 100644 (file)
@@ -7896,7 +7896,7 @@ enum {
 
 /* GEN7 chicken */
 #define GEN7_COMMON_SLICE_CHICKEN1             _MMIO(0x7010)
-  #define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC    ((1 << 10) | (1 << 26))
+  #define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC    (1 << 10)
   #define GEN9_RHWO_OPTIMIZATION_DISABLE       (1 << 14)
 
 #define COMMON_SLICE_CHICKEN2                                  _MMIO(0x7014)
index 696491d..07f663c 100644 (file)
@@ -6830,16 +6830,6 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(ILK_DISPLAY_CHICKEN2,
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
-       I915_WRITE(_3D_CHICKEN2,
-                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
-                  _3D_CHICKEN2_WM_READ_PIPELINED);
-
-       /* WaDisableRenderCachePipelinedFlush:ilk */
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:ilk */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 
        g4x_disable_trickle_feed(dev_priv);
 
@@ -6902,27 +6892,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
 
-       /* WaDisableHiZPlanesWhenMSAAEnabled:snb */
-       I915_WRITE(_3D_CHICKEN,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB));
-
-       /* WaDisable_RenderCache_OperationalFlush:snb */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /*
-        * BSpec recoomends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN6_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
-
        I915_WRITE(GEN6_UCGCTL1,
                   I915_READ(GEN6_UCGCTL1) |
                   GEN6_BLBUNIT_CLOCK_GATE_DISABLE |
@@ -6945,18 +6914,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
                   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
-       /* WaStripsFansDisableFastClipPerformanceFix:snb */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL));
-
-       /*
-        * Bspec says:
-        * "This bit must be set if 3DSTATE_CLIP clip mode is set to normal and
-        * 3DSTATE_SF number of SF output attributes is more than 16."
-        */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH));
-
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
@@ -6986,24 +6943,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
        gen6_check_mch_setup(dev_priv);
 }
 
-static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
-{
-       u32 reg = I915_READ(GEN7_FF_THREAD_MODE);
-
-       /*
-        * WaVSThreadDispatchOverride:ivb,vlv
-        *
-        * This actually overrides the dispatch
-        * mode for all thread types.
-        */
-       reg &= ~GEN7_FF_SCHED_MASK;
-       reg |= GEN7_FF_TS_SCHED_HW;
-       reg |= GEN7_FF_VS_SCHED_HW;
-       reg |= GEN7_FF_DS_SCHED_HW;
-
-       I915_WRITE(GEN7_FF_THREAD_MODE, reg);
-}
-
 static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
        /*
@@ -7230,45 +7169,10 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       /* L3 caching of data atomics doesn't work -- disable it. */
-       I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
-       I915_WRITE(HSW_ROW_CHICKEN3,
-                  _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE));
-
        /* This is required by WaCatErrorRejectionIssue:hsw */
        I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
-                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
-                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
-
-       /* WaVSRefCountFullforceMissDisable:hsw */
-       I915_WRITE(GEN7_FF_THREAD_MODE,
-                  I915_READ(GEN7_FF_THREAD_MODE) & ~GEN7_FF_VS_REF_CNT_FFME);
-
-       /* WaDisable_RenderCache_OperationalFlush:hsw */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* enable HiZ Raw Stall Optimization */
-       I915_WRITE(CACHE_MODE_0_GEN7,
-                  _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
-
-       /* WaDisable4x2SubspanOptimization:hsw */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       /* WaSampleCChickenBitEnable:hsw */
-       I915_WRITE(HALF_SLICE_CHICKEN3,
-                  _MASKED_BIT_ENABLE(HSW_SAMPLE_C_PERFORMANCE));
+                  I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
        /* WaSwitchSolVfFArbitrationPriority:hsw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -7282,32 +7186,11 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
-       /* WaDisableEarlyCull:ivb */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
-
        /* WaDisableBackToBackFlipFix:ivb */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
-       /* WaDisablePSDDualDispatchEnable:ivb */
-       if (IS_IVB_GT1(dev_priv))
-               I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
-                          _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:ivb */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
-       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
-                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
-
-       /* WaApplyL3ControlAndL3ChickenMode:ivb */
-       I915_WRITE(GEN7_L3CNTLREG1,
-                       GEN7_WA_FOR_GEN7_L3_CONTROL);
-       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
-                  GEN7_WA_L3_CHICKEN_MODE);
        if (IS_IVB_GT1(dev_priv))
                I915_WRITE(GEN7_ROW_CHICKEN2,
                           _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
@@ -7319,10 +7202,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
                           _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
        }
 
-       /* WaForceL3Serialization:ivb */
-       I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
-                  ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
-
        /*
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:ivb workaround.
@@ -7337,29 +7216,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
        g4x_disable_trickle_feed(dev_priv);
 
-       gen7_setup_fixed_func_scheduler(dev_priv);
-
-       if (0) { /* causes HiZ corruption on ivb:gt1 */
-               /* enable HiZ Raw Stall Optimization */
-               I915_WRITE(CACHE_MODE_0_GEN7,
-                          _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
-       }
-
-       /* WaDisable4x2SubspanOptimization:ivb */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
        snpcr &= ~GEN6_MBC_SNPCR_MASK;
        snpcr |= GEN6_MBC_SNPCR_MED;
@@ -7373,28 +7229,11 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       /* WaDisableEarlyCull:vlv */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
-
        /* WaDisableBackToBackFlipFix:vlv */
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
-       /* WaPsdDispatchEnable:vlv */
-       /* WaDisablePSDDualDispatchEnable:vlv */
-       I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
-                  _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
-                                     GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:vlv */
-       I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
-       /* WaForceL3Serialization:vlv */
-       I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
-                  ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
-
        /* WaDisableDopClockGating:vlv */
        I915_WRITE(GEN7_ROW_CHICKEN2,
                   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
@@ -7404,8 +7243,6 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
                   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
                   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
-       gen7_setup_fixed_func_scheduler(dev_priv);
-
        /*
         * According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:vlv workaround.
@@ -7419,30 +7256,6 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(GEN7_UCGCTL4,
                   I915_READ(GEN7_UCGCTL4) | GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
 
-       /*
-        * BSpec says this must be set, even though
-        * WaDisable4x2SubspanOptimization isn't listed for VLV.
-        */
-       I915_WRITE(CACHE_MODE_1,
-                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       I915_WRITE(GEN7_GT_MODE,
-                  _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
-
-       /*
-        * WaIncreaseL3CreditsForVLVB0:vlv
-        * This is the hardware default actually.
-        */
-       I915_WRITE(GEN7_L3SQCREG1, VLV_B0_WA_L3SQCREG1_VALUE);
-
        /*
         * WaDisableVLVClockGating_VBIIssue:vlv
         * Disable clock gating on th GCFG unit to prevent a delay
@@ -7495,13 +7308,6 @@ static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
                dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
        I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
 
-       /* WaDisableRenderCachePipelinedFlush */
-       I915_WRITE(CACHE_MODE_0,
-                  _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:g4x */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
-
        g4x_disable_trickle_feed(dev_priv);
 }
 
@@ -7517,11 +7323,6 @@ static void i965gm_init_clock_gating(struct drm_i915_private *dev_priv)
        intel_uncore_write(uncore,
                           MI_ARB_STATE,
                           _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:gen4 */
-       intel_uncore_write(uncore,
-                          CACHE_MODE_0,
-                          _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void i965g_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -7534,9 +7335,6 @@ static void i965g_init_clock_gating(struct drm_i915_private *dev_priv)
        I915_WRITE(RENCLK_GATE_D2, 0);
        I915_WRITE(MI_ARB_STATE,
                   _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
-
-       /* WaDisable_RenderCache_OperationalFlush:gen4 */
-       I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void gen3_init_clock_gating(struct drm_i915_private *dev_priv)
index 6a2be7d..6090ce3 100644 (file)
@@ -21,6 +21,7 @@ selftest(fence, i915_sw_fence_mock_selftests)
 selftest(scatterlist, scatterlist_mock_selftests)
 selftest(syncmap, i915_syncmap_mock_selftests)
 selftest(uncore, intel_uncore_mock_selftests)
+selftest(ring, intel_ring_mock_selftests)
 selftest(engine, intel_engine_cs_mock_selftests)
 selftest(timelines, intel_timeline_mock_selftests)
 selftest(requests, i915_request_mock_selftests)
index 4f932a4..603b4a9 100644 (file)
@@ -34,7 +34,7 @@ struct stp_policy_node {
        unsigned int            first_channel;
        unsigned int            last_channel;
        /* this is the one that's exposed to the attributes */
-       unsigned char           priv[0];
+       unsigned char           priv[];
 };
 
 void *stp_policy_node_priv(struct stp_policy_node *pn)
index 3569439..a9be49f 100644 (file)
@@ -23,7 +23,7 @@ void *stp_policy_node_priv(struct stp_policy_node *pn);
 
 struct stp_master {
        unsigned int    nr_free;
-       unsigned long   chan_map[0];
+       unsigned long   chan_map[];
 };
 
 struct stm_device {
@@ -42,7 +42,7 @@ struct stm_device {
        const struct config_item_type           *pdrv_node_type;
        /* master allocation */
        spinlock_t              mc_lock;
-       struct stp_master       *masters[0];
+       struct stp_master       *masters[];
 };
 
 #define to_stm_device(_d)                              \
index 6542523..13eacf6 100644 (file)
@@ -1021,7 +1021,7 @@ static int __init hp_sdc_register(void)
        hp_sdc.base_io   = (unsigned long) 0xf0428000;
        hp_sdc.data_io   = (unsigned long) hp_sdc.base_io + 1;
        hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
-       if (!probe_kernel_read(&i, (unsigned char *)hp_sdc.data_io, 1))
+       if (!copy_from_kernel_nofault(&i, (unsigned char *)hp_sdc.data_io, 1))
                hp_sdc.dev = (void *)1;
        hp_sdc.dev_err   = hp_sdc_init();
 #endif
index 3362962..b02a3c7 100644 (file)
@@ -193,7 +193,7 @@ struct pwc_raw_frame {
                                   decompressor) */
        __u8   cmd[4];          /* the four byte of the command (in case of
                                   nala, only the first 3 bytes is filled) */
-       __u8   rawframe[0];     /* frame_size = H / 4 * vbandlength */
+       __u8   rawframe[];      /* frame_size = H / 4 * vbandlength */
 } __packed;
 
 /* intermediate buffers with raw data from the USB cam */
index db8cdf5..e9cacc2 100644 (file)
@@ -412,6 +412,7 @@ MODULE_DEVICE_TABLE(of, mt6360_pmu_of_id);
 
 static struct i2c_driver mt6360_pmu_driver = {
        .driver = {
+               .name = "mt6360_pmu",
                .pm = &mt6360_pmu_pm_ops,
                .of_match_table = of_match_ptr(mt6360_pmu_of_id),
        },
index bccd341..d5d2af4 100644 (file)
@@ -828,7 +828,7 @@ static void run_plant_and_detach_test(int is_early)
        char before[BREAK_INSTR_SIZE];
        char after[BREAK_INSTR_SIZE];
 
-       probe_kernel_read(before, (char *)kgdbts_break_test,
+       copy_from_kernel_nofault(before, (char *)kgdbts_break_test,
          BREAK_INSTR_SIZE);
        init_simple_test();
        ts.tst = plant_and_detach_test;
@@ -836,8 +836,8 @@ static void run_plant_and_detach_test(int is_early)
        /* Activate test with initial breakpoint */
        if (!is_early)
                kgdb_breakpoint();
-       probe_kernel_read(after, (char *)kgdbts_break_test,
-         BREAK_INSTR_SIZE);
+       copy_from_kernel_nofault(after, (char *)kgdbts_break_test,
+                       BREAK_INSTR_SIZE);
        if (memcmp(before, after, BREAK_INSTR_SIZE)) {
                printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
                panic("kgdb memory corruption");
index efd1a1d..5d3c691 100644 (file)
@@ -552,6 +552,8 @@ static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
 static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
                        struct netlink_ext_ack *extack)
 {
+       memset(conf, 0, sizeof(*conf));
+
        if (!data[IFLA_BAREUDP_PORT]) {
                NL_SET_ERR_MSG(extack, "port not specified");
                return -EINVAL;
index d08a3d5..6ad83a8 100644 (file)
@@ -146,7 +146,7 @@ struct pciefd_rx_dma {
        __le32 irq_status;
        __le32 sys_time_low;
        __le32 sys_time_high;
-       struct pucan_rx_msg msg[0];
+       struct pucan_rx_msg msg[];
 } __packed __aligned(4);
 
 /* Tx Link record */
@@ -194,7 +194,7 @@ struct pciefd_board {
        struct pci_dev *pci_dev;
        int can_count;
        spinlock_t cmd_lock;            /* 64-bits cmds must be atomic */
-       struct pciefd_can *can[0];      /* array of network devices */
+       struct pciefd_can *can[];       /* array of network devices */
 };
 
 /* supported device ids. */
index bc0e47c..1771345 100644 (file)
@@ -891,16 +891,16 @@ void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int port,
 
        mutex_lock(&ptp_data->lock);
 
-       rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
+       rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
        if (rc < 0) {
-               dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
+               dev_err(ds->dev, "timed out polling for tstamp\n");
                kfree_skb(skb);
                goto out;
        }
 
-       rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
+       rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
        if (rc < 0) {
-               dev_err(ds->dev, "timed out polling for tstamp\n");
+               dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
                kfree_skb(skb);
                goto out;
        }
index b9b4edb..9b7f1af 100644 (file)
@@ -1249,8 +1249,12 @@ out_disable_adv_intr:
 
 static void __alx_stop(struct alx_priv *alx)
 {
-       alx_halt(alx);
        alx_free_irq(alx);
+
+       cancel_work_sync(&alx->link_check_wk);
+       cancel_work_sync(&alx->reset_wk);
+
+       alx_halt(alx);
        alx_free_rings(alx);
        alx_free_napis(alx);
 }
@@ -1855,9 +1859,6 @@ static void alx_remove(struct pci_dev *pdev)
        struct alx_priv *alx = pci_get_drvdata(pdev);
        struct alx_hw *hw = &alx->hw;
 
-       cancel_work_sync(&alx->link_check_wk);
-       cancel_work_sync(&alx->reset_wk);
-
        /* restore permanent mac address */
        alx_set_macaddr(hw, hw->perm_addr);
 
index c62589c..b93e05f 100644 (file)
@@ -10037,7 +10037,7 @@ static void bnxt_timer(struct timer_list *t)
        struct bnxt *bp = from_timer(bp, t, timer);
        struct net_device *dev = bp->dev;
 
-       if (!netif_running(dev))
+       if (!netif_running(dev) || !test_bit(BNXT_STATE_OPEN, &bp->state))
                return;
 
        if (atomic_read(&bp->intr_sem) != 0)
@@ -12133,19 +12133,9 @@ static int bnxt_resume(struct device *device)
                goto resume_exit;
        }
 
-       if (bnxt_hwrm_queue_qportcfg(bp)) {
-               rc = -ENODEV;
+       rc = bnxt_hwrm_func_qcaps(bp);
+       if (rc)
                goto resume_exit;
-       }
-
-       if (bp->hwrm_spec_code >= 0x10803) {
-               if (bnxt_alloc_ctx_mem(bp)) {
-                       rc = -ENODEV;
-                       goto resume_exit;
-               }
-       }
-       if (BNXT_NEW_RM(bp))
-               bnxt_hwrm_func_resc_qcaps(bp, false);
 
        if (bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, false)) {
                rc = -ENODEV;
@@ -12161,6 +12151,8 @@ static int bnxt_resume(struct device *device)
 
 resume_exit:
        bnxt_ulp_start(bp, rc);
+       if (!rc)
+               bnxt_reenable_sriov(bp);
        rtnl_unlock();
        return rc;
 }
@@ -12204,6 +12196,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
                bnxt_close(netdev);
 
        pci_disable_device(pdev);
+       bnxt_free_ctx_mem(bp);
+       kfree(bp->ctx);
+       bp->ctx = NULL;
        rtnl_unlock();
 
        /* Request a slot slot reset. */
@@ -12237,12 +12232,16 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
                pci_set_master(pdev);
 
                err = bnxt_hwrm_func_reset(bp);
-               if (!err && netif_running(netdev))
-                       err = bnxt_open(netdev);
-
-               if (!err)
-                       result = PCI_ERS_RESULT_RECOVERED;
+               if (!err) {
+                       err = bnxt_hwrm_func_qcaps(bp);
+                       if (!err && netif_running(netdev))
+                               err = bnxt_open(netdev);
+               }
                bnxt_ulp_start(bp, err);
+               if (!err) {
+                       bnxt_reenable_sriov(bp);
+                       result = PCI_ERS_RESULT_RECOVERED;
+               }
        }
 
        if (result != PCI_ERS_RESULT_RECOVERED) {
index 5b9d7c6..6793307 100644 (file)
@@ -2565,15 +2565,14 @@ static int macb_open(struct net_device *dev)
        if (bp->ptp_info)
                bp->ptp_info->ptp_init(dev);
 
+       return 0;
+
 napi_exit:
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
                napi_disable(&queue->napi);
 pm_exit:
-       if (err) {
-               pm_runtime_put_sync(&bp->pdev->dev);
-               return err;
-       }
-       return 0;
+       pm_runtime_put_sync(&bp->pdev->dev);
+       return err;
 }
 
 static int macb_close(struct net_device *dev)
index 1b4d04e..2baf7b3 100644 (file)
@@ -842,12 +842,13 @@ static int ibmvnic_login(struct net_device *netdev)
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
        unsigned long timeout = msecs_to_jiffies(30000);
        int retry_count = 0;
+       int retries = 10;
        bool retry;
        int rc;
 
        do {
                retry = false;
-               if (retry_count > IBMVNIC_MAX_QUEUES) {
+               if (retry_count > retries) {
                        netdev_warn(netdev, "Login attempts exceeded\n");
                        return -1;
                }
@@ -862,11 +863,23 @@ static int ibmvnic_login(struct net_device *netdev)
 
                if (!wait_for_completion_timeout(&adapter->init_done,
                                                 timeout)) {
-                       netdev_warn(netdev, "Login timed out\n");
-                       return -1;
+                       netdev_warn(netdev, "Login timed out, retrying...\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       retry_count++;
+                       continue;
                }
 
-               if (adapter->init_done_rc == PARTIALSUCCESS) {
+               if (adapter->init_done_rc == ABORTED) {
+                       netdev_warn(netdev, "Login aborted, retrying...\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       retry_count++;
+                       /* FW or device may be busy, so
+                        * wait a bit before retrying login
+                        */
+                       msleep(500);
+               } else if (adapter->init_done_rc == PARTIALSUCCESS) {
                        retry_count++;
                        release_sub_crqs(adapter, 1);
 
index d9fa460..4b2de08 100644 (file)
@@ -151,10 +151,8 @@ static int e1000_vlan_rx_kill_vid(struct net_device *netdev,
                                  __be16 proto, u16 vid);
 static void e1000_restore_vlan(struct e1000_adapter *adapter);
 
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
-static int e1000_resume(struct pci_dev *pdev);
-#endif
+static int __maybe_unused e1000_suspend(struct device *dev);
+static int __maybe_unused e1000_resume(struct device *dev);
 static void e1000_shutdown(struct pci_dev *pdev);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -179,16 +177,16 @@ static const struct pci_error_handlers e1000_err_handler = {
        .resume = e1000_io_resume,
 };
 
+static SIMPLE_DEV_PM_OPS(e1000_pm_ops, e1000_suspend, e1000_resume);
+
 static struct pci_driver e1000_driver = {
        .name     = e1000_driver_name,
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
        .remove   = e1000_remove,
-#ifdef CONFIG_PM
-       /* Power Management Hooks */
-       .suspend  = e1000_suspend,
-       .resume   = e1000_resume,
-#endif
+       .driver = {
+               .pm = &e1000_pm_ops,
+       },
        .shutdown = e1000_shutdown,
        .err_handler = &e1000_err_handler
 };
@@ -5060,9 +5058,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        struct e1000_hw *hw = &adapter->hw;
        u32 ctrl, ctrl_ext, rctl, status;
        u32 wufc = adapter->wol;
-#ifdef CONFIG_PM
-       int retval = 0;
-#endif
 
        netif_device_detach(netdev);
 
@@ -5076,12 +5071,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
                e1000_down(adapter);
        }
 
-#ifdef CONFIG_PM
-       retval = pci_save_state(pdev);
-       if (retval)
-               return retval;
-#endif
-
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -5142,37 +5131,26 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static int __maybe_unused e1000_suspend(struct device *dev)
 {
        int retval;
+       struct pci_dev *pdev = to_pci_dev(dev);
        bool wake;
 
        retval = __e1000_shutdown(pdev, &wake);
-       if (retval)
-               return retval;
-
-       if (wake) {
-               pci_prepare_to_sleep(pdev);
-       } else {
-               pci_wake_from_d3(pdev, false);
-               pci_set_power_state(pdev, PCI_D3hot);
-       }
+       device_set_wakeup_enable(dev, wake);
 
-       return 0;
+       return retval;
 }
 
-static int e1000_resume(struct pci_dev *pdev)
+static int __maybe_unused e1000_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
        u32 err;
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_save_state(pdev);
-
        if (adapter->need_ioport)
                err = pci_enable_device(pdev);
        else
@@ -5209,7 +5187,6 @@ static int e1000_resume(struct pci_dev *pdev)
 
        return 0;
 }
-#endif
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
index a279f4f..6f6479c 100644 (file)
@@ -6349,7 +6349,6 @@ fl_out:
        pm_runtime_put_sync(netdev->dev.parent);
 }
 
-#ifdef CONFIG_PM_SLEEP
 /* S0ix implementation */
 static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
 {
@@ -6571,7 +6570,6 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
        mac_data &= ~E1000_CTRL_EXT_FORCE_SMBUS;
        ew32(CTRL_EXT, mac_data);
 }
-#endif /* CONFIG_PM_SLEEP */
 
 static int e1000e_pm_freeze(struct device *dev)
 {
@@ -6611,11 +6609,17 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       u32 ctrl, ctrl_ext, rctl, status;
-       /* Runtime suspend should only enable wakeup for link changes */
-       u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
+       u32 ctrl, ctrl_ext, rctl, status, wufc;
        int retval = 0;
 
+       /* Runtime suspend should only enable wakeup for link changes */
+       if (runtime)
+               wufc = E1000_WUFC_LNKC;
+       else if (device_may_wakeup(&pdev->dev))
+               wufc = adapter->wol;
+       else
+               wufc = 0;
+
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -6672,7 +6676,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
        if (adapter->hw.phy.type == e1000_phy_igp_3) {
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
        } else if (hw->mac.type >= e1000_pch_lpt) {
-               if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
+               if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
                        /* ULP does not support wake from unicast, multicast
                         * or broadcast.
                         */
@@ -6869,7 +6873,6 @@ err_irq:
        return rc;
 }
 
-#ifdef CONFIG_PM
 static int __e1000_resume(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -6935,8 +6938,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int e1000e_pm_suspend(struct device *dev)
+static __maybe_unused int e1000e_pm_suspend(struct device *dev)
 {
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6960,7 +6962,7 @@ static int e1000e_pm_suspend(struct device *dev)
        return rc;
 }
 
-static int e1000e_pm_resume(struct device *dev)
+static __maybe_unused int e1000e_pm_resume(struct device *dev)
 {
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6979,9 +6981,8 @@ static int e1000e_pm_resume(struct device *dev)
 
        return e1000e_pm_thaw(dev);
 }
-#endif /* CONFIG_PM_SLEEP */
 
-static int e1000e_pm_runtime_idle(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_idle(struct device *dev)
 {
        struct net_device *netdev = dev_get_drvdata(dev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -6997,7 +6998,7 @@ static int e1000e_pm_runtime_idle(struct device *dev)
        return -EBUSY;
 }
 
-static int e1000e_pm_runtime_resume(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -7014,7 +7015,7 @@ static int e1000e_pm_runtime_resume(struct device *dev)
        return rc;
 }
 
-static int e1000e_pm_runtime_suspend(struct device *dev)
+static __maybe_unused int e1000e_pm_runtime_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -7039,7 +7040,6 @@ static int e1000e_pm_runtime_suspend(struct device *dev)
 
        return 0;
 }
-#endif /* CONFIG_PM */
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
index 2b5dad2..24f4d8e 100644 (file)
@@ -1544,7 +1544,7 @@ static void mvpp2_read_stats(struct mvpp2_port *port)
        for (q = 0; q < port->ntxqs; q++)
                for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_txq_regs); i++)
                        *pstats++ += mvpp2_read_index(port->priv,
-                                                     MVPP22_CTRS_TX_CTR(port->id, i),
+                                                     MVPP22_CTRS_TX_CTR(port->id, q),
                                                      mvpp2_ethtool_txq_regs[i].offset);
 
        /* Rxqs are numbered from 0 from the user standpoint, but not from the
@@ -1553,7 +1553,7 @@ static void mvpp2_read_stats(struct mvpp2_port *port)
        for (q = 0; q < port->nrxqs; q++)
                for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_rxq_regs); i++)
                        *pstats++ += mvpp2_read_index(port->priv,
-                                                     port->first_rxq + i,
+                                                     port->first_rxq + q,
                                                      mvpp2_ethtool_rxq_regs[i].offset);
 }
 
@@ -5983,8 +5983,8 @@ static int mvpp2_remove(struct platform_device *pdev)
 {
        struct mvpp2 *priv = platform_get_drvdata(pdev);
        struct fwnode_handle *fwnode = pdev->dev.fwnode;
+       int i = 0, poolnum = MVPP2_BM_POOLS_NUM;
        struct fwnode_handle *port_fwnode;
-       int i = 0;
 
        mvpp2_dbgfs_cleanup(priv);
 
@@ -5998,7 +5998,10 @@ static int mvpp2_remove(struct platform_device *pdev)
 
        destroy_workqueue(priv->stats_queue);
 
-       for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+       if (priv->percpu_pools)
+               poolnum = mvpp2_get_nrxqs(priv) * 2;
+
+       for (i = 0; i < poolnum; i++) {
                struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
 
                mvpp2_bm_pool_destroy(&pdev->dev, priv, bm_pool);
index f1ace4f..3e765bd 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 
 #define MTK_STAR_DRVNAME                       "mtk_star_emac"
 
@@ -262,7 +261,6 @@ struct mtk_star_priv {
        spinlock_t lock;
 
        struct rtnl_link_stats64 stats;
-       struct work_struct stats_work;
 };
 
 static struct device *mtk_star_get_dev(struct mtk_star_priv *priv)
@@ -432,42 +430,6 @@ static void mtk_star_intr_disable(struct mtk_star_priv *priv)
        regmap_write(priv->regs, MTK_STAR_REG_INT_MASK, ~0);
 }
 
-static void mtk_star_intr_enable_tx(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_BIT_INT_STS_TNTC);
-}
-
-static void mtk_star_intr_enable_rx(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_BIT_INT_STS_FNRC);
-}
-
-static void mtk_star_intr_enable_stats(struct mtk_star_priv *priv)
-{
-       regmap_clear_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                         MTK_STAR_REG_INT_STS_MIB_CNT_TH);
-}
-
-static void mtk_star_intr_disable_tx(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_BIT_INT_STS_TNTC);
-}
-
-static void mtk_star_intr_disable_rx(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_BIT_INT_STS_FNRC);
-}
-
-static void mtk_star_intr_disable_stats(struct mtk_star_priv *priv)
-{
-       regmap_set_bits(priv->regs, MTK_STAR_REG_INT_MASK,
-                       MTK_STAR_REG_INT_STS_MIB_CNT_TH);
-}
-
 static unsigned int mtk_star_intr_read(struct mtk_star_priv *priv)
 {
        unsigned int val;
@@ -663,20 +625,6 @@ static void mtk_star_update_stats(struct mtk_star_priv *priv)
        stats->rx_errors += stats->rx_fifo_errors;
 }
 
-/* This runs in process context and parallel TX and RX paths executing in
- * napi context may result in losing some stats data but this should happen
- * seldom enough to be acceptable.
- */
-static void mtk_star_update_stats_work(struct work_struct *work)
-{
-       struct mtk_star_priv *priv = container_of(work, struct mtk_star_priv,
-                                                stats_work);
-
-       mtk_star_update_stats(priv);
-       mtk_star_reset_counters(priv);
-       mtk_star_intr_enable_stats(priv);
-}
-
 static struct sk_buff *mtk_star_alloc_skb(struct net_device *ndev)
 {
        uintptr_t tail, offset;
@@ -767,42 +715,25 @@ static void mtk_star_free_tx_skbs(struct mtk_star_priv *priv)
        mtk_star_ring_free_skbs(priv, ring, mtk_star_dma_unmap_tx);
 }
 
-/* All processing for TX and RX happens in the napi poll callback. */
+/* All processing for TX and RX happens in the napi poll callback.
+ *
+ * FIXME: The interrupt handling should be more fine-grained with each
+ * interrupt enabled/disabled independently when needed. Unfortunatly this
+ * turned out to impact the driver's stability and until we have something
+ * working properly, we're disabling all interrupts during TX & RX processing
+ * or when resetting the counter registers.
+ */
 static irqreturn_t mtk_star_handle_irq(int irq, void *data)
 {
        struct mtk_star_priv *priv;
        struct net_device *ndev;
-       bool need_napi = false;
-       unsigned int status;
 
        ndev = data;
        priv = netdev_priv(ndev);
 
        if (netif_running(ndev)) {
-               status = mtk_star_intr_read(priv);
-
-               if (status & MTK_STAR_BIT_INT_STS_TNTC) {
-                       mtk_star_intr_disable_tx(priv);
-                       need_napi = true;
-               }
-
-               if (status & MTK_STAR_BIT_INT_STS_FNRC) {
-                       mtk_star_intr_disable_rx(priv);
-                       need_napi = true;
-               }
-
-               if (need_napi)
-                       napi_schedule(&priv->napi);
-
-               /* One of the counters reached 0x8000000 - update stats and
-                * reset all counters.
-                */
-               if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) {
-                       mtk_star_intr_disable_stats(priv);
-                       schedule_work(&priv->stats_work);
-               }
-
-               mtk_star_intr_ack_all(priv);
+               mtk_star_intr_disable(priv);
+               napi_schedule(&priv->napi);
        }
 
        return IRQ_HANDLED;
@@ -1169,8 +1100,6 @@ static void mtk_star_tx_complete_all(struct mtk_star_priv *priv)
        if (wake && netif_queue_stopped(ndev))
                netif_wake_queue(ndev);
 
-       mtk_star_intr_enable_tx(priv);
-
        spin_unlock(&priv->lock);
 }
 
@@ -1332,20 +1261,32 @@ static int mtk_star_process_rx(struct mtk_star_priv *priv, int budget)
 static int mtk_star_poll(struct napi_struct *napi, int budget)
 {
        struct mtk_star_priv *priv;
+       unsigned int status;
        int received = 0;
 
        priv = container_of(napi, struct mtk_star_priv, napi);
 
-       /* Clean-up all TX descriptors. */
-       mtk_star_tx_complete_all(priv);
-       /* Receive up to $budget packets. */
-       received = mtk_star_process_rx(priv, budget);
+       status = mtk_star_intr_read(priv);
+       mtk_star_intr_ack_all(priv);
 
-       if (received < budget) {
-               napi_complete_done(napi, received);
-               mtk_star_intr_enable_rx(priv);
+       if (status & MTK_STAR_BIT_INT_STS_TNTC)
+               /* Clean-up all TX descriptors. */
+               mtk_star_tx_complete_all(priv);
+
+       if (status & MTK_STAR_BIT_INT_STS_FNRC)
+               /* Receive up to $budget packets. */
+               received = mtk_star_process_rx(priv, budget);
+
+       if (unlikely(status & MTK_STAR_REG_INT_STS_MIB_CNT_TH)) {
+               mtk_star_update_stats(priv);
+               mtk_star_reset_counters(priv);
        }
 
+       if (received < budget)
+               napi_complete_done(napi, received);
+
+       mtk_star_intr_enable(priv);
+
        return received;
 }
 
@@ -1532,7 +1473,6 @@ static int mtk_star_probe(struct platform_device *pdev)
        ndev->max_mtu = MTK_STAR_MAX_FRAME_SIZE;
 
        spin_lock_init(&priv->lock);
-       INIT_WORK(&priv->stats_work, mtk_star_update_stats_work);
 
        base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
index 5ffa32b..55af877 100644 (file)
@@ -978,8 +978,10 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 
                lossy = !(pfc || pause_en);
                thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &thres_cells);
                delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
                                                        pfc, pause_en);
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &delay_cells);
                total_cells = thres_cells + delay_cells;
 
                taken_headroom_cells += total_cells;
index 6f96ca5..6e87457 100644 (file)
@@ -374,6 +374,19 @@ mlxsw_sp_port_vlan_find_by_vid(const struct mlxsw_sp_port *mlxsw_sp_port,
        return NULL;
 }
 
+static inline void
+mlxsw_sp_port_headroom_8x_adjust(const struct mlxsw_sp_port *mlxsw_sp_port,
+                                u16 *p_size)
+{
+       /* Ports with eight lanes use two headroom buffers between which the
+        * configured headroom size is split. Therefore, multiply the calculated
+        * headroom size by two.
+        */
+       if (mlxsw_sp_port->mapping.width != 8)
+               return;
+       *p_size *= 2;
+}
+
 enum mlxsw_sp_flood_type {
        MLXSW_SP_FLOOD_TYPE_UC,
        MLXSW_SP_FLOOD_TYPE_BC,
index 21bfb2f..f25a8b0 100644 (file)
@@ -312,6 +312,7 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
                if (i == MLXSW_SP_PB_UNUSED)
                        continue;
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &size);
                mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, size);
        }
        mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl,
index 304eb8c..f843545 100644 (file)
@@ -782,6 +782,7 @@ mlxsw_sp_span_port_buffer_update(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
                speed = 0;
 
        buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, speed, mtu);
+       mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, (u16 *) &buffsize);
        mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, buffsize);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 }
index c5c5c68..f1711ac 100644 (file)
@@ -3091,6 +3091,8 @@ static const struct pci_device_id lan743x_pcidev_tbl[] = {
        { 0, }
 };
 
+MODULE_DEVICE_TABLE(pci, lan743x_pcidev_tbl);
+
 static struct pci_driver lan743x_pcidev_driver = {
        .name     = DRIVER_NAME,
        .id_table = lan743x_pcidev_tbl,
index 8d7b9bb..1003763 100644 (file)
@@ -269,7 +269,7 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
                                     struct bin_attribute *attr, char *buf,
                                     loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -286,7 +286,7 @@ static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
                                      struct bin_attribute *attr, char *buf,
                                      loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -315,7 +315,7 @@ static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
                                     struct bin_attribute *attr, char *buf,
                                     loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u64 data;
        int ret;
@@ -337,7 +337,7 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
                                      struct bin_attribute *attr, char *buf,
                                      loff_t offset, size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u64 data;
        int ret;
@@ -402,7 +402,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pm_func_cfg *pm_cfg;
        u32 id, action, pci_func;
@@ -452,7 +452,7 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
                                           char *buf, loff_t offset,
                                           size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pm_func_cfg *pm_cfg;
        u8 pci_func;
@@ -545,7 +545,7 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
                                             char *buf, loff_t offset,
                                             size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_func_cfg *esw_cfg;
        struct qlcnic_npar_info *npar;
@@ -629,7 +629,7 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_func_cfg *esw_cfg;
        u8 pci_func;
@@ -681,7 +681,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
                                              char *buf, loff_t offset,
                                              size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_info nic_info;
        struct qlcnic_npar_func_cfg *np_cfg;
@@ -728,7 +728,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
                                             char *buf, loff_t offset,
                                             size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_npar_func_cfg *np_cfg;
        struct qlcnic_info nic_info;
@@ -775,7 +775,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
                                           char *buf, loff_t offset,
                                           size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_statistics port_stats;
        int ret;
@@ -810,7 +810,7 @@ static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
                                          char *buf, loff_t offset,
                                          size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_esw_statistics esw_stats;
        int ret;
@@ -845,7 +845,7 @@ static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -875,7 +875,7 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
                                             size_t size)
 {
 
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int ret;
 
@@ -904,7 +904,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
                                            char *buf, loff_t offset,
                                            size_t size)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        struct qlcnic_pci_func_cfg *pci_cfg;
        struct qlcnic_pci_info *pci_info;
@@ -946,7 +946,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
 {
        unsigned char *p_read_buf;
        int  ret, count;
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 
        if (!size)
@@ -1124,7 +1124,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
        int  ret;
        static int flash_mode;
        unsigned long data;
-       struct device *dev = container_of(kobj, struct device, kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 
        ret = kstrtoul(buf, 16, &data);
index 7585cd2..fc99e71 100644 (file)
@@ -647,10 +647,10 @@ static int rocker_dma_rings_init(struct rocker *rocker)
 err_dma_event_ring_bufs_alloc:
        rocker_dma_ring_destroy(rocker, &rocker->event_ring);
 err_dma_event_ring_create:
+       rocker_dma_cmd_ring_waits_free(rocker);
+err_dma_cmd_ring_waits_alloc:
        rocker_dma_ring_bufs_free(rocker, &rocker->cmd_ring,
                                  PCI_DMA_BIDIRECTIONAL);
-err_dma_cmd_ring_waits_alloc:
-       rocker_dma_cmd_ring_waits_free(rocker);
 err_dma_cmd_ring_bufs_alloc:
        rocker_dma_ring_destroy(rocker, &rocker->cmd_ring);
        return err;
index fbaf3c9..f34c790 100644 (file)
 #define XAE_RAF_TXVSTRPMODE_MASK       0x00000180 /* Tx VLAN STRIP mode */
 #define XAE_RAF_RXVSTRPMODE_MASK       0x00000600 /* Rx VLAN STRIP mode */
 #define XAE_RAF_NEWFNCENBL_MASK                0x00000800 /* New function mode */
-/* Exteneded Multicast Filtering mode */
+/* Extended Multicast Filtering mode */
 #define XAE_RAF_EMULTIFLTRENBL_MASK    0x00001000
 #define XAE_RAF_STATSRST_MASK          0x00002000 /* Stats. Counter Reset */
 #define XAE_RAF_RXBADFRMEN_MASK                0x00004000 /* Recv Bad Frame Enable */
index e1d097e..31478c0 100644 (file)
@@ -33,7 +33,7 @@ void flush_cpu_work(void);
 struct op_sample {
        unsigned long eip;
        unsigned long event;
-       unsigned long data[0];
+       unsigned long data[];
 };
 
 struct op_entry;
index 2c1a7d7..77fb23b 100644 (file)
@@ -43,7 +43,7 @@ struct samsung_usb2_phy_driver {
        struct regmap *reg_pmu;
        struct regmap *reg_sys;
        spinlock_t lock;
-       struct samsung_usb2_phy_instance instances[0];
+       struct samsung_usb2_phy_instance instances[];
 };
 
 struct samsung_usb2_common_phy {
index 0e90c5d..eb8ed28 100644 (file)
@@ -39,7 +39,7 @@ struct rio_id_table {
        u16 start;      /* logical minimal id */
        u32 max;        /* max number of IDs in table */
        spinlock_t lock;
-       unsigned long table[0];
+       unsigned long table[];
 };
 
 static int next_destid = 0;
index 038aec3..a01eda7 100644 (file)
@@ -67,7 +67,7 @@ struct knav_reg_config {
        u32             link_ram_size0;
        u32             link_ram_base1;
        u32             __pad2[2];
-       u32             starvation[0];
+       u32             starvation[];
 };
 
 struct knav_reg_region {
index f02be0d..8d418ab 100644 (file)
@@ -402,7 +402,7 @@ int __init hpfb_init(void)
        if (err)
                return err;
 
-       err = probe_kernel_read(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
+       err = copy_from_kernel_nofault(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
 
        if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
                if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
index 3041092..449680a 100644 (file)
@@ -73,7 +73,7 @@ struct w1_netlink_msg
                        __u32           res;
                } mst;
        } id;
-       __u8                            data[0];
+       __u8                            data[];
 };
 
 /**
@@ -122,7 +122,7 @@ struct w1_netlink_cmd
        __u8                            cmd;
        __u8                            res;
        __u16                           len;
-       __u8                            data[0];
+       __u8                            data[];
 };
 
 #ifdef __KERNEL__
index aa1d341..3e3c2bf 100644 (file)
@@ -648,7 +648,7 @@ static void afs_do_lookup_success(struct afs_operation *op)
                        vp = &op->file[0];
                        abort_code = vp->scb.status.abort_code;
                        if (abort_code != 0) {
-                               op->abort_code = abort_code;
+                               op->ac.abort_code = abort_code;
                                op->error = afs_abort_to_error(abort_code);
                        }
                        break;
@@ -696,10 +696,11 @@ static const struct afs_operation_ops afs_inline_bulk_status_operation = {
        .success        = afs_do_lookup_success,
 };
 
-static const struct afs_operation_ops afs_fetch_status_operation = {
+static const struct afs_operation_ops afs_lookup_fetch_status_operation = {
        .issue_afs_rpc  = afs_fs_fetch_status,
        .issue_yfs_rpc  = yfs_fs_fetch_status,
        .success        = afs_do_lookup_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
@@ -1236,6 +1237,17 @@ void afs_d_release(struct dentry *dentry)
        _enter("%pd", dentry);
 }
 
+void afs_check_for_remote_deletion(struct afs_operation *op)
+{
+       struct afs_vnode *vnode = op->file[0].vnode;
+
+       switch (op->ac.abort_code) {
+       case VNOVNODE:
+               set_bit(AFS_VNODE_DELETED, &vnode->flags);
+               afs_break_callback(vnode, afs_cb_break_for_deleted);
+       }
+}
+
 /*
  * Create a new inode for create/mkdir/symlink
  */
@@ -1268,7 +1280,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
 static void afs_create_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
        afs_vnode_new_inode(op);
@@ -1302,6 +1314,7 @@ static const struct afs_operation_ops afs_mkdir_operation = {
        .issue_afs_rpc  = afs_fs_make_dir,
        .issue_yfs_rpc  = yfs_fs_make_dir,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1325,6 +1338,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
        op->dentry      = dentry;
        op->create.mode = S_IFDIR | mode;
        op->create.reason = afs_edit_dir_for_mkdir;
@@ -1350,7 +1364,7 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
 static void afs_rmdir_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
 }
@@ -1382,6 +1396,7 @@ static const struct afs_operation_ops afs_rmdir_operation = {
        .issue_afs_rpc  = afs_fs_remove_dir,
        .issue_yfs_rpc  = yfs_fs_remove_dir,
        .success        = afs_rmdir_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_rmdir_edit_dir,
        .put            = afs_rmdir_put,
 };
@@ -1404,6 +1419,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        op->dentry      = dentry;
        op->ops         = &afs_rmdir_operation;
@@ -1479,7 +1495,8 @@ static void afs_dir_remove_link(struct afs_operation *op)
 static void afs_unlink_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       op->ctime = op->file[0].scb.status.mtime_client;
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[1]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
@@ -1511,6 +1528,7 @@ static const struct afs_operation_ops afs_unlink_operation = {
        .issue_afs_rpc  = afs_fs_remove_file,
        .issue_yfs_rpc  = yfs_fs_remove_file,
        .success        = afs_unlink_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_unlink_edit_dir,
        .put            = afs_unlink_put,
 };
@@ -1537,6 +1555,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        /* Try to make sure we have a callback promise on the victim. */
        ret = afs_validate(vnode, op->key);
@@ -1561,9 +1580,25 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        spin_unlock(&dentry->d_lock);
 
        op->file[1].vnode = vnode;
+       op->file[1].update_ctime = true;
+       op->file[1].op_unlinked = true;
        op->dentry      = dentry;
        op->ops         = &afs_unlink_operation;
-       return afs_do_sync_operation(op);
+       afs_begin_vnode_operation(op);
+       afs_wait_for_operation(op);
+
+       /* If there was a conflict with a third party, check the status of the
+        * unlinked vnode.
+        */
+       if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               op->file[1].update_ctime = false;
+               op->fetch_status.which = 1;
+               op->ops = &afs_fetch_status_operation;
+               afs_begin_vnode_operation(op);
+               afs_wait_for_operation(op);
+       }
+
+       return afs_put_operation(op);
 
 error:
        return afs_put_operation(op);
@@ -1573,6 +1608,7 @@ static const struct afs_operation_ops afs_create_operation = {
        .issue_afs_rpc  = afs_fs_create_file,
        .issue_yfs_rpc  = yfs_fs_create_file,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1601,6 +1637,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        afs_op_set_vnode(op, 0, dvnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
 
        op->dentry      = dentry;
        op->create.mode = S_IFREG | mode;
@@ -1620,6 +1657,7 @@ static void afs_link_success(struct afs_operation *op)
        struct afs_vnode_param *vp = &op->file[1];
 
        _enter("op=%08x", op->debug_id);
+       op->ctime = dvp->scb.status.mtime_client;
        afs_vnode_commit_status(op, dvp);
        afs_vnode_commit_status(op, vp);
        afs_update_dentry_version(op, dvp, op->dentry);
@@ -1640,6 +1678,7 @@ static const struct afs_operation_ops afs_link_operation = {
        .issue_afs_rpc  = afs_fs_link,
        .issue_yfs_rpc  = yfs_fs_link,
        .success        = afs_link_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_link_put,
 };
@@ -1672,6 +1711,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
        afs_op_set_vnode(op, 0, dvnode);
        afs_op_set_vnode(op, 1, vnode);
        op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = dentry;
        op->dentry_2            = from;
@@ -1689,6 +1730,7 @@ static const struct afs_operation_ops afs_symlink_operation = {
        .issue_afs_rpc  = afs_fs_symlink,
        .issue_yfs_rpc  = yfs_fs_symlink,
        .success        = afs_create_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_create_edit_dir,
        .put            = afs_create_put,
 };
@@ -1740,9 +1782,13 @@ static void afs_rename_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
 
+       op->ctime = op->file[0].scb.status.mtime_client;
+       afs_check_dir_conflict(op, &op->file[1]);
        afs_vnode_commit_status(op, &op->file[0]);
-       if (op->file[1].vnode != op->file[0].vnode)
+       if (op->file[1].vnode != op->file[0].vnode) {
+               op->ctime = op->file[1].scb.status.mtime_client;
                afs_vnode_commit_status(op, &op->file[1]);
+       }
 }
 
 static void afs_rename_edit_dir(struct afs_operation *op)
@@ -1860,6 +1906,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */
        op->file[0].dv_delta = 1;
        op->file[1].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = old_dentry;
        op->dentry_2            = new_dentry;
index b14e3d9..04f75a4 100644 (file)
@@ -16,6 +16,7 @@ static void afs_silly_rename_success(struct afs_operation *op)
 {
        _enter("op=%08x", op->debug_id);
 
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
 }
 
@@ -69,6 +70,11 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
                return PTR_ERR(op);
 
        afs_op_set_vnode(op, 0, dvnode);
+       afs_op_set_vnode(op, 1, dvnode);
+       op->file[0].dv_delta = 1;
+       op->file[1].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].update_ctime = true;
 
        op->dentry              = old;
        op->dentry_2            = new;
@@ -129,6 +135,7 @@ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
        switch (ret) {
        case 0:
                /* The rename succeeded. */
+               set_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags);
                d_move(dentry, sdentry);
                break;
        case -ERESTARTSYS:
@@ -148,19 +155,11 @@ out:
 
 static void afs_silly_unlink_success(struct afs_operation *op)
 {
-       struct afs_vnode *vnode = op->file[1].vnode;
-
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, op->file[0].vnode);
+       afs_check_dir_conflict(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_vnode_commit_status(op, &op->file[1]);
        afs_update_dentry_version(op, &op->file[0], op->dentry);
-
-       drop_nlink(&vnode->vfs_inode);
-       if (vnode->vfs_inode.i_nlink == 0) {
-               set_bit(AFS_VNODE_DELETED, &vnode->flags);
-               clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
-       }
 }
 
 static void afs_silly_unlink_edit_dir(struct afs_operation *op)
@@ -181,6 +180,7 @@ static const struct afs_operation_ops afs_silly_unlink_operation = {
        .issue_afs_rpc  = afs_fs_remove_file,
        .issue_yfs_rpc  = yfs_fs_remove_file,
        .success        = afs_silly_unlink_success,
+       .aborted        = afs_check_for_remote_deletion,
        .edit_dir       = afs_silly_unlink_edit_dir,
 };
 
@@ -200,12 +200,30 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
 
        afs_op_set_vnode(op, 0, dvnode);
        afs_op_set_vnode(op, 1, vnode);
+       op->file[0].dv_delta = 1;
+       op->file[0].update_ctime = true;
+       op->file[1].op_unlinked = true;
+       op->file[1].update_ctime = true;
 
        op->dentry      = dentry;
        op->ops         = &afs_silly_unlink_operation;
 
        trace_afs_silly_rename(vnode, true);
-       return afs_do_sync_operation(op);
+       afs_begin_vnode_operation(op);
+       afs_wait_for_operation(op);
+
+       /* If there was a conflict with a third party, check the status of the
+        * unlinked vnode.
+        */
+       if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               op->file[1].update_ctime = false;
+               op->fetch_status.which = 1;
+               op->ops = &afs_fetch_status_operation;
+               afs_begin_vnode_operation(op);
+               afs_wait_for_operation(op);
+       }
+
+       return afs_put_operation(op);
 }
 
 /*
index 506c474..6f6ed16 100644 (file)
@@ -225,7 +225,6 @@ static void afs_fetch_data_success(struct afs_operation *op)
        struct afs_vnode *vnode = op->file[0].vnode;
 
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, vnode);
        afs_vnode_commit_status(op, &op->file[0]);
        afs_stat_v(vnode, n_fetches);
        atomic_long_add(op->fetch.req->actual_len, &op->net->n_fetch_bytes);
@@ -240,6 +239,7 @@ static const struct afs_operation_ops afs_fetch_data_operation = {
        .issue_afs_rpc  = afs_fs_fetch_data,
        .issue_yfs_rpc  = yfs_fs_fetch_data,
        .success        = afs_fetch_data_success,
+       .aborted        = afs_check_for_remote_deletion,
        .put            = afs_fetch_data_put,
 };
 
index 71eea2a..ffb8575 100644 (file)
@@ -175,10 +175,7 @@ static void afs_kill_lockers_enoent(struct afs_vnode *vnode)
 
 static void afs_lock_success(struct afs_operation *op)
 {
-       struct afs_vnode *vnode = op->file[0].vnode;
-
        _enter("op=%08x", op->debug_id);
-       afs_check_for_remote_deletion(op, vnode);
        afs_vnode_commit_status(op, &op->file[0]);
 }
 
@@ -186,6 +183,7 @@ static const struct afs_operation_ops afs_set_lock_operation = {
        .issue_afs_rpc  = afs_fs_set_lock,
        .issue_yfs_rpc  = yfs_fs_set_lock,
        .success        = afs_lock_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
index 2d2dff5..c264839 100644 (file)
@@ -187,9 +187,17 @@ void afs_wait_for_operation(struct afs_operation *op)
                op->error = afs_wait_for_call_to_complete(op->call, &op->ac);
        }
 
-       if (op->error == 0) {
+       switch (op->error) {
+       case 0:
                _debug("success");
                op->ops->success(op);
+               break;
+       case -ECONNABORTED:
+               if (op->ops->aborted)
+                       op->ops->aborted(op);
+               break;
+       default:
+               break;
        }
 
        afs_end_vnode_operation(op);
index cd0a006..1d13d2e 100644 (file)
@@ -165,9 +165,11 @@ static void afs_apply_status(struct afs_operation *op,
 {
        struct afs_file_status *status = &vp->scb.status;
        struct afs_vnode *vnode = vp->vnode;
+       struct inode *inode = &vnode->vfs_inode;
        struct timespec64 t;
        umode_t mode;
        bool data_changed = false;
+       bool change_size = vp->set_size;
 
        _enter("{%llx:%llu.%u} %s",
               vp->fid.vid, vp->fid.vnode, vp->fid.unique,
@@ -186,25 +188,25 @@ static void afs_apply_status(struct afs_operation *op,
        }
 
        if (status->nlink != vnode->status.nlink)
-               set_nlink(&vnode->vfs_inode, status->nlink);
+               set_nlink(inode, status->nlink);
 
        if (status->owner != vnode->status.owner)
-               vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
+               inode->i_uid = make_kuid(&init_user_ns, status->owner);
 
        if (status->group != vnode->status.group)
-               vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
+               inode->i_gid = make_kgid(&init_user_ns, status->group);
 
        if (status->mode != vnode->status.mode) {
-               mode = vnode->vfs_inode.i_mode;
+               mode = inode->i_mode;
                mode &= ~S_IALLUGO;
                mode |= status->mode;
-               WRITE_ONCE(vnode->vfs_inode.i_mode, mode);
+               WRITE_ONCE(inode->i_mode, mode);
        }
 
        t = status->mtime_client;
-       vnode->vfs_inode.i_ctime = t;
-       vnode->vfs_inode.i_mtime = t;
-       vnode->vfs_inode.i_atime = t;
+       inode->i_mtime = t;
+       if (vp->update_ctime)
+               inode->i_ctime = op->ctime;
 
        if (vnode->status.data_version != status->data_version)
                data_changed = true;
@@ -226,6 +228,7 @@ static void afs_apply_status(struct afs_operation *op,
                } else {
                        set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
                }
+               change_size = true;
        } else if (vnode->status.type == AFS_FTYPE_DIR) {
                /* Expected directory change is handled elsewhere so
                 * that we can locally edit the directory and save on a
@@ -233,11 +236,22 @@ static void afs_apply_status(struct afs_operation *op,
                 */
                if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
                        data_changed = false;
+               change_size = true;
        }
 
        if (data_changed) {
-               inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
-               afs_set_i_size(vnode, status->size);
+               inode_set_iversion_raw(inode, status->data_version);
+
+               /* Only update the size if the data version jumped.  If the
+                * file is being modified locally, then we might have our own
+                * idea of what the size should be that's not the same as
+                * what's on the server.
+                */
+               if (change_size) {
+                       afs_set_i_size(vnode, status->size);
+                       inode->i_ctime = t;
+                       inode->i_atime = t;
+               }
        }
 }
 
@@ -267,32 +281,39 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v
 
        _enter("");
 
-       ASSERTCMP(op->error, ==, 0);
-
        write_seqlock(&vnode->cb_lock);
 
        if (vp->scb.have_error) {
+               /* A YFS server will return this from RemoveFile2 and AFS and
+                * YFS will return this from InlineBulkStatus.
+                */
                if (vp->scb.status.abort_code == VNOVNODE) {
                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
                        clear_nlink(&vnode->vfs_inode);
                        __afs_break_callback(vnode, afs_cb_break_for_deleted);
+                       op->flags &= ~AFS_OPERATION_DIR_CONFLICT;
                }
-       } else {
-               if (vp->scb.have_status)
-                       afs_apply_status(op, vp);
+       } else if (vp->scb.have_status) {
+               afs_apply_status(op, vp);
                if (vp->scb.have_cb)
                        afs_apply_callback(op, vp);
+       } else if (vp->op_unlinked && !(op->flags & AFS_OPERATION_DIR_CONFLICT)) {
+               drop_nlink(&vnode->vfs_inode);
+               if (vnode->vfs_inode.i_nlink == 0) {
+                       set_bit(AFS_VNODE_DELETED, &vnode->flags);
+                       __afs_break_callback(vnode, afs_cb_break_for_deleted);
+               }
        }
 
        write_sequnlock(&vnode->cb_lock);
 
-       if (op->error == 0 && vp->scb.have_status)
+       if (vp->scb.have_status)
                afs_cache_permit(vnode, op->key, vp->cb_break_before, &vp->scb);
 }
 
 static void afs_fetch_status_success(struct afs_operation *op)
 {
-       struct afs_vnode_param *vp = &op->file[0];
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
        struct afs_vnode *vnode = vp->vnode;
        int ret;
 
@@ -306,10 +327,11 @@ static void afs_fetch_status_success(struct afs_operation *op)
        }
 }
 
-static const struct afs_operation_ops afs_fetch_status_operation = {
+const struct afs_operation_ops afs_fetch_status_operation = {
        .issue_afs_rpc  = afs_fs_fetch_status,
        .issue_yfs_rpc  = yfs_fs_fetch_status,
        .success        = afs_fetch_status_success,
+       .aborted        = afs_check_for_remote_deletion,
 };
 
 /*
@@ -716,6 +738,9 @@ int afs_getattr(const struct path *path, struct kstat *stat,
        do {
                read_seqbegin_or_lock(&vnode->cb_lock, &seq);
                generic_fillattr(inode, stat);
+               if (test_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags) &&
+                   stat->nlink > 0)
+                       stat->nlink -= 1;
        } while (need_seqretry(&vnode->cb_lock, seq));
 
        done_seqretry(&vnode->cb_lock, seq);
@@ -785,7 +810,15 @@ void afs_evict_inode(struct inode *inode)
 
 static void afs_setattr_success(struct afs_operation *op)
 {
+       struct inode *inode = &op->file[0].vnode->vfs_inode;
+
        afs_vnode_commit_status(op, &op->file[0]);
+       if (op->setattr.attr->ia_valid & ATTR_SIZE) {
+               loff_t i_size = inode->i_size, size = op->setattr.attr->ia_size;
+               if (size > i_size)
+                       pagecache_isize_extended(inode, i_size, size);
+               truncate_pagecache(inode, size);
+       }
 }
 
 static const struct afs_operation_ops afs_setattr_operation = {
@@ -801,17 +834,31 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct afs_operation *op;
        struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
+       int ret;
 
        _enter("{%llx:%llu},{n=%pd},%x",
               vnode->fid.vid, vnode->fid.vnode, dentry,
               attr->ia_valid);
 
        if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
-                               ATTR_MTIME))) {
+                               ATTR_MTIME | ATTR_MTIME_SET | ATTR_TIMES_SET |
+                               ATTR_TOUCH))) {
                _leave(" = 0 [unsupported]");
                return 0;
        }
 
+       if (attr->ia_valid & ATTR_SIZE) {
+               if (!S_ISREG(vnode->vfs_inode.i_mode))
+                       return -EISDIR;
+
+               ret = inode_newsize_ok(&vnode->vfs_inode, attr->ia_size);
+               if (ret)
+                       return ret;
+
+               if (attr->ia_size == i_size_read(&vnode->vfs_inode))
+                       attr->ia_valid &= ~ATTR_SIZE;
+       }
+
        /* flush any dirty data outstanding on a regular file */
        if (S_ISREG(vnode->vfs_inode.i_mode))
                filemap_write_and_wait(vnode->vfs_inode.i_mapping);
@@ -825,8 +872,12 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        afs_op_set_vnode(op, 0, vnode);
        op->setattr.attr = attr;
 
-       if (attr->ia_valid & ATTR_SIZE)
+       if (attr->ia_valid & ATTR_SIZE) {
                op->file[0].dv_delta = 1;
+               op->file[0].set_size = true;
+       }
+       op->ctime = attr->ia_ctime;
+       op->file[0].update_ctime = 1;
 
        op->ops = &afs_setattr_operation;
        return afs_do_sync_operation(op);
index 0c9806e..573a592 100644 (file)
@@ -634,6 +634,7 @@ struct afs_vnode {
 #define AFS_VNODE_AUTOCELL     6               /* set if Vnode is an auto mount point */
 #define AFS_VNODE_PSEUDODIR    7               /* set if Vnode is a pseudo directory */
 #define AFS_VNODE_NEW_CONTENT  8               /* Set if file has new content (create/trunc-0) */
+#define AFS_VNODE_SILLY_DELETED        9               /* Set if file has been silly-deleted */
 
        struct list_head        wb_keys;        /* List of keys available for writeback */
        struct list_head        pending_locks;  /* locks waiting to be granted */
@@ -744,8 +745,11 @@ struct afs_vnode_param {
        afs_dataversion_t       dv_before;      /* Data version before the call */
        unsigned int            cb_break_before; /* cb_break + cb_s_break before the call */
        u8                      dv_delta;       /* Expected change in data version */
-       bool                    put_vnode;      /* T if we have a ref on the vnode */
-       bool                    need_io_lock;   /* T if we need the I/O lock on this */
+       bool                    put_vnode:1;    /* T if we have a ref on the vnode */
+       bool                    need_io_lock:1; /* T if we need the I/O lock on this */
+       bool                    update_ctime:1; /* Need to update the ctime */
+       bool                    set_size:1;     /* Must update i_size */
+       bool                    op_unlinked:1;  /* True if file was unlinked by op */
 };
 
 /*
@@ -766,9 +770,9 @@ struct afs_operation {
        struct dentry           *dentry;        /* Dentry to be altered */
        struct dentry           *dentry_2;      /* Second dentry to be altered */
        struct timespec64       mtime;          /* Modification time to record */
+       struct timespec64       ctime;          /* Change time to set */
        short                   nr_files;       /* Number of entries in file[], more_files */
        short                   error;
-       unsigned int            abort_code;
        unsigned int            debug_id;
 
        unsigned int            cb_v_break;     /* Volume break counter before op */
@@ -837,6 +841,7 @@ struct afs_operation {
 #define AFS_OPERATION_LOCK_1           0x0200  /* Set if have io_lock on file[1] */
 #define AFS_OPERATION_TRIED_ALL                0x0400  /* Set if we've tried all the fileservers */
 #define AFS_OPERATION_RETRY_SERVER     0x0800  /* Set if we should retry the current server */
+#define AFS_OPERATION_DIR_CONFLICT     0x1000  /* Set if we detected a 3rd-party dir change */
 };
 
 /*
@@ -932,6 +937,7 @@ extern const struct address_space_operations afs_dir_aops;
 extern const struct dentry_operations afs_fs_dentry_operations;
 
 extern void afs_d_release(struct dentry *);
+extern void afs_check_for_remote_deletion(struct afs_operation *);
 
 /*
  * dir_edit.c
@@ -1063,6 +1069,8 @@ extern int afs_wait_for_one_fs_probe(struct afs_server *, bool);
 /*
  * inode.c
  */
+extern const struct afs_operation_ops afs_fetch_status_operation;
+
 extern void afs_vnode_commit_status(struct afs_operation *, struct afs_vnode_param *);
 extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t *);
 extern int afs_ilookup5_test_by_fid(struct inode *, void *);
@@ -1435,7 +1443,6 @@ extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
 /*
  * yfsclient.c
  */
-extern void yfs_fs_fetch_file_status(struct afs_operation *);
 extern void yfs_fs_fetch_data(struct afs_operation *);
 extern void yfs_fs_create_file(struct afs_operation *);
 extern void yfs_fs_make_dir(struct afs_operation *);
@@ -1481,15 +1488,6 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode)
        return &vnode->vfs_inode;
 }
 
-static inline void afs_check_for_remote_deletion(struct afs_operation *op,
-                                                struct afs_vnode *vnode)
-{
-       if (op->error == -ENOENT) {
-               set_bit(AFS_VNODE_DELETED, &vnode->flags);
-               afs_break_callback(vnode, afs_cb_break_for_deleted);
-       }
-}
-
 /*
  * Note that a dentry got changed.  We need to set d_fsdata to the data version
  * number derived from the result of the operation.  It doesn't matter if
@@ -1504,6 +1502,18 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
                        (void *)(unsigned long)dir_vp->scb.status.data_version;
 }
 
+/*
+ * Check for a conflicting operation on a directory that we just unlinked from.
+ * If someone managed to sneak a link or an unlink in on the file we just
+ * unlinked, we won't be able to trust nlink on an AFS file (but not YFS).
+ */
+static inline void afs_check_dir_conflict(struct afs_operation *op,
+                                         struct afs_vnode_param *dvp)
+{
+       if (dvp->dv_before + dvp->dv_delta != dvp->scb.status.data_version)
+               op->flags |= AFS_OPERATION_DIR_CONFLICT;
+}
+
 static inline int afs_io_error(struct afs_call *call, enum afs_io_error where)
 {
        trace_afs_io_error(call->debug_id, -EIO, where);
index 52b19e9..5334f1b 100644 (file)
@@ -83,6 +83,7 @@ int afs_abort_to_error(u32 abort_code)
        case UAENOLCK:                  return -ENOLCK;
        case UAENOTEMPTY:               return -ENOTEMPTY;
        case UAELOOP:                   return -ELOOP;
+       case UAEOVERFLOW:               return -EOVERFLOW;
        case UAENOMEDIUM:               return -ENOMEDIUM;
        case UAEDQUOT:                  return -EDQUOT;
 
index 768497f..7437806 100644 (file)
@@ -194,11 +194,11 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 
        i_size = i_size_read(&vnode->vfs_inode);
        if (maybe_i_size > i_size) {
-               spin_lock(&vnode->wb_lock);
+               write_seqlock(&vnode->cb_lock);
                i_size = i_size_read(&vnode->vfs_inode);
                if (maybe_i_size > i_size)
                        i_size_write(&vnode->vfs_inode, maybe_i_size);
-               spin_unlock(&vnode->wb_lock);
+               write_sequnlock(&vnode->cb_lock);
        }
 
        if (!PageUptodate(page)) {
@@ -393,6 +393,7 @@ static void afs_store_data_success(struct afs_operation *op)
 {
        struct afs_vnode *vnode = op->file[0].vnode;
 
+       op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        if (op->error == 0) {
                afs_pages_written_back(vnode, op->store.first, op->store.last);
@@ -491,6 +492,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
        unsigned long count, priv;
        unsigned n, offset, to, f, t;
        pgoff_t start, first, last;
+       loff_t i_size, end;
        int loop, ret;
 
        _enter(",%lx", primary_page->index);
@@ -591,7 +593,12 @@ no_more:
        first = primary_page->index;
        last = first + count - 1;
 
+       end = (loff_t)last * PAGE_SIZE + to;
+       i_size = i_size_read(&vnode->vfs_inode);
+
        _debug("write back %lx[%u..] to %lx[..%u]", first, offset, last, to);
+       if (end > i_size)
+               to = i_size & ~PAGE_MASK;
 
        ret = afs_store_data(mapping, first, last, offset, to);
        switch (ret) {
@@ -844,6 +851,7 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
                             vmf->page->index, priv);
        SetPagePrivate(vmf->page);
        set_page_private(vmf->page, priv);
+       file_update_time(file);
 
        sb_end_pagefault(inode->i_sb);
        return VM_FAULT_LOCKED;
index 52d5af5..8c24fdc 100644 (file)
@@ -329,29 +329,6 @@ static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
        *_bp += sizeof(*x) / sizeof(__be32);
 }
 
-/*
- * Deliver a reply that's a status, callback and volsync.
- */
-static int yfs_deliver_fs_status_cb_and_volsync(struct afs_call *call)
-{
-       struct afs_operation *op = call->op;
-       const __be32 *bp;
-       int ret;
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       xdr_decode_YFSFetchStatus(&bp, call, &op->file[0].scb);
-       xdr_decode_YFSCallBack(&bp, call, &op->file[0].scb);
-       xdr_decode_YFSVolSync(&bp, &op->volsync);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * Deliver reply data to operations that just return a file status and a volume
  * sync record.
@@ -374,48 +351,6 @@ static int yfs_deliver_status_and_volsync(struct afs_call *call)
        return 0;
 }
 
-/*
- * YFS.FetchStatus operation type
- */
-static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = {
-       .name           = "YFS.FetchStatus(vnode)",
-       .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
-       .destructor     = afs_flat_call_destructor,
-};
-
-/*
- * Fetch the status information for a file.
- */
-void yfs_fs_fetch_file_status(struct afs_operation *op)
-{
-       struct afs_vnode_param *vp = &op->file[0];
-       struct afs_call *call;
-       __be32 *bp;
-
-       _enter(",%x,{%llx:%llu},,",
-              key_serial(op->key), vp->fid.vid, vp->fid.vnode);
-
-       call = afs_alloc_flat_call(op->net, &yfs_RXYFSFetchStatus_vnode,
-                                  sizeof(__be32) * 2 +
-                                  sizeof(struct yfs_xdr_YFSFid),
-                                  sizeof(struct yfs_xdr_YFSFetchStatus) +
-                                  sizeof(struct yfs_xdr_YFSCallBack) +
-                                  sizeof(struct yfs_xdr_YFSVolSync));
-       if (!call)
-               return afs_op_nomem(op);
-
-       /* marshall the parameters */
-       bp = call->request;
-       bp = xdr_encode_u32(bp, YFSFETCHSTATUS);
-       bp = xdr_encode_u32(bp, 0); /* RPC flags */
-       bp = xdr_encode_YFSFid(bp, &vp->fid);
-       yfs_check_req(call, bp);
-
-       trace_afs_make_fs_call(call, &vp->fid);
-       afs_make_op_call(op, call, GFP_NOFS);
-}
-
 /*
  * Deliver reply data to an YFS.FetchData64.
  */
@@ -1604,13 +1539,37 @@ void yfs_fs_release_lock(struct afs_operation *op)
        afs_make_op_call(op, call, GFP_NOFS);
 }
 
+/*
+ * Deliver a reply to YFS.FetchStatus
+ */
+static int yfs_deliver_fs_fetch_status(struct afs_call *call)
+{
+       struct afs_operation *op = call->op;
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
+       const __be32 *bp;
+       int ret;
+
+       ret = afs_transfer_reply(call);
+       if (ret < 0)
+               return ret;
+
+       /* unmarshall the reply once we've received all of it */
+       bp = call->buffer;
+       xdr_decode_YFSFetchStatus(&bp, call, &vp->scb);
+       xdr_decode_YFSCallBack(&bp, call, &vp->scb);
+       xdr_decode_YFSVolSync(&bp, &op->volsync);
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
 /*
  * YFS.FetchStatus operation type
  */
 static const struct afs_call_type yfs_RXYFSFetchStatus = {
        .name           = "YFS.FetchStatus",
        .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
+       .deliver        = yfs_deliver_fs_fetch_status,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -1619,7 +1578,7 @@ static const struct afs_call_type yfs_RXYFSFetchStatus = {
  */
 void yfs_fs_fetch_status(struct afs_operation *op)
 {
-       struct afs_vnode_param *vp = &op->file[0];
+       struct afs_vnode_param *vp = &op->file[op->fetch_status.which];
        struct afs_call *call;
        __be32 *bp;
 
index 7ecddc2..91e7cc4 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -67,7 +67,7 @@ struct aio_ring {
        unsigned        header_length;  /* size of aio_ring */
 
 
-       struct io_event         io_events[0];
+       struct io_event         io_events[];
 }; /* 128 bytes + ring size */
 
 /*
index 4ccb3c9..2e42f47 100644 (file)
@@ -9,7 +9,8 @@ ext4-y  := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
                extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
                indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
                mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
-               super.o symlink.o sysfs.o xattr.o xattr_trusted.o xattr_user.o
+               super.o symlink.o sysfs.o xattr.o xattr_hurd.o xattr_trusted.o \
+               xattr_user.o
 
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)       += acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)                += xattr_security.o
index c654205..1d82336 100644 (file)
@@ -675,6 +675,7 @@ static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
        struct qstr qstr = {.name = str, .len = len };
        const struct dentry *parent = READ_ONCE(dentry->d_parent);
        const struct inode *inode = READ_ONCE(parent->d_inode);
+       char strbuf[DNAME_INLINE_LEN];
 
        if (!inode || !IS_CASEFOLDED(inode) ||
            !EXT4_SB(inode->i_sb)->s_encoding) {
@@ -683,6 +684,21 @@ static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
                return memcmp(str, name->name, len);
        }
 
+       /*
+        * If the dentry name is stored in-line, then it may be concurrently
+        * modified by a rename.  If this happens, the VFS will eventually retry
+        * the lookup, so it doesn't matter what ->d_compare() returns.
+        * However, it's unsafe to call utf8_strncasecmp() with an unstable
+        * string.  Therefore, we have to copy the name into a temporary buffer.
+        */
+       if (len <= DNAME_INLINE_LEN - 1) {
+               memcpy(strbuf, str, len);
+               strbuf[len] = 0;
+               qstr.name = strbuf;
+               /* prevent compiler from optimizing out the temporary buffer */
+               barrier();
+       }
+
        return ext4_ci_compare(inode, name, &qstr, false);
 }
 
index b08841f..42f5060 100644 (file)
@@ -426,13 +426,16 @@ struct flex_groups {
 #define EXT4_VERITY_FL                 0x00100000 /* Verity protected inode */
 #define EXT4_EA_INODE_FL               0x00200000 /* Inode used for large EA */
 /* 0x00400000 was formerly EXT4_EOFBLOCKS_FL */
+
+#define EXT4_DAX_FL                    0x02000000 /* Inode is DAX */
+
 #define EXT4_INLINE_DATA_FL            0x10000000 /* Inode has inline data. */
 #define EXT4_PROJINHERIT_FL            0x20000000 /* Create with parents projid */
 #define EXT4_CASEFOLD_FL               0x40000000 /* Casefolded directory */
 #define EXT4_RESERVED_FL               0x80000000 /* reserved for ext4 lib */
 
-#define EXT4_FL_USER_VISIBLE           0x705BDFFF /* User visible flags */
-#define EXT4_FL_USER_MODIFIABLE                0x604BC0FF /* User modifiable flags */
+#define EXT4_FL_USER_VISIBLE           0x725BDFFF /* User visible flags */
+#define EXT4_FL_USER_MODIFIABLE                0x624BC0FF /* User modifiable flags */
 
 /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
 #define EXT4_FL_XFLAG_VISIBLE          (EXT4_SYNC_FL | \
@@ -440,14 +443,16 @@ struct flex_groups {
                                         EXT4_APPEND_FL | \
                                         EXT4_NODUMP_FL | \
                                         EXT4_NOATIME_FL | \
-                                        EXT4_PROJINHERIT_FL)
+                                        EXT4_PROJINHERIT_FL | \
+                                        EXT4_DAX_FL)
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
                           EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
                           EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
                           EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\
-                          EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL)
+                          EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL |\
+                          EXT4_DAX_FL)
 
 /* Flags that are appropriate for regular files (all but dir-specific ones). */
 #define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL | EXT4_CASEFOLD_FL |\
@@ -459,6 +464,10 @@ struct flex_groups {
 /* The only flags that should be swapped */
 #define EXT4_FL_SHOULD_SWAP (EXT4_HUGE_FILE_FL | EXT4_EXTENTS_FL)
 
+/* Flags which are mutually exclusive to DAX */
+#define EXT4_DAX_MUT_EXCL (EXT4_VERITY_FL | EXT4_ENCRYPT_FL |\
+                          EXT4_JOURNAL_DATA_FL)
+
 /* Mask out flags that are inappropriate for the given type of inode. */
 static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
 {
@@ -499,6 +508,7 @@ enum {
        EXT4_INODE_VERITY       = 20,   /* Verity protected inode */
        EXT4_INODE_EA_INODE     = 21,   /* Inode used for large EA */
 /* 22 was formerly EXT4_INODE_EOFBLOCKS */
+       EXT4_INODE_DAX          = 25,   /* Inode is DAX */
        EXT4_INODE_INLINE_DATA  = 28,   /* Data in inode. */
        EXT4_INODE_PROJINHERIT  = 29,   /* Create with parents projid */
        EXT4_INODE_CASEFOLD     = 30,   /* Casefolded directory */
@@ -1135,9 +1145,9 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_MINIX_DF            0x00080 /* Mimics the Minix statfs */
 #define EXT4_MOUNT_NOLOAD              0x00100 /* Don't use existing journal*/
 #ifdef CONFIG_FS_DAX
-#define EXT4_MOUNT_DAX                 0x00200 /* Direct Access */
+#define EXT4_MOUNT_DAX_ALWAYS          0x00200 /* Direct Access */
 #else
-#define EXT4_MOUNT_DAX                 0
+#define EXT4_MOUNT_DAX_ALWAYS          0
 #endif
 #define EXT4_MOUNT_DATA_FLAGS          0x00C00 /* Mode for data writes: */
 #define EXT4_MOUNT_JOURNAL_DATA                0x00400 /* Write data to journal */
@@ -1180,6 +1190,8 @@ struct ext4_inode_info {
                                                      blocks */
 #define EXT4_MOUNT2_HURD_COMPAT                0x00000004 /* Support HURD-castrated
                                                      file systems */
+#define EXT4_MOUNT2_DAX_NEVER          0x00000008 /* Do not allow Direct Access */
+#define EXT4_MOUNT2_DAX_INODE          0x00000010 /* For printing options only */
 
 #define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM  0x00000008 /* User explicitly
                                                specified journal checksum */
@@ -1992,6 +2004,7 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
  */
 #define EXT4_FLAGS_RESIZING    0
 #define EXT4_FLAGS_SHUTDOWN    1
+#define EXT4_FLAGS_BDEV_IS_DAX 2
 
 static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
 {
@@ -2705,7 +2718,7 @@ extern int ext4_can_truncate(struct inode *inode);
 extern int ext4_truncate(struct inode *);
 extern int ext4_break_layouts(struct inode *);
 extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
-extern void ext4_set_inode_flags(struct inode *);
+extern void ext4_set_inode_flags(struct inode *, bool init);
 extern int ext4_alloc_da_blocks(struct inode *inode);
 extern void ext4_set_aops(struct inode *inode);
 extern int ext4_writepage_trans_blocks(struct inode *);
index 7d088ff..221f240 100644 (file)
@@ -2844,7 +2844,7 @@ again:
                         * in use to avoid freeing it when removing blocks.
                         */
                        if (sbi->s_cluster_ratio > 1) {
-                               pblk = ext4_ext_pblock(ex) + end - ee_block + 2;
+                               pblk = ext4_ext_pblock(ex) + end - ee_block + 1;
                                partial.pclu = EXT4_B2C(sbi, pblk);
                                partial.state = nofree;
                        }
index 54d324e..df25d38 100644 (file)
@@ -1116,7 +1116,7 @@ got:
        ei->i_block_group = group;
        ei->i_last_alloc_group = ~0;
 
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, true);
        if (IS_DIRSYNC(inode))
                ext4_handle_sync(handle);
        if (insert_inode_locked(inode) < 0) {
index 40ec5c7..10dd470 100644 (file)
@@ -4403,9 +4403,11 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
                !ext4_test_inode_state(inode, EXT4_STATE_XATTR));
 }
 
-static bool ext4_should_use_dax(struct inode *inode)
+static bool ext4_should_enable_dax(struct inode *inode)
 {
-       if (!test_opt(inode->i_sb, DAX))
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+
+       if (test_opt2(inode->i_sb, DAX_NEVER))
                return false;
        if (!S_ISREG(inode->i_mode))
                return false;
@@ -4417,14 +4419,21 @@ static bool ext4_should_use_dax(struct inode *inode)
                return false;
        if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY))
                return false;
-       return true;
+       if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags))
+               return false;
+       if (test_opt(inode->i_sb, DAX_ALWAYS))
+               return true;
+
+       return ext4_test_inode_flag(inode, EXT4_INODE_DAX);
 }
 
-void ext4_set_inode_flags(struct inode *inode)
+void ext4_set_inode_flags(struct inode *inode, bool init)
 {
        unsigned int flags = EXT4_I(inode)->i_flags;
        unsigned int new_fl = 0;
 
+       WARN_ON_ONCE(IS_DAX(inode) && init);
+
        if (flags & EXT4_SYNC_FL)
                new_fl |= S_SYNC;
        if (flags & EXT4_APPEND_FL)
@@ -4435,8 +4444,13 @@ void ext4_set_inode_flags(struct inode *inode)
                new_fl |= S_NOATIME;
        if (flags & EXT4_DIRSYNC_FL)
                new_fl |= S_DIRSYNC;
-       if (ext4_should_use_dax(inode))
+
+       /* Because of the way inode_set_flags() works we must preserve S_DAX
+        * here if already set. */
+       new_fl |= (inode->i_flags & S_DAX);
+       if (init && ext4_should_enable_dax(inode))
                new_fl |= S_DAX;
+
        if (flags & EXT4_ENCRYPT_FL)
                new_fl |= S_ENCRYPTED;
        if (flags & EXT4_CASEFOLD_FL)
@@ -4650,7 +4664,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                 * not initialized on a new filesystem. */
        }
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, true);
        inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
        ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
        if (ext4_has_feature_64bit(sb))
index 2162db0..999cf6a 100644 (file)
@@ -292,6 +292,38 @@ static int ext4_ioctl_check_immutable(struct inode *inode, __u32 new_projid,
        return 0;
 }
 
+static void ext4_dax_dontcache(struct inode *inode, unsigned int flags)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+
+       if (S_ISDIR(inode->i_mode))
+               return;
+
+       if (test_opt2(inode->i_sb, DAX_NEVER) ||
+           test_opt(inode->i_sb, DAX_ALWAYS))
+               return;
+
+       if ((ei->i_flags ^ flags) & EXT4_DAX_FL)
+               d_mark_dontcache(inode);
+}
+
+static bool dax_compatible(struct inode *inode, unsigned int oldflags,
+                          unsigned int flags)
+{
+       if (flags & EXT4_DAX_FL) {
+               if ((oldflags & EXT4_DAX_MUT_EXCL) ||
+                    ext4_test_inode_state(inode,
+                                         EXT4_STATE_VERITY_IN_PROGRESS)) {
+                       return false;
+               }
+       }
+
+       if ((flags & EXT4_DAX_MUT_EXCL) && (oldflags & EXT4_DAX_FL))
+                       return false;
+
+       return true;
+}
+
 static int ext4_ioctl_setflags(struct inode *inode,
                               unsigned int flags)
 {
@@ -300,7 +332,6 @@ static int ext4_ioctl_setflags(struct inode *inode,
        int err = -EPERM, migrate = 0;
        struct ext4_iloc iloc;
        unsigned int oldflags, mask, i;
-       unsigned int jflag;
        struct super_block *sb = inode->i_sb;
 
        /* Is it quota file? Do not allow user to mess with it */
@@ -309,9 +340,6 @@ static int ext4_ioctl_setflags(struct inode *inode,
 
        oldflags = ei->i_flags;
 
-       /* The JOURNAL_DATA flag is modifiable only by root */
-       jflag = flags & EXT4_JOURNAL_DATA_FL;
-
        err = vfs_ioc_setflags_prepare(inode, oldflags, flags);
        if (err)
                goto flags_out;
@@ -320,10 +348,16 @@ static int ext4_ioctl_setflags(struct inode *inode,
         * The JOURNAL_DATA flag can only be changed by
         * the relevant capability.
         */
-       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+       if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
                if (!capable(CAP_SYS_RESOURCE))
                        goto flags_out;
        }
+
+       if (!dax_compatible(inode, oldflags, flags)) {
+               err = -EOPNOTSUPP;
+               goto flags_out;
+       }
+
        if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
                migrate = 1;
 
@@ -369,6 +403,8 @@ static int ext4_ioctl_setflags(struct inode *inode,
        if (err)
                goto flags_err;
 
+       ext4_dax_dontcache(inode, flags);
+
        for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
                if (!(mask & EXT4_FL_USER_MODIFIABLE))
                        continue;
@@ -381,7 +417,8 @@ static int ext4_ioctl_setflags(struct inode *inode,
                        ext4_clear_inode_flag(inode, i);
        }
 
-       ext4_set_inode_flags(inode);
+       ext4_set_inode_flags(inode, false);
+
        inode->i_ctime = current_time(inode);
 
        err = ext4_mark_iloc_dirty(handle, inode, &iloc);
@@ -390,17 +427,18 @@ flags_err:
        if (err)
                goto flags_out;
 
-       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+       if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
                /*
                 * Changes to the journaling mode can cause unsafe changes to
-                * S_DAX if we are using the DAX mount option.
+                * S_DAX if the inode is DAX
                 */
-               if (test_opt(inode->i_sb, DAX)) {
+               if (IS_DAX(inode)) {
                        err = -EBUSY;
                        goto flags_out;
                }
 
-               err = ext4_change_inode_journal_flag(inode, jflag);
+               err = ext4_change_inode_journal_flag(inode,
+                                                    flags & EXT4_JOURNAL_DATA_FL);
                if (err)
                        goto flags_out;
        }
@@ -527,12 +565,15 @@ static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
                xflags |= FS_XFLAG_NOATIME;
        if (iflags & EXT4_PROJINHERIT_FL)
                xflags |= FS_XFLAG_PROJINHERIT;
+       if (iflags & EXT4_DAX_FL)
+               xflags |= FS_XFLAG_DAX;
        return xflags;
 }
 
 #define EXT4_SUPPORTED_FS_XFLAGS (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | \
                                  FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \
-                                 FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT)
+                                 FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT | \
+                                 FS_XFLAG_DAX)
 
 /* Transfer xflags flags to internal */
 static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
@@ -551,6 +592,8 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
                iflags |= EXT4_NOATIME_FL;
        if (xflags & FS_XFLAG_PROJINHERIT)
                iflags |= EXT4_PROJINHERIT_FL;
+       if (xflags & FS_XFLAG_DAX)
+               iflags |= EXT4_DAX_FL;
 
        return iflags;
 }
index a908311..c0a331e 100644 (file)
@@ -4708,7 +4708,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        }
 
        ac->ac_op = EXT4_MB_HISTORY_PREALLOC;
-       seq = *this_cpu_ptr(&discard_pa_seq);
+       seq = this_cpu_read(discard_pa_seq);
        if (!ext4_mb_use_preallocated(ac)) {
                ac->ac_op = EXT4_MB_HISTORY_ALLOC;
                ext4_mb_normalize_request(ac, ar);
index c668f6b..330957e 100644 (file)
@@ -522,9 +522,6 @@ static void ext4_handle_error(struct super_block *sb)
                smp_wmb();
                sb->s_flags |= SB_RDONLY;
        } else if (test_opt(sb, ERRORS_PANIC)) {
-               if (EXT4_SB(sb)->s_journal &&
-                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
-                       return;
                panic("EXT4-fs (device %s): panic forced after error\n",
                        sb->s_id);
        }
@@ -725,23 +722,20 @@ void __ext4_abort(struct super_block *sb, const char *function,
        va_end(args);
 
        if (sb_rdonly(sb) == 0) {
-               ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
                EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+               if (EXT4_SB(sb)->s_journal)
+                       jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+
+               ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
                /*
                 * Make sure updated value of ->s_mount_flags will be visible
                 * before ->s_flags update
                 */
                smp_wmb();
                sb->s_flags |= SB_RDONLY;
-               if (EXT4_SB(sb)->s_journal)
-                       jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
        }
-       if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
-               if (EXT4_SB(sb)->s_journal &&
-                 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
-                       return;
+       if (test_opt(sb, ERRORS_PANIC) && !system_going_down())
                panic("EXT4-fs panic from previous error\n");
-       }
 }
 
 void __ext4_msg(struct super_block *sb,
@@ -1324,6 +1318,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
        if (WARN_ON_ONCE(IS_DAX(inode) && i_size_read(inode)))
                return -EINVAL;
 
+       if (ext4_test_inode_flag(inode, EXT4_INODE_DAX))
+               return -EOPNOTSUPP;
+
        res = ext4_convert_inline_data(inode);
        if (res)
                return res;
@@ -1349,7 +1346,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
                         * Update inode->i_flags - S_ENCRYPTED will be enabled,
                         * S_DAX may be disabled
                         */
-                       ext4_set_inode_flags(inode);
+                       ext4_set_inode_flags(inode, false);
                }
                return res;
        }
@@ -1376,7 +1373,7 @@ retry:
                 * Update inode->i_flags - S_ENCRYPTED will be enabled,
                 * S_DAX may be disabled
                 */
-               ext4_set_inode_flags(inode);
+               ext4_set_inode_flags(inode, false);
                res = ext4_mark_inode_dirty(handle, inode);
                if (res)
                        EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
@@ -1514,7 +1511,8 @@ enum {
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
-       Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
+       Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version,
+       Opt_dax, Opt_dax_always, Opt_dax_inode, Opt_dax_never,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error,
        Opt_nowarn_on_error, Opt_mblk_io_submit,
        Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize,
@@ -1581,6 +1579,9 @@ static const match_table_t tokens = {
        {Opt_nobarrier, "nobarrier"},
        {Opt_i_version, "i_version"},
        {Opt_dax, "dax"},
+       {Opt_dax_always, "dax=always"},
+       {Opt_dax_inode, "dax=inode"},
+       {Opt_dax_never, "dax=never"},
        {Opt_stripe, "stripe=%u"},
        {Opt_delalloc, "delalloc"},
        {Opt_warn_on_error, "warn_on_error"},
@@ -1729,6 +1730,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
 #define MOPT_NO_EXT3   0x0200
 #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3)
 #define MOPT_STRING    0x0400
+#define MOPT_SKIP      0x0800
 
 static const struct mount_opts {
        int     token;
@@ -1778,7 +1780,13 @@ static const struct mount_opts {
        {Opt_min_batch_time, 0, MOPT_GTE0},
        {Opt_inode_readahead_blks, 0, MOPT_GTE0},
        {Opt_init_itable, 0, MOPT_GTE0},
-       {Opt_dax, EXT4_MOUNT_DAX, MOPT_SET},
+       {Opt_dax, EXT4_MOUNT_DAX_ALWAYS, MOPT_SET | MOPT_SKIP},
+       {Opt_dax_always, EXT4_MOUNT_DAX_ALWAYS,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
+       {Opt_dax_inode, EXT4_MOUNT2_DAX_INODE,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
+       {Opt_dax_never, EXT4_MOUNT2_DAX_NEVER,
+               MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
        {Opt_stripe, 0, MOPT_GTE0},
        {Opt_resuid, 0, MOPT_GTE0},
        {Opt_resgid, 0, MOPT_GTE0},
@@ -2123,13 +2131,56 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                }
                sbi->s_jquota_fmt = m->mount_opt;
 #endif
-       } else if (token == Opt_dax) {
+       } else if (token == Opt_dax || token == Opt_dax_always ||
+                  token == Opt_dax_inode || token == Opt_dax_never) {
 #ifdef CONFIG_FS_DAX
-               ext4_msg(sb, KERN_WARNING,
-               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
-               sbi->s_mount_opt |= m->mount_opt;
+               switch (token) {
+               case Opt_dax:
+               case Opt_dax_always:
+                       if (is_remount &&
+                           (!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
+                            (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
+                       fail_dax_change_remount:
+                               ext4_msg(sb, KERN_ERR, "can't change "
+                                        "dax mount option while remounting");
+                               return -1;
+                       }
+                       if (is_remount &&
+                           (test_opt(sb, DATA_FLAGS) ==
+                            EXT4_MOUNT_JOURNAL_DATA)) {
+                                   ext4_msg(sb, KERN_ERR, "can't mount with "
+                                            "both data=journal and dax");
+                                   return -1;
+                       }
+                       ext4_msg(sb, KERN_WARNING,
+                               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+                       sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
+                       sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+                       break;
+               case Opt_dax_never:
+                       if (is_remount &&
+                           (!(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
+                            (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS)))
+                               goto fail_dax_change_remount;
+                       sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+                       break;
+               case Opt_dax_inode:
+                       if (is_remount &&
+                           ((sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
+                            (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
+                            !(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_INODE)))
+                               goto fail_dax_change_remount;
+                       sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+                       sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+                       /* Strictly for printing options */
+                       sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_INODE;
+                       break;
+               }
 #else
                ext4_msg(sb, KERN_INFO, "dax option not supported");
+               sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
+               sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
                return -1;
 #endif
        } else if (token == Opt_data_err_abort) {
@@ -2293,7 +2344,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
        for (m = ext4_mount_opts; m->token != Opt_err; m++) {
                int want_set = m->flags & MOPT_SET;
                if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
-                   (m->flags & MOPT_CLEAR_ERR))
+                   (m->flags & MOPT_CLEAR_ERR) || m->flags & MOPT_SKIP)
                        continue;
                if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
                        continue; /* skip if same as the default */
@@ -2353,6 +2404,17 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 
        fscrypt_show_test_dummy_encryption(seq, sep, sb);
 
+       if (test_opt(sb, DAX_ALWAYS)) {
+               if (IS_EXT2_SB(sb))
+                       SEQ_OPTS_PUTS("dax");
+               else
+                       SEQ_OPTS_PUTS("dax=always");
+       } else if (test_opt2(sb, DAX_NEVER)) {
+               SEQ_OPTS_PUTS("dax=never");
+       } else if (test_opt2(sb, DAX_INODE)) {
+               SEQ_OPTS_PUTS("dax=inode");
+       }
+
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -2383,6 +2445,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                ext4_msg(sb, KERN_ERR, "revision level too high, "
                         "forcing read-only mode");
                err = -EROFS;
+               goto done;
        }
        if (read_only)
                goto done;
@@ -4017,7 +4080,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                 "both data=journal and delalloc");
                        goto failed_mount;
                }
-               if (test_opt(sb, DAX)) {
+               if (test_opt(sb, DAX_ALWAYS)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
                                 "both data=journal and dax");
                        goto failed_mount;
@@ -4127,13 +4190,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       if (sbi->s_mount_opt & EXT4_MOUNT_DAX) {
+       if (bdev_dax_supported(sb->s_bdev, blocksize))
+               set_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags);
+
+       if (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) {
                if (ext4_has_feature_inline_data(sb)) {
                        ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
                                        " that may contain inline data");
                        goto failed_mount;
                }
-               if (!bdev_dax_supported(sb->s_bdev, blocksize)) {
+               if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags)) {
                        ext4_msg(sb, KERN_ERR,
                                "DAX unsupported by block device.");
                        goto failed_mount;
@@ -5447,12 +5513,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                        err = -EINVAL;
                        goto restore_opts;
                }
-               if (test_opt(sb, DAX)) {
-                       ext4_msg(sb, KERN_ERR, "can't mount with "
-                                "both data=journal and dax");
-                       err = -EINVAL;
-                       goto restore_opts;
-               }
        } else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) {
                if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
@@ -5468,12 +5528,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
-       if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) {
-               ext4_msg(sb, KERN_WARNING, "warning: refusing change of "
-                       "dax flag with busy inodes while remounting");
-               sbi->s_mount_opt ^= EXT4_MOUNT_DAX;
-       }
-
        if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
                ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
 
index dec1244..bbd5e7e 100644 (file)
@@ -113,6 +113,9 @@ static int ext4_begin_enable_verity(struct file *filp)
        handle_t *handle;
        int err;
 
+       if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX))
+               return -EINVAL;
+
        if (ext4_verity_in_progress(inode))
                return -EBUSY;
 
@@ -241,7 +244,7 @@ static int ext4_end_enable_verity(struct file *filp, const void *desc,
                if (err)
                        goto out_stop;
                ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
-               ext4_set_inode_flags(inode);
+               ext4_set_inode_flags(inode, false);
                err = ext4_mark_iloc_dirty(handle, inode, &iloc);
        }
 out_stop:
index 9b29a40..7d2f657 100644 (file)
@@ -93,6 +93,7 @@ static const struct xattr_handler * const ext4_xattr_handler_map[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
        [EXT4_XATTR_INDEX_SECURITY]          = &ext4_xattr_security_handler,
 #endif
+       [EXT4_XATTR_INDEX_HURD]              = &ext4_xattr_hurd_handler,
 };
 
 const struct xattr_handler *ext4_xattr_handlers[] = {
@@ -105,6 +106,7 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
        &ext4_xattr_security_handler,
 #endif
+       &ext4_xattr_hurd_handler,
        NULL
 };
 
index ffe21ac..730b91f 100644 (file)
@@ -124,6 +124,7 @@ struct ext4_xattr_inode_array {
 extern const struct xattr_handler ext4_xattr_user_handler;
 extern const struct xattr_handler ext4_xattr_trusted_handler;
 extern const struct xattr_handler ext4_xattr_security_handler;
+extern const struct xattr_handler ext4_xattr_hurd_handler;
 
 #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c"
 
diff --git a/fs/ext4/xattr_hurd.c b/fs/ext4/xattr_hurd.c
new file mode 100644 (file)
index 0000000..8cfa74a
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * linux/fs/ext4/xattr_hurd.c
+ * Handler for extended gnu attributes for the Hurd.
+ *
+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2020 by Jan (janneke) Nieuwenhuizen, <janneke@gnu.org>
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include "ext4.h"
+#include "xattr.h"
+
+static bool
+ext4_xattr_hurd_list(struct dentry *dentry)
+{
+       return test_opt(dentry->d_sb, XATTR_USER);
+}
+
+static int
+ext4_xattr_hurd_get(const struct xattr_handler *handler,
+                   struct dentry *unused, struct inode *inode,
+                   const char *name, void *buffer, size_t size)
+{
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+
+       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_HURD,
+                             name, buffer, size);
+}
+
+static int
+ext4_xattr_hurd_set(const struct xattr_handler *handler,
+                   struct dentry *unused, struct inode *inode,
+                   const char *name, const void *value,
+                   size_t size, int flags)
+{
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+
+       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_HURD,
+                             name, value, size, flags);
+}
+
+const struct xattr_handler ext4_xattr_hurd_handler = {
+       .prefix = XATTR_HURD_PREFIX,
+       .list   = ext4_xattr_hurd_list,
+       .get    = ext4_xattr_hurd_get,
+       .set    = ext4_xattr_hurd_set,
+};
index a49d0e6..e494443 100644 (file)
@@ -1140,6 +1140,7 @@ static journal_t *journal_init_common(struct block_device *bdev,
        init_waitqueue_head(&journal->j_wait_commit);
        init_waitqueue_head(&journal->j_wait_updates);
        init_waitqueue_head(&journal->j_wait_reserved);
+       mutex_init(&journal->j_abort_mutex);
        mutex_init(&journal->j_barrier);
        mutex_init(&journal->j_checkpoint_mutex);
        spin_lock_init(&journal->j_revoke_lock);
@@ -1402,7 +1403,8 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
                printk(KERN_ERR "JBD2: Error %d detected when updating "
                       "journal superblock for %s.\n", ret,
                       journal->j_devname);
-               jbd2_journal_abort(journal, ret);
+               if (!is_journal_aborted(journal))
+                       jbd2_journal_abort(journal, ret);
        }
 
        return ret;
@@ -2153,6 +2155,13 @@ void jbd2_journal_abort(journal_t *journal, int errno)
 {
        transaction_t *transaction;
 
+       /*
+        * Lock the aborting procedure until everything is done, this avoid
+        * races between filesystem's error handling flow (e.g. ext4_abort()),
+        * ensure panic after the error info is written into journal's
+        * superblock.
+        */
+       mutex_lock(&journal->j_abort_mutex);
        /*
         * ESHUTDOWN always takes precedence because a file system check
         * caused by any other journal abort error is not required after
@@ -2167,6 +2176,7 @@ void jbd2_journal_abort(journal_t *journal, int errno)
                        journal->j_errno = errno;
                        jbd2_journal_update_sb_errno(journal);
                }
+               mutex_unlock(&journal->j_abort_mutex);
                return;
        }
 
@@ -2188,10 +2198,7 @@ void jbd2_journal_abort(journal_t *journal, int errno)
         * layer could realise that a filesystem check is needed.
         */
        jbd2_journal_update_sb_errno(journal);
-
-       write_lock(&journal->j_state_lock);
-       journal->j_flags |= JBD2_REC_ERR;
-       write_unlock(&journal->j_state_lock);
+       mutex_unlock(&journal->j_abort_mutex);
 }
 
 /**
index 0637271..8ff4d1a 100644 (file)
@@ -259,7 +259,7 @@ struct jffs2_full_dirent
        uint32_t ino; /* == zero for unlink */
        unsigned int nhash;
        unsigned char type;
-       unsigned char name[0];
+       unsigned char name[];
 };
 
 /*
index 60207a2..e4131cb 100644 (file)
@@ -61,7 +61,7 @@ struct jffs2_sum_dirent_flash
        jint32_t ino;           /* == zero for unlink */
        uint8_t nsize;          /* dirent name size */
        uint8_t type;           /* dirent type */
-       uint8_t name[0];        /* dirent name */
+       uint8_t name[]; /* dirent name */
 } __attribute__((packed));
 
 struct jffs2_sum_xattr_flash
@@ -117,7 +117,7 @@ struct jffs2_sum_dirent_mem
        jint32_t ino;           /* == zero for unlink */
        uint8_t nsize;          /* dirent name size */
        uint8_t type;           /* dirent type */
-       uint8_t name[0];        /* dirent name */
+       uint8_t name[]; /* dirent name */
 } __attribute__((packed));
 
 struct jffs2_sum_xattr_mem
index 8ba492d..e502414 100644 (file)
@@ -512,7 +512,8 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                                 * Using bounce buffer to bypass the
                                 * hardened user copy kernel text checks.
                                 */
-                               if (probe_kernel_read(buf, (void *) start, tsz)) {
+                               if (copy_from_kernel_nofault(buf, (void *)start,
+                                               tsz)) {
                                        if (clear_user(buffer, tsz)) {
                                                ret = -EFAULT;
                                                goto out;
index 7187bd1..8d64edb 100644 (file)
@@ -262,7 +262,7 @@ struct squashfs_dir_index {
        __le32                  index;
        __le32                  start_block;
        __le32                  size;
-       unsigned char           name[0];
+       unsigned char           name[];
 };
 
 struct squashfs_base_inode {
@@ -327,7 +327,7 @@ struct squashfs_symlink_inode {
        __le32                  inode_number;
        __le32                  nlink;
        __le32                  symlink_size;
-       char                    symlink[0];
+       char                    symlink[];
 };
 
 struct squashfs_reg_inode {
@@ -341,7 +341,7 @@ struct squashfs_reg_inode {
        __le32                  fragment;
        __le32                  offset;
        __le32                  file_size;
-       __le16                  block_list[0];
+       __le16                  block_list[];
 };
 
 struct squashfs_lreg_inode {
@@ -358,7 +358,7 @@ struct squashfs_lreg_inode {
        __le32                  fragment;
        __le32                  offset;
        __le32                  xattr;
-       __le16                  block_list[0];
+       __le16                  block_list[];
 };
 
 struct squashfs_dir_inode {
@@ -389,7 +389,7 @@ struct squashfs_ldir_inode {
        __le16                  i_count;
        __le16                  offset;
        __le32                  xattr;
-       struct squashfs_dir_index       index[0];
+       struct squashfs_dir_index       index[];
 };
 
 union squashfs_inode {
@@ -410,7 +410,7 @@ struct squashfs_dir_entry {
        __le16                  inode_number;
        __le16                  type;
        __le16                  size;
-       char                    name[0];
+       char                    name[];
 };
 
 struct squashfs_dir_header {
@@ -428,12 +428,12 @@ struct squashfs_fragment_entry {
 struct squashfs_xattr_entry {
        __le16                  type;
        __le16                  size;
-       char                    data[0];
+       char                    data[];
 };
 
 struct squashfs_xattr_val {
        __le32                  vsize;
-       char                    value[0];
+       char                    value[];
 };
 
 struct squashfs_xattr_id {
index 27bdd27..77941ef 100644 (file)
@@ -89,7 +89,7 @@ struct displayid_detailed_timings_1 {
 
 struct displayid_detailed_timing_block {
        struct displayid_block base;
-       struct displayid_detailed_timings_1 timings[0];
+       struct displayid_detailed_timings_1 timings[];
 };
 
 #define for_each_displayid_db(displayid, block, idx, length) \
index 9e9ccb2..38afb34 100644 (file)
@@ -27,7 +27,7 @@ struct encrypted_key_payload {
        unsigned short payload_datalen;         /* payload data length */
        unsigned short encrypted_key_format;    /* encrypted key format */
        u8 *decrypted_data;     /* decrypted data */
-       u8 payload_data[0];     /* payload data + datablob + hmac */
+       u8 payload_data[];      /* payload data + datablob + hmac */
 };
 
 extern struct key_type key_type_encrypted;
index a183278..2b0b15a 100644 (file)
@@ -28,7 +28,7 @@ struct rxkad_key {
        u8      primary_flag;           /* T if key for primary cell for this user */
        u16     ticket_len;             /* length of ticket[] */
        u8      session_key[8];         /* DES session key */
-       u8      ticket[0];              /* the encrypted ticket */
+       u8      ticket[];               /* the encrypted ticket */
 };
 
 /*
@@ -100,7 +100,7 @@ struct rxrpc_key_data_v1 {
        u32             expiry;                 /* time_t */
        u32             kvno;
        u8              session_key[8];
-       u8              ticket[0];
+       u8              ticket[];
 };
 
 /*
index a954def..900b9f4 100644 (file)
@@ -34,7 +34,7 @@
 struct can_skb_priv {
        int ifindex;
        int skbcnt;
-       struct can_frame cf[0];
+       struct can_frame cf[];
 };
 
 static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)
index 60de3fe..405657a 100644 (file)
@@ -36,7 +36,7 @@ struct cb710_chip {
        unsigned                slot_mask;
        unsigned                slots;
        spinlock_t              irq_lock;
-       struct cb710_slot       slot[0];
+       struct cb710_slot       slot[];
 };
 
 /* NOTE: cb710_chip.slots is modified only during device init/exit and
index 2247e71..e5ed1c5 100644 (file)
@@ -52,8 +52,7 @@ struct ceph_options {
        unsigned long osd_idle_ttl;             /* jiffies */
        unsigned long osd_keepalive_timeout;    /* jiffies */
        unsigned long osd_request_timeout;      /* jiffies */
-
-       u32 osd_req_flags;  /* CEPH_OSD_FLAG_*, applied to each OSD request */
+       u32 read_from_replica;  /* CEPH_OSD_FLAG_BALANCE/LOCALIZE_READS */
 
        /*
         * any type that can't be simply compared or doesn't need
@@ -76,6 +75,7 @@ struct ceph_options {
 #define CEPH_OSD_KEEPALIVE_DEFAULT     msecs_to_jiffies(5 * 1000)
 #define CEPH_OSD_IDLE_TTL_DEFAULT      msecs_to_jiffies(60 * 1000)
 #define CEPH_OSD_REQUEST_TIMEOUT_DEFAULT 0  /* no timeout */
+#define CEPH_READ_FROM_REPLICA_DEFAULT 0  /* read from primary */
 
 #define CEPH_MONC_HUNT_INTERVAL                msecs_to_jiffies(3 * 1000)
 #define CEPH_MONC_PING_INTERVAL                msecs_to_jiffies(10 * 1000)
index 21aed09..e368384 100644 (file)
@@ -5,20 +5,20 @@
 #ifndef __ASSEMBLY__
 
 #ifdef __CHECKER__
-# define __user                __attribute__((noderef, address_space(1)))
 # define __kernel      __attribute__((address_space(0)))
+# define __user                __attribute__((noderef, address_space(__user)))
 # define __safe                __attribute__((safe))
 # define __force       __attribute__((force))
 # define __nocast      __attribute__((nocast))
-# define __iomem       __attribute__((noderef, address_space(2)))
+# define __iomem       __attribute__((noderef, address_space(__iomem)))
 # define __must_hold(x)        __attribute__((context(x,1,1)))
 # define __acquires(x) __attribute__((context(x,0,1)))
 # define __releases(x) __attribute__((context(x,1,0)))
 # define __acquire(x)  __context__(x,1)
 # define __release(x)  __context__(x,-1)
 # define __cond_lock(x,c)      ((c) ? ({ __acquire(x); 1; }) : 0)
-# define __percpu      __attribute__((noderef, address_space(3)))
-# define __rcu         __attribute__((noderef, address_space(4)))
+# define __percpu      __attribute__((noderef, address_space(__percpu)))
+# define __rcu         __attribute__((noderef, address_space(__rcu)))
 # define __private     __attribute__((noderef))
 extern void __chk_user_ptr(const volatile void __user *);
 extern void __chk_io_ptr(const volatile void __iomem *);
index e1c0333..6283917 100644 (file)
@@ -153,7 +153,7 @@ struct dma_interleaved_template {
        bool dst_sgl;
        size_t numf;
        size_t frame_size;
-       struct data_chunk sgl[0];
+       struct data_chunk sgl[];
 };
 
 /**
@@ -535,7 +535,7 @@ struct dmaengine_unmap_data {
        struct device *dev;
        struct kref kref;
        size_t len;
-       dma_addr_t addr[0];
+       dma_addr_t addr[];
 };
 
 struct dma_async_tx_descriptor;
index ce0b5fb..3f0b19d 100644 (file)
@@ -46,7 +46,7 @@ struct fscache_cache_tag {
        unsigned long           flags;
 #define FSCACHE_TAG_RESERVED   0               /* T if tag is reserved for a cache */
        atomic_t                usage;
-       char                    name[0];        /* tag name */
+       char                    name[]; /* tag name */
 };
 
 /*
index f613d85..d56128d 100644 (file)
@@ -765,6 +765,11 @@ struct journal_s
         */
        int                     j_errno;
 
+       /**
+        * @j_abort_mutex: Lock the whole aborting procedure.
+        */
+       struct mutex            j_abort_mutex;
+
        /**
         * @j_sb_buffer: The first part of the superblock buffer.
         */
@@ -1247,7 +1252,6 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3,                CSUM_V3)
 #define JBD2_ABORT_ON_SYNCDATA_ERR     0x040   /* Abort the journal on file
                                                 * data write error in ordered
                                                 * mode */
-#define JBD2_REC_ERR   0x080   /* The errno in the sb has been recorded */
 
 /*
  * Function declarations for the journaling transaction and buffer
index 1776eb2..ea67910 100644 (file)
@@ -208,7 +208,7 @@ struct crash_mem_range {
 struct crash_mem {
        unsigned int max_nr_ranges;
        unsigned int nr_ranges;
-       struct crash_mem_range ranges[0];
+       struct crash_mem_range ranges[];
 };
 
 extern int crash_exclude_mem_range(struct crash_mem *mem,
index 594265b..e210af7 100644 (file)
@@ -161,7 +161,7 @@ struct kretprobe_instance {
        kprobe_opcode_t *ret_addr;
        struct task_struct *task;
        void *fp;
-       char data[0];
+       char data[];
 };
 
 struct kretprobe_blackpoint {
index 62ec926..d564855 100644 (file)
@@ -409,7 +409,7 @@ struct kvm_irq_routing_table {
         * Array indexed by gsi. Each entry contains list of irq chips
         * the gsi is connected to.
         */
-       struct hlist_head map[0];
+       struct hlist_head map[];
 };
 #endif
 
index af83285..675895f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/acpi.h>
 #include <linux/cdrom.h>
 #include <linux/sched.h>
+#include <linux/async.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -609,7 +610,7 @@ struct ata_host {
        struct task_struct      *eh_owner;
 
        struct ata_port         *simplex_claimed;       /* channel owning the DMA */
-       struct ata_port         *ports[0];
+       struct ata_port         *ports[];
 };
 
 struct ata_queued_cmd {
@@ -872,6 +873,8 @@ struct ata_port {
        struct timer_list       fastdrain_timer;
        unsigned long           fastdrain_cnt;
 
+       async_cookie_t          cookie;
+
        int                     em_message_type;
        void                    *private_data;
 
index 6590450..93fcef1 100644 (file)
@@ -304,16 +304,33 @@ static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
  * struct_size() - Calculate size of structure with trailing array.
  * @p: Pointer to the structure.
  * @member: Name of the array member.
- * @n: Number of elements in the array.
+ * @count: Number of elements in the array.
  *
  * Calculates size of memory needed for structure @p followed by an
- * array of @n @member elements.
+ * array of @count number of @member elements.
  *
  * Return: number of bytes needed or SIZE_MAX on overflow.
  */
-#define struct_size(p, member, n)                                      \
-       __ab_c_size(n,                                                  \
+#define struct_size(p, member, count)                                  \
+       __ab_c_size(count,                                              \
                    sizeof(*(p)->member) + __must_be_array((p)->member),\
                    sizeof(*(p)))
 
+/**
+ * flex_array_size() - Calculate size of a flexible array member
+ *                     within an enclosing structure.
+ *
+ * @p: Pointer to the structure.
+ * @member: Name of the flexible array member.
+ * @count: Number of elements in the array.
+ *
+ * Calculates size of a flexible array of @count number of @member
+ * elements, at the end of structure @p.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define flex_array_size(p, member, count)                              \
+       array_size(count,                                               \
+                   sizeof(*(p)->member) + __must_be_array((p)->member))
+
 #endif /* __LINUX_OVERFLOW_H */
index 8ccd821..7673123 100644 (file)
@@ -221,7 +221,7 @@ struct sctp_datahdr {
        __be16 stream;
        __be16 ssn;
        __u32 ppid;
-       __u8  payload[0];
+       __u8  payload[];
 };
 
 struct sctp_data_chunk {
@@ -269,7 +269,7 @@ struct sctp_inithdr {
        __be16 num_outbound_streams;
        __be16 num_inbound_streams;
        __be32 initial_tsn;
-       __u8  params[0];
+       __u8  params[];
 };
 
 struct sctp_init_chunk {
@@ -299,13 +299,13 @@ struct sctp_cookie_preserve_param {
 /* Section 3.3.2.1 Host Name Address (11) */
 struct sctp_hostname_param {
        struct sctp_paramhdr param_hdr;
-       uint8_t hostname[0];
+       uint8_t hostname[];
 };
 
 /* Section 3.3.2.1 Supported Address Types (12) */
 struct sctp_supported_addrs_param {
        struct sctp_paramhdr param_hdr;
-       __be16 types[0];
+       __be16 types[];
 };
 
 /* ADDIP Section 3.2.6 Adaptation Layer Indication */
@@ -317,25 +317,25 @@ struct sctp_adaptation_ind_param {
 /* ADDIP Section 4.2.7 Supported Extensions Parameter */
 struct sctp_supported_ext_param {
        struct sctp_paramhdr param_hdr;
-       __u8 chunks[0];
+       __u8 chunks[];
 };
 
 /* AUTH Section 3.1 Random */
 struct sctp_random_param {
        struct sctp_paramhdr param_hdr;
-       __u8 random_val[0];
+       __u8 random_val[];
 };
 
 /* AUTH Section 3.2 Chunk List */
 struct sctp_chunks_param {
        struct sctp_paramhdr param_hdr;
-       __u8 chunks[0];
+       __u8 chunks[];
 };
 
 /* AUTH Section 3.3 HMAC Algorithm */
 struct sctp_hmac_algo_param {
        struct sctp_paramhdr param_hdr;
-       __be16 hmac_ids[0];
+       __be16 hmac_ids[];
 };
 
 /* RFC 2960.  Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
@@ -350,7 +350,7 @@ struct sctp_initack_chunk {
 /* Section 3.3.3.1 State Cookie (7) */
 struct sctp_cookie_param {
        struct sctp_paramhdr p;
-       __u8 body[0];
+       __u8 body[];
 };
 
 /* Section 3.3.3.1 Unrecognized Parameters (8) */
@@ -384,7 +384,7 @@ struct sctp_sackhdr {
        __be32 a_rwnd;
        __be16 num_gap_ack_blocks;
        __be16 num_dup_tsns;
-       union sctp_sack_variable variable[0];
+       union sctp_sack_variable variable[];
 };
 
 struct sctp_sack_chunk {
@@ -436,7 +436,7 @@ struct sctp_shutdown_chunk {
 struct sctp_errhdr {
        __be16 cause;
        __be16 length;
-       __u8  variable[0];
+       __u8  variable[];
 };
 
 struct sctp_operr_chunk {
@@ -594,7 +594,7 @@ struct sctp_fwdtsn_skip {
 
 struct sctp_fwdtsn_hdr {
        __be32 new_cum_tsn;
-       struct sctp_fwdtsn_skip skip[0];
+       struct sctp_fwdtsn_skip skip[];
 };
 
 struct sctp_fwdtsn_chunk {
@@ -611,7 +611,7 @@ struct sctp_ifwdtsn_skip {
 
 struct sctp_ifwdtsn_hdr {
        __be32 new_cum_tsn;
-       struct sctp_ifwdtsn_skip skip[0];
+       struct sctp_ifwdtsn_skip skip[];
 };
 
 struct sctp_ifwdtsn_chunk {
@@ -658,7 +658,7 @@ struct sctp_addip_param {
 
 struct sctp_addiphdr {
        __be32  serial;
-       __u8    params[0];
+       __u8    params[];
 };
 
 struct sctp_addip_chunk {
@@ -718,7 +718,7 @@ struct sctp_addip_chunk {
 struct sctp_authhdr {
        __be16 shkey_id;
        __be16 hmac_id;
-       __u8   hmac[0];
+       __u8   hmac[];
 };
 
 struct sctp_auth_chunk {
@@ -733,7 +733,7 @@ struct sctp_infox {
 
 struct sctp_reconf_chunk {
        struct sctp_chunkhdr chunk_hdr;
-       __u8 params[0];
+       __u8 params[];
 };
 
 struct sctp_strreset_outreq {
@@ -741,13 +741,13 @@ struct sctp_strreset_outreq {
        __be32 request_seq;
        __be32 response_seq;
        __be32 send_reset_at_tsn;
-       __be16 list_of_streams[0];
+       __be16 list_of_streams[];
 };
 
 struct sctp_strreset_inreq {
        struct sctp_paramhdr param_hdr;
        __be32 request_seq;
-       __be16 list_of_streams[0];
+       __be16 list_of_streams[];
 };
 
 struct sctp_strreset_tsnreq {
index 299cbb8..44073d0 100644 (file)
@@ -124,7 +124,7 @@ struct tifm_adapter {
        int                 (*has_ms_pif)(struct tifm_adapter *fm,
                                          struct tifm_dev *sock);
 
-       struct tifm_dev     *sockets[0];
+       struct tifm_dev     *sockets[];
 };
 
 struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
index 7bcadca..0a76ddc 100644 (file)
@@ -301,13 +301,14 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
        return 0;
 }
 
-bool probe_kernel_read_allowed(const void *unsafe_src, size_t size);
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size);
 
-extern long probe_kernel_read(void *dst, const void *src, size_t size);
-extern long probe_user_read(void *dst, const void __user *src, size_t size);
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
+long notrace copy_to_kernel_nofault(void *dst, const void *src, size_t size);
 
-extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
-extern long notrace probe_user_write(void __user *dst, const void *src, size_t size);
+long copy_from_user_nofault(void *dst, const void __user *src, size_t size);
+long notrace copy_to_user_nofault(void __user *dst, const void *src,
+               size_t size);
 
 long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr,
                long count);
@@ -317,14 +318,16 @@ long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
 long strnlen_user_nofault(const void __user *unsafe_addr, long count);
 
 /**
- * probe_kernel_address(): safely attempt to read from a location
- * @addr: address to read from
- * @retval: read into this variable
+ * get_kernel_nofault(): safely attempt to read from a location
+ * @val: read into this variable
+ * @ptr: address to read from
  *
  * Returns 0 on success, or -EFAULT.
  */
-#define probe_kernel_address(addr, retval)             \
-       probe_kernel_read(&retval, addr, sizeof(retval))
+#define get_kernel_nofault(val, ptr) ({                                \
+       const typeof(val) *__gk_ptr = (ptr);                    \
+       copy_from_kernel_nofault(&(val), __gk_ptr, sizeof(val));\
+})
 
 #ifndef user_access_begin
 #define user_access_begin(ptr,len) access_ok(ptr, len)
index d7338bf..16e8b2f 100644 (file)
@@ -161,10 +161,51 @@ struct nf_flow_route {
 struct flow_offload *flow_offload_alloc(struct nf_conn *ct);
 void flow_offload_free(struct flow_offload *flow);
 
-int nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
-                                flow_setup_cb_t *cb, void *cb_priv);
-void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
-                                 flow_setup_cb_t *cb, void *cb_priv);
+static inline int
+nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
+                            flow_setup_cb_t *cb, void *cb_priv)
+{
+       struct flow_block *block = &flow_table->flow_block;
+       struct flow_block_cb *block_cb;
+       int err = 0;
+
+       down_write(&flow_table->flow_block_lock);
+       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
+       if (block_cb) {
+               err = -EEXIST;
+               goto unlock;
+       }
+
+       block_cb = flow_block_cb_alloc(cb, cb_priv, cb_priv, NULL);
+       if (IS_ERR(block_cb)) {
+               err = PTR_ERR(block_cb);
+               goto unlock;
+       }
+
+       list_add_tail(&block_cb->list, &block->cb_list);
+
+unlock:
+       up_write(&flow_table->flow_block_lock);
+       return err;
+}
+
+static inline void
+nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
+                            flow_setup_cb_t *cb, void *cb_priv)
+{
+       struct flow_block *block = &flow_table->flow_block;
+       struct flow_block_cb *block_cb;
+
+       down_write(&flow_table->flow_block_lock);
+       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
+       if (block_cb) {
+               list_del(&block_cb->list);
+               flow_block_cb_free(block_cb);
+       } else {
+               WARN_ON(true);
+       }
+       up_write(&flow_table->flow_block_lock);
+}
 
 int flow_offload_route_init(struct flow_offload *flow,
                            const struct nf_flow_route *route);
index 79654bc..8250d6f 100644 (file)
@@ -66,7 +66,16 @@ static inline struct nf_flowtable *tcf_ct_ft(const struct tc_action *a)
 #endif /* CONFIG_NF_CONNTRACK */
 
 #if IS_ENABLED(CONFIG_NET_ACT_CT)
-void tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie);
+static inline void
+tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie)
+{
+       enum ip_conntrack_info ctinfo = cookie & NFCT_INFOMASK;
+       struct nf_conn *ct;
+
+       ct = (struct nf_conn *)(cookie & NFCT_PTRMASK);
+       nf_conntrack_get(&ct->ct_general);
+       nf_ct_set(skb, ct, ctinfo);
+}
 #else
 static inline void
 tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie) { }
index 379a612..f44eb0a 100644 (file)
@@ -262,6 +262,7 @@ struct fsxattr {
 #define FS_EA_INODE_FL                 0x00200000 /* Inode used for large EA */
 #define FS_EOFBLOCKS_FL                        0x00400000 /* Reserved for ext4 */
 #define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
+#define FS_DAX_FL                      0x02000000 /* Inode is DAX */
 #define FS_INLINE_DATA_FL              0x10000000 /* Reserved for ext4 */
 #define FS_PROJINHERIT_FL              0x20000000 /* Create with parents projid */
 #define FS_CASEFOLD_FL                 0x40000000 /* Folder is case insensitive */
index c1395b5..9463db2 100644 (file)
@@ -7,6 +7,7 @@
   Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
   Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
   Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+  Copyright (c) 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 */
 
 #include <linux/libc-compat.h>
@@ -31,6 +32,9 @@
 #define XATTR_BTRFS_PREFIX "btrfs."
 #define XATTR_BTRFS_PREFIX_LEN (sizeof(XATTR_BTRFS_PREFIX) - 1)
 
+#define XATTR_HURD_PREFIX "gnu."
+#define XATTR_HURD_PREFIX_LEN (sizeof(XATTR_HURD_PREFIX) - 1)
+
 #define XATTR_SECURITY_PREFIX  "security."
 #define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1)
 
index ccc0f98..bc8d25f 100644 (file)
@@ -169,18 +169,18 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
        int err;
 
-       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+       err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
                                BREAK_INSTR_SIZE);
        if (err)
                return err;
-       err = probe_kernel_write((char *)bpt->bpt_addr,
+       err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
        return err;
 }
 
 int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-       return probe_kernel_write((char *)bpt->bpt_addr,
+       return copy_to_kernel_nofault((char *)bpt->bpt_addr,
                                  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
index 4b280fc..61774ae 100644 (file)
@@ -247,7 +247,7 @@ char *kgdb_mem2hex(char *mem, char *buf, int count)
         */
        tmp = buf + count;
 
-       err = probe_kernel_read(tmp, mem, count);
+       err = copy_from_kernel_nofault(tmp, mem, count);
        if (err)
                return NULL;
        while (count > 0) {
@@ -283,7 +283,7 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
                *tmp_raw |= hex_to_bin(*tmp_hex--) << 4;
        }
 
-       return probe_kernel_write(mem, tmp_raw, count);
+       return copy_to_kernel_nofault(mem, tmp_raw, count);
 }
 
 /*
@@ -335,7 +335,7 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count)
                size++;
        }
 
-       return probe_kernel_write(mem, c, size);
+       return copy_to_kernel_nofault(mem, c, size);
 }
 
 #if DBG_MAX_REG_NUM > 0
index ec19056..5c79490 100644 (file)
@@ -2326,7 +2326,8 @@ void kdb_ps1(const struct task_struct *p)
        int cpu;
        unsigned long tmp;
 
-       if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
+       if (!p ||
+           copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
                return;
 
        cpu = kdb_process_cpu(p);
index b8e6306..004c5b6 100644 (file)
@@ -325,7 +325,7 @@ char *kdb_strdup(const char *str, gfp_t type)
  */
 int kdb_getarea_size(void *res, unsigned long addr, size_t size)
 {
-       int ret = probe_kernel_read((char *)res, (char *)addr, size);
+       int ret = copy_from_kernel_nofault((char *)res, (char *)addr, size);
        if (ret) {
                if (!KDB_STATE(SUPPRESS)) {
                        kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
@@ -350,7 +350,7 @@ int kdb_getarea_size(void *res, unsigned long addr, size_t size)
  */
 int kdb_putarea_size(unsigned long addr, void *res, size_t size)
 {
-       int ret = probe_kernel_read((char *)addr, (char *)res, size);
+       int ret = copy_from_kernel_nofault((char *)addr, (char *)res, size);
        if (ret) {
                if (!KDB_STATE(SUPPRESS)) {
                        kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
@@ -624,7 +624,8 @@ char kdb_task_state_char (const struct task_struct *p)
        char state;
        unsigned long tmp;
 
-       if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
+       if (!p ||
+           copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
                return 'E';
 
        cpu = kdb_process_cpu(p);
index d006668..a0ce3c1 100644 (file)
@@ -73,18 +73,18 @@ config SWIOTLB
 config DMA_NONCOHERENT_MMAP
        bool
 
+config DMA_COHERENT_POOL
+       bool
+
 config DMA_REMAP
+       bool
        depends on MMU
        select GENERIC_ALLOCATOR
        select DMA_NONCOHERENT_MMAP
-       bool
-
-config DMA_COHERENT_POOL
-       bool
-       select DMA_REMAP
 
 config DMA_DIRECT_REMAP
        bool
+       select DMA_REMAP
        select DMA_COHERENT_POOL
 
 config DMA_CMA
index 35bb51c..8cfa012 100644 (file)
@@ -175,10 +175,9 @@ static int __init dma_atomic_pool_init(void)
         * sizes to 128KB per 1GB of memory, min 128KB, max MAX_ORDER-1.
         */
        if (!atomic_pool_size) {
-               atomic_pool_size = max(totalram_pages() >> PAGE_SHIFT, 1UL) *
-                                       SZ_128K;
-               atomic_pool_size = min_t(size_t, atomic_pool_size,
-                                        1 << (PAGE_SHIFT + MAX_ORDER-1));
+               unsigned long pages = totalram_pages() / (SZ_1G / SZ_128K);
+               pages = min_t(unsigned long, pages, MAX_ORDER_NR_PAGES);
+               atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, SZ_128K);
        }
        INIT_WORK(&atomic_pool_work, atomic_pool_work_fn);
 
index 8e3d2d7..132f84a 100644 (file)
@@ -201,7 +201,7 @@ void *kthread_probe_data(struct task_struct *task)
        struct kthread *kthread = to_kthread(task);
        void *data = NULL;
 
-       probe_kernel_read(&data, &kthread->data, sizeof(data));
+       copy_from_kernel_nofault(&data, &kthread->data, sizeof(data));
        return data;
 }
 
index e729c9e..dc05626 100644 (file)
@@ -141,7 +141,7 @@ bpf_probe_read_user_common(void *dst, u32 size, const void __user *unsafe_ptr)
 {
        int ret;
 
-       ret = probe_user_read(dst, unsafe_ptr, size);
+       ret = copy_from_user_nofault(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
                memset(dst, 0, size);
        return ret;
@@ -196,7 +196,7 @@ bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
 
        if (unlikely(ret < 0))
                goto fail;
-       ret = probe_kernel_read(dst, unsafe_ptr, size);
+       ret = copy_from_kernel_nofault(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
                goto fail;
        return ret;
@@ -326,7 +326,7 @@ BPF_CALL_3(bpf_probe_write_user, void __user *, unsafe_ptr, const void *, src,
        if (unlikely(!nmi_uaccess_okay()))
                return -EPERM;
 
-       return probe_user_write(unsafe_ptr, src, size);
+       return copy_to_user_nofault(unsafe_ptr, src, size);
 }
 
 static const struct bpf_func_proto bpf_probe_write_user_proto = {
@@ -661,7 +661,7 @@ BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size,
 
                        copy_size = (fmt[i + 2] == '4') ? 4 : 16;
 
-                       err = probe_kernel_read(bufs->buf[memcpy_cnt],
+                       err = copy_from_kernel_nofault(bufs->buf[memcpy_cnt],
                                                (void *) (long) args[fmt_cnt],
                                                copy_size);
                        if (err < 0)
index 6048f1b..aefb606 100644 (file)
@@ -1222,7 +1222,7 @@ fetch_store_strlen(unsigned long addr)
 #endif
 
        do {
-               ret = probe_kernel_read(&c, (u8 *)addr + len, 1);
+               ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
                len++;
        } while (c && ret == 0 && len < MAX_STRING_SIZE);
 
@@ -1290,7 +1290,7 @@ probe_mem_read_user(void *dest, void *src, size_t size)
 {
        const void __user *uaddr =  (__force const void __user *)src;
 
-       return probe_user_read(dest, uaddr, size);
+       return copy_from_user_nofault(dest, uaddr, size);
 }
 
 static nokprobe_inline int
@@ -1300,7 +1300,7 @@ probe_mem_read(void *dest, void *src, size_t size)
        if ((unsigned long)src < TASK_SIZE)
                return probe_mem_read_user(dest, src, size);
 #endif
-       return probe_kernel_read(dest, src, size);
+       return copy_from_kernel_nofault(dest, src, size);
 }
 
 /* Note that we don't verify it, since the code does not come from user space */
index a0ff9e2..a22b628 100644 (file)
@@ -236,7 +236,7 @@ struct trace_probe_event {
        struct trace_event_call         call;
        struct list_head                files;
        struct list_head                probes;
-       struct trace_uprobe_filter      filter[0];
+       struct trace_uprobe_filter      filter[];
 };
 
 struct trace_probe {
index 9fbe1e2..c41c3c1 100644 (file)
@@ -4638,11 +4638,11 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
         * Carefully copy the associated workqueue's workfn, name and desc.
         * Keep the original last '\0' in case the original is garbage.
         */
-       probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
-       probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
-       probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
-       probe_kernel_read(name, wq->name, sizeof(name) - 1);
-       probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
+       copy_from_kernel_nofault(&fn, &worker->current_func, sizeof(fn));
+       copy_from_kernel_nofault(&pwq, &worker->current_pwq, sizeof(pwq));
+       copy_from_kernel_nofault(&wq, &pwq->wq, sizeof(wq));
+       copy_from_kernel_nofault(name, wq->name, sizeof(name) - 1);
+       copy_from_kernel_nofault(desc, worker->desc, sizeof(desc) - 1);
 
        if (fn || name[0] || desc[0]) {
                printk("%sWorkqueue: %s %ps", log_lvl, name, fn);
index f258743..bd7c7ff 100644 (file)
@@ -419,8 +419,8 @@ static bool test_kernel_ptr(unsigned long addr, int size)
        /* should be at least readable kernel address */
        if (access_ok(ptr, 1) ||
            access_ok(ptr + size - 1, 1) ||
-           probe_kernel_address(ptr, buf) ||
-           probe_kernel_address(ptr + size - 1, buf)) {
+           get_kernel_nofault(buf, ptr) ||
+           get_kernel_nofault(buf, ptr + size - 1)) {
                pr_err("invalid kernel ptr: %#lx\n", addr);
                return true;
        }
@@ -437,7 +437,7 @@ static bool __maybe_unused test_magic(unsigned long addr, int offset,
        if (!addr)
                return false;
 
-       if (probe_kernel_address(ptr, magic) || magic != expected) {
+       if (get_kernel_nofault(magic, ptr) || magic != expected) {
                pr_err("invalid magic at %#lx + %#x = %#x, expected %#x\n",
                       addr, offset, magic, expected);
                return true;
index 72c1abf..da13793 100644 (file)
@@ -979,10 +979,10 @@ err_check_expect_stats2:
 err_world2_obj_get:
        for (i--; i >= 0; i--)
                world_obj_put(&world2, objagg, hints_case->key_ids[i]);
-       objagg_hints_put(hints);
-       objagg_destroy(objagg2);
        i = hints_case->key_ids_count;
+       objagg_destroy(objagg2);
 err_check_expect_hints_stats:
+       objagg_hints_put(hints);
 err_hints_get:
 err_check_expect_stats:
 err_world_obj_get:
index b5b1de8..4f37651 100644 (file)
@@ -120,9 +120,9 @@ void __dump_page(struct page *page, const char *reason)
                 * mapping can be invalid pointer and we don't want to crash
                 * accessing it, so probe everything depending on it carefully
                 */
-               if (probe_kernel_read(&host, &mapping->host,
+               if (copy_from_kernel_nofault(&host, &mapping->host,
                                        sizeof(struct inode *)) ||
-                   probe_kernel_read(&a_ops, &mapping->a_ops,
+                   copy_from_kernel_nofault(&a_ops, &mapping->a_ops,
                                sizeof(struct address_space_operations *))) {
                        pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n");
                        goto out_mapping;
@@ -133,7 +133,7 @@ void __dump_page(struct page *page, const char *reason)
                        goto out_mapping;
                }
 
-               if (probe_kernel_read(&dentry_first,
+               if (copy_from_kernel_nofault(&dentry_first,
                        &host->i_dentry.first, sizeof(struct hlist_node *))) {
                        pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n",
                                a_ops, host);
@@ -146,7 +146,7 @@ void __dump_page(struct page *page, const char *reason)
                }
 
                dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias);
-               if (probe_kernel_read(&dentry, dentry_ptr,
+               if (copy_from_kernel_nofault(&dentry, dentry_ptr,
                                                        sizeof(struct dentry))) {
                        pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n",
                                a_ops, dentry_ptr);
index 88845ed..f98ff91 100644 (file)
@@ -6,14 +6,15 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 
-bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
+bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
+               size_t size)
 {
        return true;
 }
 
 #ifdef HAVE_GET_KERNEL_NOFAULT
 
-#define probe_kernel_read_loop(dst, src, len, type, err_label)         \
+#define copy_from_kernel_nofault_loop(dst, src, len, type, err_label)  \
        while (len >= sizeof(type)) {                                   \
                __get_kernel_nofault(dst, src, type, err_label);                \
                dst += sizeof(type);                                    \
@@ -21,25 +22,25 @@ bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
                len -= sizeof(type);                                    \
        }
 
-long probe_kernel_read(void *dst, const void *src, size_t size)
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
 {
-       if (!probe_kernel_read_allowed(src, size))
+       if (!copy_from_kernel_nofault_allowed(src, size))
                return -ERANGE;
 
        pagefault_disable();
-       probe_kernel_read_loop(dst, src, size, u64, Efault);
-       probe_kernel_read_loop(dst, src, size, u32, Efault);
-       probe_kernel_read_loop(dst, src, size, u16, Efault);
-       probe_kernel_read_loop(dst, src, size, u8, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
+       copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
        pagefault_enable();
        return 0;
 Efault:
        pagefault_enable();
        return -EFAULT;
 }
-EXPORT_SYMBOL_GPL(probe_kernel_read);
+EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
 
-#define probe_kernel_write_loop(dst, src, len, type, err_label)                \
+#define copy_to_kernel_nofault_loop(dst, src, len, type, err_label)    \
        while (len >= sizeof(type)) {                                   \
                __put_kernel_nofault(dst, src, type, err_label);                \
                dst += sizeof(type);                                    \
@@ -47,13 +48,13 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
                len -= sizeof(type);                                    \
        }
 
-long probe_kernel_write(void *dst, const void *src, size_t size)
+long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
 {
        pagefault_disable();
-       probe_kernel_write_loop(dst, src, size, u64, Efault);
-       probe_kernel_write_loop(dst, src, size, u32, Efault);
-       probe_kernel_write_loop(dst, src, size, u16, Efault);
-       probe_kernel_write_loop(dst, src, size, u8, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
+       copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
        pagefault_enable();
        return 0;
 Efault:
@@ -67,7 +68,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 
        if (unlikely(count <= 0))
                return 0;
-       if (!probe_kernel_read_allowed(unsafe_addr, count))
+       if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
                return -ERANGE;
 
        pagefault_disable();
@@ -87,7 +88,7 @@ Efault:
 }
 #else /* HAVE_GET_KERNEL_NOFAULT */
 /**
- * probe_kernel_read(): safely attempt to read from kernel-space
+ * copy_from_kernel_nofault(): safely attempt to read from kernel-space
  * @dst: pointer to the buffer that shall take the data
  * @src: address to read from
  * @size: size of the data chunk
@@ -98,15 +99,15 @@ Efault:
  *
  * We ensure that the copy_from_user is executed in atomic context so that
  * do_page_fault() doesn't attempt to take mmap_lock.  This makes
- * probe_kernel_read() suitable for use within regions where the caller
+ * copy_from_kernel_nofault() suitable for use within regions where the caller
  * already holds mmap_lock, or other locks which nest inside mmap_lock.
  */
-long probe_kernel_read(void *dst, const void *src, size_t size)
+long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
 
-       if (!probe_kernel_read_allowed(src, size))
+       if (!copy_from_kernel_nofault_allowed(src, size))
                return -ERANGE;
 
        set_fs(KERNEL_DS);
@@ -120,10 +121,10 @@ long probe_kernel_read(void *dst, const void *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_kernel_read);
+EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
 
 /**
- * probe_kernel_write(): safely attempt to write to a location
+ * copy_to_kernel_nofault(): safely attempt to write to a location
  * @dst: address to write to
  * @src: pointer to the data that shall be written
  * @size: size of the data chunk
@@ -131,7 +132,7 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_kernel_write(void *dst, const void *src, size_t size)
+long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
@@ -174,7 +175,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 
        if (unlikely(count <= 0))
                return 0;
-       if (!probe_kernel_read_allowed(unsafe_addr, count))
+       if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
                return -ERANGE;
 
        set_fs(KERNEL_DS);
@@ -193,7 +194,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 #endif /* HAVE_GET_KERNEL_NOFAULT */
 
 /**
- * probe_user_read(): safely attempt to read from a user-space location
+ * copy_from_user_nofault(): safely attempt to read from a user-space location
  * @dst: pointer to the buffer that shall take the data
  * @src: address to read from. This must be a user address.
  * @size: size of the data chunk
@@ -201,7 +202,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
  * Safely read from user address @src to the buffer at @dst. If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_user_read(void *dst, const void __user *src, size_t size)
+long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
 {
        long ret = -EFAULT;
        mm_segment_t old_fs = get_fs();
@@ -218,10 +219,10 @@ long probe_user_read(void *dst, const void __user *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_user_read);
+EXPORT_SYMBOL_GPL(copy_from_user_nofault);
 
 /**
- * probe_user_write(): safely attempt to write to a user-space location
+ * copy_to_user_nofault(): safely attempt to write to a user-space location
  * @dst: address to write to
  * @src: pointer to the data that shall be written
  * @size: size of the data chunk
@@ -229,7 +230,7 @@ EXPORT_SYMBOL_GPL(probe_user_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_user_write(void __user *dst, const void *src, size_t size)
+long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
 {
        long ret = -EFAULT;
        mm_segment_t old_fs = get_fs();
@@ -246,7 +247,7 @@ long probe_user_write(void __user *dst, const void *src, size_t size)
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_GPL(probe_user_write);
+EXPORT_SYMBOL_GPL(copy_to_user_nofault);
 
 /**
  * strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user
index 5e313fa..2a99df7 100644 (file)
@@ -25,7 +25,7 @@ void rodata_test(void)
        }
 
        /* test 2: write to the variable; this should fault */
-       if (!probe_kernel_write((void *)&rodata_test_data,
+       if (!copy_to_kernel_nofault((void *)&rodata_test_data,
                                (void *)&zero, sizeof(zero))) {
                pr_err("test data was not read only\n");
                return;
index b8f798b..fe81773 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -292,7 +292,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
                return get_freepointer(s, object);
 
        freepointer_addr = (unsigned long)object + s->offset;
-       probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p));
+       copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
        return freelist_ptr(s, p, freepointer_addr);
 }
 
index afe0e81..4e7edd7 100644 (file)
@@ -332,6 +332,7 @@ struct ceph_options *ceph_alloc_options(void)
        opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
        opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
+       opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
        return opt;
 }
 EXPORT_SYMBOL(ceph_alloc_options);
@@ -490,16 +491,13 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
        case Opt_read_from_replica:
                switch (result.uint_32) {
                case Opt_read_from_replica_no:
-                       opt->osd_req_flags &= ~(CEPH_OSD_FLAG_BALANCE_READS |
-                                               CEPH_OSD_FLAG_LOCALIZE_READS);
+                       opt->read_from_replica = 0;
                        break;
                case Opt_read_from_replica_balance:
-                       opt->osd_req_flags |= CEPH_OSD_FLAG_BALANCE_READS;
-                       opt->osd_req_flags &= ~CEPH_OSD_FLAG_LOCALIZE_READS;
+                       opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS;
                        break;
                case Opt_read_from_replica_localize:
-                       opt->osd_req_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
-                       opt->osd_req_flags &= ~CEPH_OSD_FLAG_BALANCE_READS;
+                       opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS;
                        break;
                default:
                        BUG();
@@ -613,9 +611,9 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
                }
                seq_putc(m, ',');
        }
-       if (opt->osd_req_flags & CEPH_OSD_FLAG_BALANCE_READS) {
+       if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) {
                seq_puts(m, "read_from_replica=balance,");
-       } else if (opt->osd_req_flags & CEPH_OSD_FLAG_LOCALIZE_READS) {
+       } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
                seq_puts(m, "read_from_replica=localize,");
        }
 
index 4fea3c3..2db8b44 100644 (file)
@@ -445,8 +445,10 @@ static void target_copy(struct ceph_osd_request_target *dest,
        dest->size = src->size;
        dest->min_size = src->min_size;
        dest->sort_bitwise = src->sort_bitwise;
+       dest->recovery_deletes = src->recovery_deletes;
 
        dest->flags = src->flags;
+       dest->used_replica = src->used_replica;
        dest->paused = src->paused;
 
        dest->epoch = src->epoch;
@@ -1117,10 +1119,10 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                       truncate_size, truncate_seq);
        }
 
-       req->r_flags = flags;
        req->r_base_oloc.pool = layout->pool_id;
        req->r_base_oloc.pool_ns = ceph_try_get_string(layout->pool_ns);
        ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum);
+       req->r_flags = flags | osdc->client->options->read_from_replica;
 
        req->r_snapid = vino.snap;
        if (flags & CEPH_OSD_FLAG_WRITE)
@@ -2431,14 +2433,11 @@ promote:
 
 static void account_request(struct ceph_osd_request *req)
 {
-       struct ceph_osd_client *osdc = req->r_osdc;
-
        WARN_ON(req->r_flags & (CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK));
        WARN_ON(!(req->r_flags & (CEPH_OSD_FLAG_READ | CEPH_OSD_FLAG_WRITE)));
 
        req->r_flags |= CEPH_OSD_FLAG_ONDISK;
-       req->r_flags |= osdc->client->options->osd_req_flags;
-       atomic_inc(&osdc->num_requests);
+       atomic_inc(&req->r_osdc->num_requests);
 
        req->r_start_stamp = jiffies;
        req->r_start_latency = ktime_get();
index 83330a6..12fda8f 100644 (file)
@@ -4605,7 +4605,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
        if (tcp_ooo_try_coalesce(sk, tp->ooo_last_skb,
                                 skb, &fragstolen)) {
 coalesce_done:
-               tcp_grow_window(sk, skb);
+               /* For non sack flows, do not grow window to force DUPACK
+                * and trigger fast retransmit.
+                */
+               if (tcp_is_sack(tp))
+                       tcp_grow_window(sk, skb);
                kfree_skb_partial(skb, fragstolen);
                skb = NULL;
                goto add_sack;
@@ -4689,7 +4693,11 @@ add_sack:
                tcp_sack_new_ofo_skb(sk, seq, end_seq);
 end:
        if (skb) {
-               tcp_grow_window(sk, skb);
+               /* For non sack flows, do not grow window to force DUPACK
+                * and trigger fast retransmit.
+                */
+               if (tcp_is_sack(tp))
+                       tcp_grow_window(sk, skb);
                skb_condense(skb);
                skb_set_owner_r(skb, sk);
        }
index 7e12d21..8cd2782 100644 (file)
@@ -2615,6 +2615,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
                idev->mc_list = i->next;
 
                write_unlock_bh(&idev->lock);
+               ip6_mc_clear_src(i);
                ma_put(i);
                write_lock_bh(&idev->lock);
        }
index 809687d..db56535 100644 (file)
@@ -135,8 +135,6 @@ static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field)
                     ((nib & 0xF) << 8) | field);
 }
 
-#define MPTCP_PM_MAX_ADDR      4
-
 struct mptcp_addr_info {
        sa_family_t             family;
        __be16                  port;
@@ -234,10 +232,7 @@ static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
 
-       if (list_empty(&msk->rtx_queue))
-               return NULL;
-
-       return list_first_entry(&msk->rtx_queue, struct mptcp_data_frag, list);
+       return list_first_entry_or_null(&msk->rtx_queue, struct mptcp_data_frag, list);
 }
 
 struct mptcp_subflow_request_sock {
index bf13257..bbdb74b 100644 (file)
@@ -1053,8 +1053,10 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
        err = tcp_set_ulp(sf->sk, "mptcp");
        release_sock(sf->sk);
 
-       if (err)
+       if (err) {
+               sock_release(sf);
                return err;
+       }
 
        /* the newly created socket really belongs to the owning MPTCP master
         * socket, even if for additional subflows the allocation is performed
index d7bd8b1..832eabe 100644 (file)
@@ -939,7 +939,8 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
                        filter->mark.mask = 0xffffffff;
                }
        } else if (cda[CTA_MARK_MASK]) {
-               return ERR_PTR(-EINVAL);
+               err = -EINVAL;
+               goto err_filter;
        }
 #endif
        if (!cda[CTA_FILTER])
@@ -947,15 +948,17 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
 
        err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
        if (err < 0)
-               return ERR_PTR(err);
+               goto err_filter;
 
        err = ctnetlink_parse_filter(cda[CTA_FILTER], filter);
        if (err < 0)
-               return ERR_PTR(err);
+               goto err_filter;
 
        if (filter->orig_flags) {
-               if (!cda[CTA_TUPLE_ORIG])
-                       return ERR_PTR(-EINVAL);
+               if (!cda[CTA_TUPLE_ORIG]) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
 
                err = ctnetlink_parse_tuple_filter(cda, &filter->orig,
                                                   CTA_TUPLE_ORIG,
@@ -963,23 +966,32 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
                                                   &filter->zone,
                                                   filter->orig_flags);
                if (err < 0)
-                       return ERR_PTR(err);
+                       goto err_filter;
        }
 
        if (filter->reply_flags) {
-               if (!cda[CTA_TUPLE_REPLY])
-                       return ERR_PTR(-EINVAL);
+               if (!cda[CTA_TUPLE_REPLY]) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
 
                err = ctnetlink_parse_tuple_filter(cda, &filter->reply,
                                                   CTA_TUPLE_REPLY,
                                                   filter->family,
                                                   &filter->zone,
                                                   filter->orig_flags);
-               if (err < 0)
-                       return ERR_PTR(err);
+               if (err < 0) {
+                       err = -EINVAL;
+                       goto err_filter;
+               }
        }
 
        return filter;
+
+err_filter:
+       kfree(filter);
+
+       return ERR_PTR(err);
 }
 
 static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
index 6a3034f..afa8517 100644 (file)
@@ -387,51 +387,6 @@ static void nf_flow_offload_work_gc(struct work_struct *work)
        queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
 }
 
-int nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
-                                flow_setup_cb_t *cb, void *cb_priv)
-{
-       struct flow_block *block = &flow_table->flow_block;
-       struct flow_block_cb *block_cb;
-       int err = 0;
-
-       down_write(&flow_table->flow_block_lock);
-       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
-       if (block_cb) {
-               err = -EEXIST;
-               goto unlock;
-       }
-
-       block_cb = flow_block_cb_alloc(cb, cb_priv, cb_priv, NULL);
-       if (IS_ERR(block_cb)) {
-               err = PTR_ERR(block_cb);
-               goto unlock;
-       }
-
-       list_add_tail(&block_cb->list, &block->cb_list);
-
-unlock:
-       up_write(&flow_table->flow_block_lock);
-       return err;
-}
-EXPORT_SYMBOL_GPL(nf_flow_table_offload_add_cb);
-
-void nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
-                                 flow_setup_cb_t *cb, void *cb_priv)
-{
-       struct flow_block *block = &flow_table->flow_block;
-       struct flow_block_cb *block_cb;
-
-       down_write(&flow_table->flow_block_lock);
-       block_cb = flow_block_cb_lookup(block, cb, cb_priv);
-       if (block_cb) {
-               list_del(&block_cb->list);
-               flow_block_cb_free(block_cb);
-       } else {
-               WARN_ON(true);
-       }
-       up_write(&flow_table->flow_block_lock);
-}
-EXPORT_SYMBOL_GPL(nf_flow_table_offload_del_cb);
 
 static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
                                __be16 port, __be16 new_port)
index 073aa10..7647ecf 100644 (file)
@@ -6550,12 +6550,22 @@ err1:
        return err;
 }
 
+static void nft_flowtable_hook_release(struct nft_flowtable_hook *flowtable_hook)
+{
+       struct nft_hook *this, *next;
+
+       list_for_each_entry_safe(this, next, &flowtable_hook->list, list) {
+               list_del(&this->list);
+               kfree(this);
+       }
+}
+
 static int nft_delflowtable_hook(struct nft_ctx *ctx,
                                 struct nft_flowtable *flowtable)
 {
        const struct nlattr * const *nla = ctx->nla;
        struct nft_flowtable_hook flowtable_hook;
-       struct nft_hook *this, *next, *hook;
+       struct nft_hook *this, *hook;
        struct nft_trans *trans;
        int err;
 
@@ -6564,33 +6574,40 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
        if (err < 0)
                return err;
 
-       list_for_each_entry_safe(this, next, &flowtable_hook.list, list) {
+       list_for_each_entry(this, &flowtable_hook.list, list) {
                hook = nft_hook_list_find(&flowtable->hook_list, this);
                if (!hook) {
                        err = -ENOENT;
                        goto err_flowtable_del_hook;
                }
                hook->inactive = true;
-               list_del(&this->list);
-               kfree(this);
        }
 
        trans = nft_trans_alloc(ctx, NFT_MSG_DELFLOWTABLE,
                                sizeof(struct nft_trans_flowtable));
-       if (!trans)
-               return -ENOMEM;
+       if (!trans) {
+               err = -ENOMEM;
+               goto err_flowtable_del_hook;
+       }
 
        nft_trans_flowtable(trans) = flowtable;
        nft_trans_flowtable_update(trans) = true;
        INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
+       nft_flowtable_hook_release(&flowtable_hook);
 
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
 
        return 0;
 
 err_flowtable_del_hook:
-       list_for_each_entry(hook, &flowtable_hook.list, list)
+       list_for_each_entry(this, &flowtable_hook.list, list) {
+               hook = nft_hook_list_find(&flowtable->hook_list, this);
+               if (!hook)
+                       break;
+
                hook->inactive = false;
+       }
+       nft_flowtable_hook_release(&flowtable_hook);
 
        return err;
 }
index 8b5acc6..8c04388 100644 (file)
@@ -1242,7 +1242,9 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
                end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
        }
 
-       if (!*this_cpu_ptr(m->scratch) || bsize_max > m->bsize_max) {
+       if (!*get_cpu_ptr(m->scratch) || bsize_max > m->bsize_max) {
+               put_cpu_ptr(m->scratch);
+
                err = pipapo_realloc_scratch(m, bsize_max);
                if (err)
                        return err;
@@ -1250,6 +1252,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
                this_cpu_write(nft_pipapo_scratch_index, false);
 
                m->bsize_max = bsize_max;
+       } else {
+               put_cpu_ptr(m->scratch);
        }
 
        *ext2 = &e->ext;
index 62f416b..b6aad3f 100644 (file)
@@ -271,12 +271,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
 
                        if (nft_rbtree_interval_start(new)) {
                                if (nft_rbtree_interval_end(rbe) &&
-                                   nft_set_elem_active(&rbe->ext, genmask))
+                                   nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
                        } else {
                                overlap = nft_rbtree_interval_end(rbe) &&
                                          nft_set_elem_active(&rbe->ext,
-                                                             genmask);
+                                                             genmask) &&
+                                         !nft_set_elem_expired(&rbe->ext);
                        }
                } else if (d > 0) {
                        p = &parent->rb_right;
@@ -284,9 +286,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                        if (nft_rbtree_interval_end(new)) {
                                overlap = nft_rbtree_interval_end(rbe) &&
                                          nft_set_elem_active(&rbe->ext,
-                                                             genmask);
+                                                             genmask) &&
+                                         !nft_set_elem_expired(&rbe->ext);
                        } else if (nft_rbtree_interval_end(rbe) &&
-                                  nft_set_elem_active(&rbe->ext, genmask)) {
+                                  nft_set_elem_active(&rbe->ext, genmask) &&
+                                  !nft_set_elem_expired(&rbe->ext)) {
                                overlap = true;
                        }
                } else {
@@ -294,15 +298,18 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                            nft_rbtree_interval_start(new)) {
                                p = &parent->rb_left;
 
-                               if (nft_set_elem_active(&rbe->ext, genmask))
+                               if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
                        } else if (nft_rbtree_interval_start(rbe) &&
                                   nft_rbtree_interval_end(new)) {
                                p = &parent->rb_right;
 
-                               if (nft_set_elem_active(&rbe->ext, genmask))
+                               if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                   !nft_set_elem_expired(&rbe->ext))
                                        overlap = false;
-                       } else if (nft_set_elem_active(&rbe->ext, genmask)) {
+                       } else if (nft_set_elem_active(&rbe->ext, genmask) &&
+                                  !nft_set_elem_expired(&rbe->ext)) {
                                *ext = &rbe->ext;
                                return -EEXIST;
                        } else {
index 5ae069d..8dfff43 100644 (file)
@@ -264,7 +264,13 @@ struct rds_ib_device {
        int                     *vector_load;
 };
 
-#define ibdev_to_node(ibdev) dev_to_node((ibdev)->dev.parent)
+static inline int ibdev_to_node(struct ib_device *ibdev)
+{
+       struct device *parent;
+
+       parent = ibdev->dev.parent;
+       return parent ? dev_to_node(parent) : NUMA_NO_NODE;
+}
 #define rdsibdev_to_node(rdsibdev) ibdev_to_node(rdsibdev->dev)
 
 /* bits for i_ack_flags */
index e29f0f4..e9f3576 100644 (file)
@@ -1543,17 +1543,6 @@ static void __exit ct_cleanup_module(void)
        destroy_workqueue(act_ct_wq);
 }
 
-void tcf_ct_flow_table_restore_skb(struct sk_buff *skb, unsigned long cookie)
-{
-       enum ip_conntrack_info ctinfo = cookie & NFCT_INFOMASK;
-       struct nf_conn *ct;
-
-       ct = (struct nf_conn *)(cookie & NFCT_PTRMASK);
-       nf_conntrack_get(&ct->ct_general);
-       nf_ct_set(skb, ct, ctinfo);
-}
-EXPORT_SYMBOL_GPL(tcf_ct_flow_table_restore_skb);
-
 module_init(ct_init_module);
 module_exit(ct_cleanup_module);
 MODULE_AUTHOR("Paul Blakey <paulb@mellanox.com>");
index 3223448..ad3e560 100644 (file)
@@ -267,7 +267,7 @@ struct amt_host_if_msg_header {
 struct amt_host_if_resp_header {
        struct amt_host_if_msg_header header;
        uint32_t status;
-       unsigned char data[0];
+       unsigned char data[];
 } __attribute__((packed));
 
 const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,  \
index 13e5fba..66a6d51 100755 (executable)
@@ -27,7 +27,10 @@ parse_symbol() {
        elif [[ "${modcache[$module]+isset}" == "isset" ]]; then
                local objfile=${modcache[$module]}
        else
-               [[ $modpath == "" ]] && return
+               if [[ $modpath == "" ]]; then
+                       echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2
+                       return
+               fi
                local objfile=$(find "$modpath" -name "${module//_/[-_]}.ko*" -print -quit)
                [[ $objfile == "" ]] && return
                modcache[$module]=$objfile
index 298b737..16c1894 100644 (file)
@@ -107,7 +107,7 @@ struct ima_digest_data {
                } ng;
                u8 data[2];
        } xattr;
-       u8 digest[0];
+       u8 digest[];
 } __packed;
 
 /*
@@ -119,7 +119,7 @@ struct signature_v2_hdr {
        uint8_t hash_algo;      /* Digest algorithm [enum hash_algo] */
        __be32 keyid;           /* IMA key identifier - not X509/PGP specific */
        __be16 sig_size;        /* signature size */
-       uint8_t sig[0];         /* signature payload */
+       uint8_t sig[];          /* signature payload */
 } __packed;
 
 /* integrity data associated with an inode */
index b04b728..5e159ab 100644 (file)
@@ -36,7 +36,7 @@ struct sof_probe_point_desc {
 struct sof_ipc_probe_dma_add_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       struct sof_probe_dma dma[0];
+       struct sof_probe_dma dma[];
 } __packed;
 
 struct sof_ipc_probe_info_params {
@@ -51,19 +51,19 @@ struct sof_ipc_probe_info_params {
 struct sof_ipc_probe_dma_remove_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       unsigned int stream_tag[0];
+       unsigned int stream_tag[];
 } __packed;
 
 struct sof_ipc_probe_point_add_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       struct sof_probe_point_desc desc[0];
+       struct sof_probe_point_desc desc[];
 } __packed;
 
 struct sof_ipc_probe_point_remove_params {
        struct sof_ipc_cmd_hdr hdr;
        unsigned int num_elems;
-       unsigned int buffer_id[0];
+       unsigned int buffer_id[];
 } __packed;
 
 int sof_ipc_probe_init(struct snd_sof_dev *sdev,
index db18994..02dabc9 100644 (file)
 #define X86_FEATURE_AVX512_4FMAPS      (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
 #define X86_FEATURE_FSRM               (18*32+ 4) /* Fast Short Rep Mov */
 #define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
+#define X86_FEATURE_SRBDS_CTRL         (18*32+ 9) /* "" SRBDS mitigation MSR available */
 #define X86_FEATURE_MD_CLEAR           (18*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_TSX_FORCE_ABORT    (18*32+13) /* "" TSX_FORCE_ABORT */
 #define X86_FEATURE_PCONFIG            (18*32+18) /* Intel PCONFIG */
 #define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
 #define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
+#define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index ef452b8..e8370e6 100644 (file)
 #define TSX_CTRL_RTM_DISABLE           BIT(0)  /* Disable RTM feature */
 #define TSX_CTRL_CPUID_CLEAR           BIT(1)  /* Disable TSX enumeration */
 
+/* SRBDS support */
+#define MSR_IA32_MCU_OPT_CTRL          0x00000123
+#define RNGDS_MITG_DIS                 BIT(0)
+
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
 #define MSR_IA32_SYSENTER_EIP          0x00000176
index 43e2490..17c5a03 100644 (file)
@@ -385,33 +385,48 @@ struct kvm_sync_regs {
 #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
 
 #define KVM_STATE_NESTED_FORMAT_VMX    0
-#define KVM_STATE_NESTED_FORMAT_SVM    1       /* unused */
+#define KVM_STATE_NESTED_FORMAT_SVM    1
 
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
 #define KVM_STATE_NESTED_MTF_PENDING   0x00000008
+#define KVM_STATE_NESTED_GIF_SET       0x00000100
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
 
 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
 
+#define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000
+
+#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE        0x00000001
+
 struct kvm_vmx_nested_state_data {
        __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
        __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-       __u64 preemption_timer_deadline;
 };
 
 struct kvm_vmx_nested_state_hdr {
+       __u32 flags;
        __u64 vmxon_pa;
        __u64 vmcs12_pa;
+       __u64 preemption_timer_deadline;
 
        struct {
                __u16 flags;
        } smm;
 };
 
+struct kvm_svm_nested_state_data {
+       /* Save area only used if KVM_STATE_NESTED_RUN_PENDING.  */
+       __u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE];
+};
+
+struct kvm_svm_nested_state_hdr {
+       __u64 vmcb_pa;
+};
+
 /* for KVM_CAP_NESTED_STATE */
 struct kvm_nested_state {
        __u16 flags;
@@ -420,6 +435,7 @@ struct kvm_nested_state {
 
        union {
                struct kvm_vmx_nested_state_hdr vmx;
+               struct kvm_svm_nested_state_hdr svm;
 
                /* Pad the header to 128 bytes.  */
                __u8 pad[120];
@@ -432,6 +448,7 @@ struct kvm_nested_state {
         */
        union {
                struct kvm_vmx_nested_state_data vmx[0];
+               struct kvm_svm_nested_state_data svm[0];
        } data;
 };
 
index 30d7d04..be5e2e7 100644 (file)
@@ -2,7 +2,14 @@
 #ifndef _UAPI_ASM_X86_UNISTD_H
 #define _UAPI_ASM_X86_UNISTD_H
 
-/* x32 syscall flag bit */
+/*
+ * x32 syscall flag bit.  Some user programs expect syscall NR macros
+ * and __X32_SYSCALL_BIT to have type int, even though syscall numbers
+ * are, for practical purposes, unsigned long.
+ *
+ * Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right
+ * thing regardless.
+ */
 #define __X32_SYSCALL_BIT      0x40000000
 
 #ifndef __KERNEL__
index e95b72e..b8ff9e8 100644 (file)
        { EXIT_REASON_UMWAIT,                "UMWAIT" }, \
        { EXIT_REASON_TPAUSE,                "TPAUSE" }
 
+#define VMX_EXIT_REASON_FLAGS \
+       { VMX_EXIT_REASONS_FAILED_VMENTRY,      "FAILED_VMENTRY" }
+
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
 #define VMX_ABORT_LOAD_HOST_MSR_FAIL         4
index 3a3201e..f4a0130 100644 (file)
@@ -855,9 +855,11 @@ __SYSCALL(__NR_clone3, sys_clone3)
 __SYSCALL(__NR_openat2, sys_openat2)
 #define __NR_pidfd_getfd 438
 __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+#define __NR_faccessat2 439
+__SYSCALL(__NR_faccessat2, sys_faccessat2)
 
 #undef __NR_syscalls
-#define __NR_syscalls 439
+#define __NR_syscalls 440
 
 /*
  * 32 bit systems traditionally used different
index 2813e57..14b67cd 100644 (file)
@@ -1969,6 +1969,30 @@ enum drm_i915_perf_property_id {
         */
        DRM_I915_PERF_PROP_HOLD_PREEMPTION,
 
+       /**
+        * Specifying this pins all contexts to the specified SSEU power
+        * configuration for the duration of the recording.
+        *
+        * This parameter's value is a pointer to a struct
+        * drm_i915_gem_context_param_sseu.
+        *
+        * This property is available in perf revision 4.
+        */
+       DRM_I915_PERF_PROP_GLOBAL_SSEU,
+
+       /**
+        * This optional parameter specifies the timer interval in nanoseconds
+        * at which the i915 driver will check the OA buffer for available data.
+        * Minimum allowed value is 100 microseconds. A default value is used by
+        * the driver if this parameter is not specified. Note that larger timer
+        * values will reduce cpu consumption during OA perf captures. However,
+        * excessively large values would potentially result in OA buffer
+        * overwrites as captures reach end of the OA buffer.
+        *
+        * This property is available in perf revision 5.
+        */
+       DRM_I915_PERF_PROP_POLL_OA_PERIOD,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
index ca88b7b..2f86b2a 100644 (file)
 #define DN_ATTRIB      0x00000020      /* File changed attibutes */
 #define DN_MULTISHOT   0x80000000      /* Don't remove notifier */
 
+/*
+ * The constants AT_REMOVEDIR and AT_EACCESS have the same value.  AT_EACCESS is
+ * meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
+ * unlinkat.  The two functions do completely different things and therefore,
+ * the flags can be allowed to overlap.  For example, passing AT_REMOVEDIR to
+ * faccessat would be undefined behavior and thus treating it equivalent to
+ * AT_EACCESS is valid undefined behavior.
+ */
 #define AT_FDCWD               -100    /* Special value used to indicate
                                            openat should use the current
                                            working directory. */
 #define AT_SYMLINK_NOFOLLOW    0x100   /* Do not follow symbolic links.  */
+#define AT_EACCESS             0x200   /* Test access permitted for
+                                           effective IDs, not real IDs.  */
 #define AT_REMOVEDIR           0x200   /* Remove directory instead of
                                            unlinking file.  */
 #define AT_SYMLINK_FOLLOW      0x400   /* Follow symbolic links.  */
index 379a612..f44eb0a 100644 (file)
@@ -262,6 +262,7 @@ struct fsxattr {
 #define FS_EA_INODE_FL                 0x00200000 /* Inode used for large EA */
 #define FS_EOFBLOCKS_FL                        0x00400000 /* Reserved for ext4 */
 #define FS_NOCOW_FL                    0x00800000 /* Do not cow file */
+#define FS_DAX_FL                      0x02000000 /* Inode is DAX */
 #define FS_INLINE_DATA_FL              0x10000000 /* Reserved for ext4 */
 #define FS_PROJINHERIT_FL              0x20000000 /* Create with parents projid */
 #define FS_CASEFOLD_FL                 0x40000000 /* Folder is case insensitive */
index a10e3cd..7875709 100644 (file)
@@ -19,7 +19,8 @@
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
 #define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
-#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32     0x10
+#define FSCRYPT_POLICY_FLAGS_VALID             0x1F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1
index fdd632c..4fdf303 100644 (file)
@@ -188,10 +188,13 @@ struct kvm_s390_cmma_log {
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
 #define KVM_EXIT_HYPERV_HCALL          2
+#define KVM_EXIT_HYPERV_SYNDBG         3
        __u32 type;
+       __u32 pad1;
        union {
                struct {
                        __u32 msr;
+                       __u32 pad2;
                        __u64 control;
                        __u64 evt_page;
                        __u64 msg_page;
@@ -201,6 +204,15 @@ struct kvm_hyperv_exit {
                        __u64 result;
                        __u64 params[2];
                } hcall;
+               struct {
+                       __u32 msr;
+                       __u32 pad2;
+                       __u64 control;
+                       __u64 status;
+                       __u64 send_page;
+                       __u64 recv_page;
+                       __u64 pending_page;
+               } syndbg;
        } u;
 };
 
@@ -1017,6 +1029,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_VCPU_RESETS 179
 #define KVM_CAP_S390_PROTECTED 180
 #define KVM_CAP_PPC_SECURE_GUEST 181
+#define KVM_CAP_HALT_POLL 182
+#define KVM_CAP_ASYNC_PF_INT 183
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index d119278..82cc58f 100644 (file)
@@ -123,7 +123,10 @@ struct statx {
        __u32   stx_dev_major;  /* ID of device containing file [uncond] */
        __u32   stx_dev_minor;
        /* 0x90 */
-       __u64   __spare2[14];   /* Spare space for future expansion */
+       __u64   stx_mnt_id;
+       __u64   __spare2;
+       /* 0xa0 */
+       __u64   __spare3[12];   /* Spare space for future expansion */
        /* 0x100 */
 };
 
@@ -148,6 +151,7 @@ struct statx {
 #define STATX_BLOCKS           0x00000400U     /* Want/got stx_blocks */
 #define STATX_BASIC_STATS      0x000007ffU     /* The stuff in the normal stat struct */
 #define STATX_BTIME            0x00000800U     /* Want/got stx_btime */
+#define STATX_MNT_ID           0x00001000U     /* Got stx_mnt_id */
 
 #define STATX__RESERVED                0x80000000U     /* Reserved for future struct statx expansion */
 
@@ -177,7 +181,9 @@ struct statx {
 #define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
 #define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_MOUNT_ROOT          0x00002000 /* Root of a mount */
 #define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
+#define STATX_ATTR_DAX                 0x00002000 /* [I] File is DAX */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index 9fe72e4..0c23496 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+#define VHOST_FILE_UNBIND -1
+
 /* ioctls */
 
 #define VHOST_VIRTIO 0xAF
 /* Get the max ring size. */
 #define VHOST_VDPA_GET_VRING_NUM       _IOR(VHOST_VIRTIO, 0x76, __u16)
 
+/* Set event fd for config interrupt*/
+#define VHOST_VDPA_SET_CONFIG_CALL     _IOW(VHOST_VIRTIO, 0x77, int)
 #endif
index e1bd2a9..5b36c58 100644 (file)
@@ -1425,13 +1425,28 @@ static unsigned int type_size(const char *name)
        return 0;
 }
 
+static int append(char **buf, const char *delim, const char *str)
+{
+       char *new_buf;
+
+       new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
+       if (!new_buf)
+               return -1;
+       strcat(new_buf, delim);
+       strcat(new_buf, str);
+       *buf = new_buf;
+       return 0;
+}
+
 static int event_read_fields(struct tep_event *event, struct tep_format_field **fields)
 {
        struct tep_format_field *field = NULL;
        enum tep_event_type type;
        char *token;
        char *last_token;
+       char *delim = " ";
        int count = 0;
+       int ret;
 
        do {
                unsigned int size_dynamic = 0;
@@ -1490,24 +1505,51 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                                        field->flags |= TEP_FIELD_IS_POINTER;
 
                                if (field->type) {
-                                       char *new_type;
-                                       new_type = realloc(field->type,
-                                                          strlen(field->type) +
-                                                          strlen(last_token) + 2);
-                                       if (!new_type) {
-                                               free(last_token);
-                                               goto fail;
-                                       }
-                                       field->type = new_type;
-                                       strcat(field->type, " ");
-                                       strcat(field->type, last_token);
+                                       ret = append(&field->type, delim, last_token);
                                        free(last_token);
+                                       if (ret < 0)
+                                               goto fail;
                                } else
                                        field->type = last_token;
                                last_token = token;
+                               delim = " ";
                                continue;
                        }
 
+                       /* Handle __attribute__((user)) */
+                       if ((type == TEP_EVENT_DELIM) &&
+                           strcmp("__attribute__", last_token) == 0 &&
+                           token[0] == '(') {
+                               int depth = 1;
+                               int ret;
+
+                               ret = append(&field->type, " ", last_token);
+                               ret |= append(&field->type, "", "(");
+                               if (ret < 0)
+                                       goto fail;
+
+                               delim = " ";
+                               while ((type = read_token(&token)) != TEP_EVENT_NONE) {
+                                       if (type == TEP_EVENT_DELIM) {
+                                               if (token[0] == '(')
+                                                       depth++;
+                                               else if (token[0] == ')')
+                                                       depth--;
+                                               if (!depth)
+                                                       break;
+                                               ret = append(&field->type, "", token);
+                                               delim = "";
+                                       } else {
+                                               ret = append(&field->type, delim, token);
+                                               delim = " ";
+                                       }
+                                       if (ret < 0)
+                                               goto fail;
+                                       free(last_token);
+                                       last_token = token;
+                               }
+                               continue;
+                       }
                        break;
                }
 
@@ -1523,8 +1565,6 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                if (strcmp(token, "[") == 0) {
                        enum tep_event_type last_type = type;
                        char *brackets = token;
-                       char *new_brackets;
-                       int len;
 
                        field->flags |= TEP_FIELD_IS_ARRAY;
 
@@ -1536,29 +1576,27 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                                field->arraylen = 0;
 
                        while (strcmp(token, "]") != 0) {
+                               const char *delim;
+
                                if (last_type == TEP_EVENT_ITEM &&
                                    type == TEP_EVENT_ITEM)
-                                       len = 2;
+                                       delim = " ";
                                else
-                                       len = 1;
+                                       delim = "";
+
                                last_type = type;
 
-                               new_brackets = realloc(brackets,
-                                                      strlen(brackets) +
-                                                      strlen(token) + len);
-                               if (!new_brackets) {
+                               ret = append(&brackets, delim, token);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               brackets = new_brackets;
-                               if (len == 2)
-                                       strcat(brackets, " ");
-                               strcat(brackets, token);
                                /* We only care about the last token */
                                field->arraylen = strtoul(token, NULL, 0);
                                free_token(token);
                                type = read_token(&token);
                                if (type == TEP_EVENT_NONE) {
+                                       free(brackets);
                                        do_warning_event(event, "failed to find token");
                                        goto fail;
                                }
@@ -1566,13 +1604,11 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
 
                        free_token(token);
 
-                       new_brackets = realloc(brackets, strlen(brackets) + 2);
-                       if (!new_brackets) {
+                       ret = append(&brackets, "", "]");
+                       if (ret < 0) {
                                free(brackets);
                                goto fail;
                        }
-                       brackets = new_brackets;
-                       strcat(brackets, "]");
 
                        /* add brackets to type */
 
@@ -1582,34 +1618,23 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
                         * the format: type [] item;
                         */
                        if (type == TEP_EVENT_ITEM) {
-                               char *new_type;
-                               new_type = realloc(field->type,
-                                                  strlen(field->type) +
-                                                  strlen(field->name) +
-                                                  strlen(brackets) + 2);
-                               if (!new_type) {
+                               ret = append(&field->type, " ", field->name);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               field->type = new_type;
-                               strcat(field->type, " ");
-                               strcat(field->type, field->name);
+                               ret = append(&field->type, "", brackets);
+
                                size_dynamic = type_size(field->name);
                                free_token(field->name);
-                               strcat(field->type, brackets);
                                field->name = field->alias = token;
                                type = read_token(&token);
                        } else {
-                               char *new_type;
-                               new_type = realloc(field->type,
-                                                  strlen(field->type) +
-                                                  strlen(brackets) + 1);
-                               if (!new_type) {
+                               ret = append(&field->type, "", brackets);
+                               if (ret < 0) {
                                        free(brackets);
                                        goto fail;
                                }
-                               field->type = new_type;
-                               strcat(field->type, brackets);
                        }
                        free(brackets);
                }
@@ -2046,19 +2071,16 @@ process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
                /* could just be a type pointer */
                if ((strcmp(arg->op.op, "*") == 0) &&
                    type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
-                       char *new_atom;
+                       int ret;
 
                        if (left->type != TEP_PRINT_ATOM) {
                                do_warning_event(event, "bad pointer type");
                                goto out_free;
                        }
-                       new_atom = realloc(left->atom.atom,
-                                           strlen(left->atom.atom) + 3);
-                       if (!new_atom)
+                       ret = append(&left->atom.atom, " ", "*");
+                       if (ret < 0)
                                goto out_warn_free;
 
-                       left->atom.atom = new_atom;
-                       strcat(left->atom.atom, " *");
                        free(arg->op.op);
                        *arg = *left;
                        free(left);
@@ -3062,6 +3084,37 @@ err:
        return TEP_EVENT_ERROR;
 }
 
+static enum tep_event_type
+process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
+{
+       enum tep_event_type type;
+       char *token = NULL;
+
+       /* Handle __builtin_expect( cond, #) */
+       type = process_arg(event, arg, &token);
+
+       if (type != TEP_EVENT_DELIM || token[0] != ',')
+               goto out_free;
+
+       free_token(token);
+
+       /* We don't care what the second parameter is of the __builtin_expect() */
+       if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
+               goto out_free;
+
+       if (read_expected(TEP_EVENT_DELIM, ")") < 0)
+               goto out_free;
+
+       free_token(token);
+       type = read_token_item(tok);
+       return type;
+
+out_free:
+       free_token(token);
+       *tok = NULL;
+       return TEP_EVENT_ERROR;
+}
+
 static enum tep_event_type
 process_function(struct tep_event *event, struct tep_print_arg *arg,
                 char *token, char **tok)
@@ -3106,6 +3159,10 @@ process_function(struct tep_event *event, struct tep_print_arg *arg,
                free_token(token);
                return process_dynamic_array_len(event, arg, tok);
        }
+       if (strcmp(token, "__builtin_expect") == 0) {
+               free_token(token);
+               return process_builtin_expect(event, arg, tok);
+       }
 
        func = find_func_handler(event->tep, token);
        if (func) {
@@ -3151,18 +3208,15 @@ process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
                }
                /* atoms can be more than one token long */
                while (type == TEP_EVENT_ITEM) {
-                       char *new_atom;
-                       new_atom = realloc(atom,
-                                          strlen(atom) + strlen(token) + 2);
-                       if (!new_atom) {
+                       int ret;
+
+                       ret = append(&atom, " ", token);
+                       if (ret < 0) {
                                free(atom);
                                *tok = NULL;
                                free_token(token);
                                return TEP_EVENT_ERROR;
                        }
-                       atom = new_atom;
-                       strcat(atom, " ");
-                       strcat(atom, token);
                        free_token(token);
                        type = read_token_item(&token);
                }
index 877ca6b..5136338 100644 (file)
@@ -396,6 +396,18 @@ else
       NO_LIBBPF := 1
       NO_JVMTI := 1
     else
+      ifneq ($(filter s% -fsanitize=address%,$(EXTRA_CFLAGS),),)
+        ifneq ($(shell ldconfig -p | grep libasan >/dev/null 2>&1; echo $$?), 0)
+          msg := $(error No libasan found, please install libasan);
+        endif
+      endif
+
+      ifneq ($(filter s% -fsanitize=undefined%,$(EXTRA_CFLAGS),),)
+        ifneq ($(shell ldconfig -p | grep libubsan >/dev/null 2>&1; echo $$?), 0)
+          msg := $(error No libubsan found, please install libubsan);
+        endif
+      endif
+
       ifneq ($(filter s% -static%,$(LDFLAGS),),)
         msg := $(error No static glibc found, please install glibc-static);
       else
index 37b844f..78847b3 100644 (file)
 435    common  clone3                  sys_clone3
 437    common  openat2                 sys_openat2
 438    common  pidfd_getfd             sys_pidfd_getfd
+439    common  faccessat2              sys_faccessat2
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index b63b3fb..5f1d2a8 100644 (file)
@@ -478,8 +478,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
        if (rep->time_str)
                ret += fprintf(fp, " (time slices: %s)", rep->time_str);
 
-       if (symbol_conf.show_ref_callgraph &&
-           strstr(evname, "call-graph=no")) {
+       if (symbol_conf.show_ref_callgraph && evname && strstr(evname, "call-graph=no")) {
                ret += fprintf(fp, ", show reference callgraph");
        }
 
index 5da2436..181d65e 100644 (file)
@@ -3837,6 +3837,9 @@ int cmd_script(int argc, const char **argv)
        if (err)
                goto out_delete;
 
+       if (zstd_init(&(session->zstd_data), 0) < 0)
+               pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
+
        err = __cmd_script(&script);
 
        flush_scripting();
index 811cc0e..110f0c6 100644 (file)
@@ -65,6 +65,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a
        P_FLAG(SIZE);
        P_FLAG(BLOCKS);
        P_FLAG(BTIME);
+       P_FLAG(MNT_ID);
 
 #undef P_FLAG
 
index b020a86..9887ae0 100644 (file)
@@ -142,7 +142,8 @@ static int
 gen_read_mem(struct bpf_insn_pos *pos,
             int src_base_addr_reg,
             int dst_addr_reg,
-            long offset)
+            long offset,
+            int probeid)
 {
        /* mov arg3, src_base_addr_reg */
        if (src_base_addr_reg != BPF_REG_ARG3)
@@ -159,7 +160,7 @@ gen_read_mem(struct bpf_insn_pos *pos,
                ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos);
 
        /* Call probe_read  */
-       ins(BPF_EMIT_CALL(BPF_FUNC_probe_read), pos);
+       ins(BPF_EMIT_CALL(probeid), pos);
        /*
         * Error processing: if read fail, goto error code,
         * will be relocated. Target should be the start of
@@ -241,7 +242,7 @@ static int
 gen_prologue_slowpath(struct bpf_insn_pos *pos,
                      struct probe_trace_arg *args, int nargs)
 {
-       int err, i;
+       int err, i, probeid;
 
        for (i = 0; i < nargs; i++) {
                struct probe_trace_arg *arg = &args[i];
@@ -276,11 +277,16 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
                                stack_offset), pos);
 
                ref = arg->ref;
+               probeid = BPF_FUNC_probe_read_kernel;
                while (ref) {
                        pr_debug("prologue: arg %d: offset %ld\n",
                                 i, ref->offset);
+
+                       if (ref->user_access)
+                               probeid = BPF_FUNC_probe_read_user;
+
                        err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7,
-                                          ref->offset);
+                                          ref->offset, probeid);
                        if (err) {
                                pr_err("prologue: failed to generate probe_read function call\n");
                                goto errout;
index c4ca932..acef87d 100644 (file)
@@ -26,7 +26,7 @@ do { \
                YYABORT; \
 } while (0)
 
-static struct list_head* alloc_list()
+static struct list_head* alloc_list(void)
 {
        struct list_head *list;
 
@@ -349,7 +349,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
        struct list_head *list;
        char pmu_name[128];
 
-       snprintf(&pmu_name, 128, "%s-%s", $1, $3);
+       snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
        free($1);
        free($3);
        if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0)
index 85e0c7f..f971d9a 100644 (file)
@@ -86,7 +86,6 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
                          struct perf_pmu_info *info);
 struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
                                  struct list_head *head_terms);
-int perf_pmu_wrap(void);
 void perf_pmu_error(struct list_head *list, char *name, char const *msg);
 
 int perf_pmu__new_format(struct list_head *list, char *name,
index a08f373..df713a5 100644 (file)
@@ -1575,7 +1575,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
        }
 
        tmp = strchr(str, '@');
-       if (tmp && tmp != str && strcmp(tmp + 1, "user")) { /* user attr */
+       if (tmp && tmp != str && !strcmp(tmp + 1, "user")) { /* user attr */
                if (!user_access_is_supported()) {
                        semantic_error("ftrace does not support user access\n");
                        return -EINVAL;
@@ -1995,7 +1995,10 @@ static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
                if (depth < 0)
                        return depth;
        }
-       err = strbuf_addf(buf, "%+ld(", ref->offset);
+       if (ref->user_access)
+               err = strbuf_addf(buf, "%s%ld(", "+u", ref->offset);
+       else
+               err = strbuf_addf(buf, "%+ld(", ref->offset);
        return (err < 0) ? err : depth;
 }
 
index 8c85294..064b63a 100644 (file)
@@ -1044,7 +1044,7 @@ static struct {
        DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
        DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
        DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
-       DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*[u]<offset>*"),
+       DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*u]<offset>*"),
        DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"),
        DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"),
 };
index 3c6976f..57d0706 100644 (file)
@@ -668,7 +668,7 @@ static void print_aggr(struct perf_stat_config *config,
        int s;
        bool first;
 
-       if (!(config->aggr_map || config->aggr_get_id))
+       if (!config->aggr_map || !config->aggr_get_id)
                return;
 
        aggr_update_shadow(config, evlist);
@@ -1169,7 +1169,7 @@ static void print_percore(struct perf_stat_config *config,
        int s;
        bool first = true;
 
-       if (!(config->aggr_map || config->aggr_get_id))
+       if (!config->aggr_map || !config->aggr_get_id)
                return;
 
        if (config->percore_show_thread)
index db3c07b..b5f7a99 100644 (file)
@@ -51,7 +51,7 @@ struct nd_cmd_translate_spa {
                __u32 nfit_device_handle;
                __u32 _reserved;
                __u64 dpa;
-       } __packed devices[0];
+       } __packed devices[];
 
 } __packed;
 
@@ -74,7 +74,7 @@ struct nd_cmd_ars_err_inj_stat {
        struct nd_error_stat_query_record {
                __u64 err_inj_stat_spa_range_base;
                __u64 err_inj_stat_spa_range_length;
-       } __packed record[0];
+       } __packed record[];
 } __packed;
 
 #define ND_INTEL_SMART                  1
@@ -180,7 +180,7 @@ struct nd_intel_fw_send_data {
        __u32 context;
        __u32 offset;
        __u32 length;
-       __u8 data[0];
+       __u8 data[];
 /* this field is not declared due ot variable data from input */
 /*     __u32 status; */
 } __packed;