Merge branch 'for-4.21/block' into for-4.21/aio
authorJens Axboe <axboe@kernel.dk>
Tue, 18 Dec 2018 15:29:53 +0000 (08:29 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 18 Dec 2018 15:29:53 +0000 (08:29 -0700)
* for-4.21/block: (351 commits)
  blk-mq: enable IO poll if .nr_queues of type poll > 0
  blk-mq: change blk_mq_queue_busy() to blk_mq_queue_inflight()
  blk-mq: skip zero-queue maps in blk_mq_map_swqueue
  block: fix blk-iolatency accounting underflow
  blk-mq: fix dispatch from sw queue
  block: mq-deadline: Fix write completion handling
  nvme-pci: don't share queue maps
  blk-mq: only dispatch to non-defauly queue maps if they have queues
  blk-mq: export hctx->type in debugfs instead of sysfs
  blk-mq: fix allocation for queue mapping table
  blk-wbt: export internal state via debugfs
  blk-mq-debugfs: support rq_qos
  block: update sysfs documentation
  block: loop: check error using IS_ERR instead of IS_ERR_OR_NULL in loop_add()
  aoe: add __exit annotation
  block: clear REQ_HIPRI if polling is not supported
  blk-mq: replace and kill blk_mq_request_issue_directly
  blk-mq: issue directly with bypass 'false' in blk_mq_sched_insert_requests
  blk-mq: refactor the code of issue request directly
  block: remove the bio_integrity_advance export
  ...

153 files changed:
CREDITS
Documentation/core-api/xarray.rst
Documentation/media/uapi/v4l/extended-controls.rst
MAINTAINERS
Makefile
arch/alpha/kernel/setup.c
arch/alpha/mm/numa.c
arch/arm/boot/dts/arm-realview-pb1176.dts
arch/arm/boot/dts/arm-realview-pb11mp.dts
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
arch/arm/boot/dts/bcm2837-rpi-3-b.dts
arch/arm/boot/dts/imx7d-nitrogen7.dts
arch/arm/boot/dts/imx7d-pico.dtsi
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
arch/arm/mach-imx/cpuidle-imx6sx.c
arch/arm/mach-mmp/cputype.h
arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
arch/arm64/boot/dts/marvell/armada-ap806.dtsi
arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
arch/arm64/boot/dts/mediatek/mt7622.dtsi
arch/arm64/include/asm/memory.h
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/init.c
arch/powerpc/boot/Makefile
arch/powerpc/boot/crt0.S
arch/powerpc/include/asm/perf_event.h
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/bpf_perf_event.h [new file with mode: 0644]
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/msi.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/mm/dump_linuxpagetables.c
arch/powerpc/mm/init_64.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/papr_scm.c
arch/sh/include/asm/io.h
block/bio.c
block/blk-zoned.c
drivers/clk/qcom/gcc-qcs404.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
drivers/gpu/drm/i915/gvt/fb_decoder.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_workarounds.c
drivers/gpu/drm/i915/intel_workarounds.h
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
drivers/hid/hid-ids.h
drivers/hid/hid-ite.c
drivers/hid/hid-quirks.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/qp.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/odp.c
drivers/md/dm-cache-metadata.c
drivers/md/dm-thin.c
drivers/md/dm-zoned-target.c
drivers/md/dm.c
drivers/media/Kconfig
drivers/media/common/videobuf2/videobuf2-core.c
drivers/media/common/videobuf2/videobuf2-v4l2.c
drivers/media/media-device.c
drivers/media/platform/vicodec/vicodec-core.c
drivers/media/platform/vivid/vivid-sdr-cap.c
drivers/media/platform/vivid/vivid-vbi-cap.c
drivers/media/platform/vivid/vivid-vbi-out.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-out.c
drivers/media/platform/vsp1/vsp1_lif.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/mmc/core/block.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-omap.c
drivers/mmc/host/sdhci.c
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/qcom/pinctrl-sdm660.c
drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
drivers/staging/media/sunxi/cedrus/Kconfig
drivers/staging/media/sunxi/cedrus/cedrus_hw.c
drivers/thermal/hisi_thermal.c
drivers/thermal/st/stm_thermal.c
drivers/video/backlight/pwm_bl.c
fs/aio.c
fs/ceph/super.c
fs/ceph/super.h
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/iomap.c
fs/overlayfs/dir.c
fs/overlayfs/export.c
fs/overlayfs/inode.c
fs/userfaultfd.c
include/asm-generic/fixmap.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/xarray.h
include/media/mpeg2-ctrls.h [new file with mode: 0644]
include/media/v4l2-ctrls.h
include/media/videobuf2-core.h
include/uapi/linux/input-event-codes.h
include/uapi/linux/v4l2-controls.h
include/uapi/linux/videodev2.h
init/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_trigger.c
lib/radix-tree.c
lib/test_xarray.c
lib/xarray.c
mm/hugetlb.c
mm/memblock.c
mm/shmem.c
mm/sparse.c
scripts/checkstack.pl
scripts/spdxcheck.py
security/integrity/ima/ima_policy.c
security/keys/keyctl_pkey.c
security/keys/trusted.c
sound/firewire/fireface/ff-protocol-ff400.c
sound/pci/hda/patch_realtek.c
tools/testing/radix-tree/Makefile
tools/testing/radix-tree/main.c
tools/testing/radix-tree/regression.h
tools/testing/radix-tree/regression4.c [new file with mode: 0644]
tools/testing/selftests/seccomp/seccomp_bpf.c

diff --git a/CREDITS b/CREDITS
index c927339..7d397ee 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2541,6 +2541,10 @@ S: Ormond
 S: Victoria 3163
 S: Australia
 
+N: Eric Miao
+E: eric.y.miao@gmail.com
+D: MMP support
+
 N: Pauline Middelink
 E: middelin@polyware.nl
 D: General low-level bug fixes, /proc fixes, identd support
@@ -4115,6 +4119,10 @@ S: 1507 145th Place SE #B5
 S: Bellevue, Washington 98007
 S: USA
 
+N: Haojian Zhuang
+E: haojian.zhuang@gmail.com
+D: MMP support
+
 N: Richard Zidlicky
 E: rz@linux-m68k.org, rdzidlic@geocities.com
 W: http://www.geocities.com/rdzidlic
index dbe96cb..6a6d67a 100644 (file)
@@ -187,6 +187,8 @@ Takes xa_lock internally:
  * :c:func:`xa_erase_bh`
  * :c:func:`xa_erase_irq`
  * :c:func:`xa_cmpxchg`
+ * :c:func:`xa_cmpxchg_bh`
+ * :c:func:`xa_cmpxchg_irq`
  * :c:func:`xa_store_range`
  * :c:func:`xa_alloc`
  * :c:func:`xa_alloc_bh`
@@ -263,7 +265,8 @@ using :c:func:`xa_lock_irqsave` in both the interrupt handler and process
 context, or :c:func:`xa_lock_irq` in process context and :c:func:`xa_lock`
 in the interrupt handler.  Some of the more common patterns have helper
 functions such as :c:func:`xa_store_bh`, :c:func:`xa_store_irq`,
-:c:func:`xa_erase_bh` and :c:func:`xa_erase_irq`.
+:c:func:`xa_erase_bh`, :c:func:`xa_erase_irq`, :c:func:`xa_cmpxchg_bh`
+and :c:func:`xa_cmpxchg_irq`.
 
 Sometimes you need to protect access to the XArray with a mutex because
 that lock sits above another mutex in the locking hierarchy.  That does
index 65a1d87..027358b 100644 (file)
@@ -1505,6 +1505,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
     configuring a stateless hardware decoding pipeline for MPEG-2.
     The bitstream parameters are defined according to :ref:`mpeg2part2`.
 
+    .. note::
+
+       This compound control is not yet part of the public kernel API and
+       it is expected to change.
+
 .. c:type:: v4l2_ctrl_mpeg2_slice_params
 
 .. cssclass:: longtable
@@ -1625,6 +1630,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
     Specifies quantization matrices (as extracted from the bitstream) for the
     associated MPEG-2 slice data.
 
+    .. note::
+
+       This compound control is not yet part of the public kernel API and
+       it is expected to change.
+
 .. c:type:: v4l2_ctrl_mpeg2_quantization
 
 .. cssclass:: longtable
index 8119141..3318f30 100644 (file)
@@ -1739,13 +1739,17 @@ ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+W:     https://mtk.bcnfs.org/
+C:     irc://chat.freenode.net/linux-mediatek
 S:     Maintained
 F:     arch/arm/boot/dts/mt6*
 F:     arch/arm/boot/dts/mt7*
 F:     arch/arm/boot/dts/mt8*
 F:     arch/arm/mach-mediatek/
 F:     arch/arm64/boot/dts/mediatek/
+F:     drivers/soc/mediatek/
 N:     mtk
+N:     mt[678]
 K:     mediatek
 
 ARM/Mediatek USB3 PHY DRIVER
@@ -4843,6 +4847,7 @@ F:        include/uapi/drm/vmwgfx_drm.h
 
 DRM DRIVERS
 M:     David Airlie <airlied@linux.ie>
+M:     Daniel Vetter <daniel@ffwll.ch>
 L:     dri-devel@lists.freedesktop.org
 T:     git git://anongit.freedesktop.org/drm/drm
 B:     https://bugs.freedesktop.org/
@@ -10005,12 +10010,9 @@ S:     Odd Fixes
 F:     drivers/media/radio/radio-miropcm20*
 
 MMP SUPPORT
-M:     Eric Miao <eric.y.miao@gmail.com>
-M:     Haojian Zhuang <haojian.zhuang@gmail.com>
+R:     Lubomir Rintel <lkundrak@v3.sk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-T:     git git://github.com/hzhuang1/linux.git
-T:     git git://git.linaro.org/people/ycmiao/pxa-linux.git
-S:     Maintained
+S:     Odd Fixes
 F:     arch/arm/boot/dts/mmp*
 F:     arch/arm/mach-mmp/
 
index f2c3423..56d5270 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 4
 PATCHLEVEL = 20
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
index a37fd99..4b5b1b2 100644 (file)
@@ -634,6 +634,7 @@ setup_arch(char **cmdline_p)
 
        /* Find our memory.  */
        setup_memory(kernel_end);
+       memblock_set_bottom_up(true);
 
        /* First guess at cpu cache sizes.  Do this before init_arch.  */
        determine_cpu_caches(cpu->type);
index 7484655..d0b7337 100644 (file)
@@ -144,14 +144,14 @@ setup_memory_node(int nid, void *kernel_end)
        if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
                panic("kernel loaded out of ram");
 
+       memblock_add(PFN_PHYS(node_min_pfn),
+                    (node_max_pfn - node_min_pfn) << PAGE_SHIFT);
+
        /* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned.
           Note that we round this down, not up - node memory
           has much larger alignment than 8Mb, so it's safe. */
        node_min_pfn &= ~((1UL << (MAX_ORDER-1))-1);
 
-       memblock_add(PFN_PHYS(node_min_pfn),
-                    (node_max_pfn - node_min_pfn) << PAGE_SHIFT);
-
        NODE_DATA(nid)->node_start_pfn = node_min_pfn;
        NODE_DATA(nid)->node_present_pages = node_max_pfn - node_min_pfn;
 
index f2a1d25..83e0fbc 100644 (file)
@@ -45,7 +45,7 @@
        };
 
        /* The voltage to the MMC card is hardwired at 3.3V */
-       vmmc: fixedregulator@0 {
+       vmmc: regulator-vmmc {
                compatible = "regulator-fixed";
                regulator-name = "vmmc";
                regulator-min-microvolt = <3300000>;
@@ -53,7 +53,7 @@
                regulator-boot-on;
         };
 
-       veth: fixedregulator@0 {
+       veth: regulator-veth {
                compatible = "regulator-fixed";
                regulator-name = "veth";
                regulator-min-microvolt = <3300000>;
index 7f9cbdf..2f6aa24 100644 (file)
        };
 
        /* The voltage to the MMC card is hardwired at 3.3V */
-       vmmc: fixedregulator@0 {
+       vmmc: regulator-vmmc {
                compatible = "regulator-fixed";
                regulator-name = "vmmc";
                regulator-min-microvolt = <3300000>;
                regulator-boot-on;
         };
 
-       veth: fixedregulator@0 {
+       veth: regulator-veth {
                compatible = "regulator-fixed";
                regulator-name = "veth";
                regulator-min-microvolt = <3300000>;
index 4adb85e..9376224 100644 (file)
@@ -31,7 +31,7 @@
 
        wifi_pwrseq: wifi-pwrseq {
                compatible = "mmc-pwrseq-simple";
-               reset-gpios = <&expgpio 1 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
        };
 };
 
index c318bcb..89e6fd5 100644 (file)
@@ -26,7 +26,7 @@
 
        wifi_pwrseq: wifi-pwrseq {
                compatible = "mmc-pwrseq-simple";
-               reset-gpios = <&expgpio 1 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
        };
 };
 
index d8aac4a..177d21f 100644 (file)
                compatible = "regulator-fixed";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
-               clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
-               clock-names = "slow";
                regulator-name = "reg_wlan";
                startup-delay-us = <70000>;
                gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
                enable-active-high;
        };
+
+       usdhc2_pwrseq: usdhc2_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
+               clock-names = "ext_clock";
+       };
 };
 
 &adc1 {
        bus-width = <4>;
        non-removable;
        vmmc-supply = <&reg_wlan>;
+       mmc-pwrseq = <&usdhc2_pwrseq>;
        cap-power-off-card;
        keep-power-in-suspend;
        status = "okay";
index 21973eb..f27b384 100644 (file)
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
        };
+
+       usdhc2_pwrseq: usdhc2_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
+               clock-names = "ext_clock";
+       };
+};
+
+&clks {
+       assigned-clocks = <&clks IMX7D_CLKO2_ROOT_SRC>,
+                         <&clks IMX7D_CLKO2_ROOT_DIV>;
+       assigned-clock-parents = <&clks IMX7D_CKIL>;
+       assigned-clock-rates = <0>, <32768>;
 };
 
 &i2c4 {
 
 &usdhc2 { /* Wifi SDIO */
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc2>;
+       pinctrl-0 = <&pinctrl_usdhc2 &pinctrl_wifi_clk>;
        no-1-8-v;
        non-removable;
        keep-power-in-suspend;
        wakeup-source;
        vmmc-supply = <&reg_ap6212>;
+       mmc-pwrseq = <&usdhc2_pwrseq>;
        status = "okay";
 };
 
 };
 
 &iomuxc_lpsr {
+       pinctrl_wifi_clk: wificlkgrp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO03__CCM_CLKO2     0x7d
+               >;
+       };
+
        pinctrl_wdog: wdoggrp {
                fsl,pins = <
                        MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B  0x74
index 742d294..583a5a0 100644 (file)
 
 &reg_dldo3 {
        regulator-always-on;
-       regulator-min-microvolt = <2500000>;
-       regulator-max-microvolt = <2500000>;
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
        regulator-name = "vcc-pd";
 };
 
index 243a108..fd0053e 100644 (file)
@@ -110,7 +110,7 @@ int __init imx6sx_cpuidle_init(void)
         * except for power up sw2iso which need to be
         * larger than LDO ramp up time.
         */
-       imx_gpc_set_arm_power_up_timing(2, 1);
+       imx_gpc_set_arm_power_up_timing(0xf, 1);
        imx_gpc_set_arm_power_down_timing(1, 1);
 
        return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
index 446edae..a96abcf 100644 (file)
@@ -44,10 +44,12 @@ static inline int cpu_is_pxa910(void)
 #define cpu_is_pxa910()        (0)
 #endif
 
-#ifdef CONFIG_CPU_MMP2
+#if defined(CONFIG_CPU_MMP2) || defined(CONFIG_MACH_MMP2_DT)
 static inline int cpu_is_mmp2(void)
 {
-       return (((read_cpuid_id() >> 8) & 0xff) == 0x58);
+       return (((read_cpuid_id() >> 8) & 0xff) == 0x58) &&
+               (((mmp_chip_id & 0xfff) == 0x410) ||
+                ((mmp_chip_id & 0xfff) == 0x610));
 }
 #else
 #define cpu_is_mmp2()  (0)
index 64632c8..01ea662 100644 (file)
                        compatible = "arm,cortex-a72", "arm,armv8";
                        reg = <0x000>;
                        enable-method = "psci";
-                       cpu-idle-states = <&CPU_SLEEP_0>;
                };
                cpu1: cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a72", "arm,armv8";
                        reg = <0x001>;
                        enable-method = "psci";
-                       cpu-idle-states = <&CPU_SLEEP_0>;
                };
                cpu2: cpu@100 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a72", "arm,armv8";
                        reg = <0x100>;
                        enable-method = "psci";
-                       cpu-idle-states = <&CPU_SLEEP_0>;
                };
                cpu3: cpu@101 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a72", "arm,armv8";
                        reg = <0x101>;
                        enable-method = "psci";
-                       cpu-idle-states = <&CPU_SLEEP_0>;
                };
        };
 };
index 073610a..7d94c1f 100644 (file)
                method = "smc";
        };
 
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               idle_states {
-                       entry_method = "arm,pcsi";
-
-                       CPU_SLEEP_0: cpu-sleep-0 {
-                               compatible = "arm,idle-state";
-                               local-timer-stop;
-                               arm,psci-suspend-param = <0x0010000>;
-                               entry-latency-us = <80>;
-                               exit-latency-us  = <160>;
-                               min-residency-us = <320>;
-                       };
-
-                       CLUSTER_SLEEP_0: cluster-sleep-0 {
-                               compatible = "arm,idle-state";
-                               local-timer-stop;
-                               arm,psci-suspend-param = <0x1010000>;
-                               entry-latency-us = <500>;
-                               exit-latency-us = <1000>;
-                               min-residency-us = <2500>;
-                       };
-               };
-       };
-
        ap806 {
                #address-cells = <2>;
                #size-cells = <2>;
index 5d6005c..710c5c3 100644 (file)
        model = "Bananapi BPI-R64";
        compatible = "bananapi,bpi-r64", "mediatek,mt7622";
 
+       aliases {
+               serial0 = &uart0;
+       };
+
        chosen {
-               bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
+               stdout-path = "serial0:115200n8";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
        };
 
        cpus {
index dcad086..3f78334 100644 (file)
        model = "MediaTek MT7622 RFB1 board";
        compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
 
+       aliases {
+               serial0 = &uart0;
+       };
+
        chosen {
-               bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
+               stdout-path = "serial0:115200n8";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
        };
 
        cpus {
index fe0c875..14a1028 100644 (file)
                #reset-cells = <1>;
        };
 
-       timer: timer@10004000 {
-               compatible = "mediatek,mt7622-timer",
-                            "mediatek,mt6577-timer";
-               reg = <0 0x10004000 0 0x80>;
-               interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
-               clocks = <&infracfg CLK_INFRA_APXGPT_PD>,
-                        <&topckgen CLK_TOP_RTC>;
-               clock-names = "system-clk", "rtc-clk";
-       };
-
        scpsys: scpsys@10006000 {
                compatible = "mediatek,mt7622-scpsys",
                             "syscon";
index b964429..f0a5c95 100644 (file)
 #define PCI_IO_SIZE            SZ_16M
 
 /*
- * Log2 of the upper bound of the size of a struct page. Used for sizing
- * the vmemmap region only, does not affect actual memory footprint.
- * We don't use sizeof(struct page) directly since taking its size here
- * requires its definition to be available at this point in the inclusion
- * chain, and it may not be a power of 2 in the first place.
- */
-#define STRUCT_PAGE_MAX_SHIFT  6
-
-/*
  * VMEMMAP_SIZE - allows the whole linear region to be covered by
  *                a struct page array
  */
index a3ac262..a537044 100644 (file)
@@ -429,9 +429,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
                                                   prot,
                                                   __builtin_return_address(0));
                if (addr) {
-                       memset(addr, 0, size);
                        if (!coherent)
                                __dma_flush_area(page_to_virt(page), iosize);
+                       memset(addr, 0, size);
                } else {
                        iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
                        dma_release_from_contiguous(dev, page,
index 9b432d9..0340e45 100644 (file)
@@ -610,14 +610,6 @@ void __init mem_init(void)
        BUILD_BUG_ON(TASK_SIZE_32                       > TASK_SIZE_64);
 #endif
 
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-       /*
-        * Make sure we chose the upper bound of sizeof(struct page)
-        * correctly when sizing the VMEMMAP array.
-        */
-       BUILD_BUG_ON(sizeof(struct page) > (1 << STRUCT_PAGE_MAX_SHIFT));
-#endif
-
        if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
                extern int sysctl_overcommit_memory;
                /*
index 3935436..ed98831 100644 (file)
@@ -197,7 +197,7 @@ $(obj)/empty.c:
 $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S
        $(Q)cp $< $@
 
-$(obj)/serial.c: $(obj)/autoconf.h
+$(srctree)/$(src)/serial.c: $(obj)/autoconf.h
 
 $(obj)/autoconf.h: $(obj)/%: $(objtree)/include/generated/%
        $(Q)cp $< $@
index 32dfe6d..9b9d174 100644 (file)
@@ -15,7 +15,7 @@
 RELA = 7
 RELACOUNT = 0x6ffffff9
 
-       .text
+       .data
        /* A procedure descriptor used when booting this as a COFF file.
         * When making COFF, this comes first in the link and we're
         * linked at 0x500000.
@@ -23,6 +23,8 @@ RELACOUNT = 0x6ffffff9
        .globl  _zimage_start_opd
 _zimage_start_opd:
        .long   0x500000, 0, 0, 0
+       .text
+       b       _zimage_start
 
 #ifdef __powerpc64__
 .balign 8
index 8bf1b63..16a4981 100644 (file)
@@ -26,6 +26,8 @@
 #include <asm/ptrace.h>
 #include <asm/reg.h>
 
+#define perf_arch_bpf_user_pt_regs(regs) &regs->user_regs
+
 /*
  * Overload regs->result to specify whether we should use the MSR (result
  * is zero) or the SIAR (result is non zero).
index a658091..3712152 100644 (file)
@@ -1,7 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += bpf_perf_event.h
 generic-y += param.h
 generic-y += poll.h
 generic-y += resource.h
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
new file mode 100644 (file)
index 0000000..b551b74
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
+#define _UAPI__ASM_BPF_PERF_EVENT_H__
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
index 33b34a5..5b9dce1 100644 (file)
@@ -372,6 +372,8 @@ void __init find_legacy_serial_ports(void)
 
        /* Now find out if one of these is out firmware console */
        path = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (path == NULL)
+               path = of_get_property(of_chosen, "stdout-path", NULL);
        if (path != NULL) {
                stdout = of_find_node_by_path(path);
                if (stdout)
@@ -595,8 +597,10 @@ static int __init check_legacy_serial_console(void)
        /* We are getting a weird phandle from OF ... */
        /* ... So use the full path instead */
        name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name == NULL)
+               name = of_get_property(of_chosen, "stdout-path", NULL);
        if (name == NULL) {
-               DBG(" no linux,stdout-path !\n");
+               DBG(" no stdout-path !\n");
                return -ENODEV;
        }
        prom_stdout = of_find_node_by_path(name);
index dab616a..f219765 100644 (file)
@@ -34,5 +34,10 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct pci_controller *phb = pci_bus_to_host(dev->bus);
 
-       phb->controller_ops.teardown_msi_irqs(dev);
+       /*
+        * We can be called even when arch_setup_msi_irqs() returns -ENOSYS,
+        * so check the pointer again.
+        */
+       if (phb->controller_ops.teardown_msi_irqs)
+               phb->controller_ops.teardown_msi_irqs(dev);
 }
index afb819f..714c348 100644 (file)
@@ -3266,12 +3266,17 @@ long do_syscall_trace_enter(struct pt_regs *regs)
        user_exit();
 
        if (test_thread_flag(TIF_SYSCALL_EMU)) {
-               ptrace_report_syscall(regs);
                /*
+                * A nonzero return code from tracehook_report_syscall_entry()
+                * tells us to prevent the syscall execution, but we are not
+                * going to execute it anyway.
+                *
                 * Returning -1 will skip the syscall execution. We want to
                 * avoid clobbering any register also, thus, not 'gotoing'
                 * skip label.
                 */
+               if (tracehook_report_syscall_entry(regs))
+                       ;
                return -1;
        }
 
index 2b74f8a..6aa4166 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/hugetlb.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <asm/fixmap.h>
index 7a9886f..a5091c0 100644 (file)
@@ -188,15 +188,20 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
        pr_debug("vmemmap_populate %lx..%lx, node %d\n", start, end, node);
 
        for (; start < end; start += page_size) {
-               void *p;
+               void *p = NULL;
                int rc;
 
                if (vmemmap_populated(start, page_size))
                        continue;
 
+               /*
+                * Allocate from the altmap first if we have one. This may
+                * fail due to alignment issues when using 16MB hugepages, so
+                * fall back to system memory if the altmap allocation fail.
+                */
                if (altmap)
                        p = altmap_alloc_block_buf(page_size, altmap);
-               else
+               if (!p)
                        p = vmemmap_alloc_block_buf(page_size, node);
                if (!p)
                        return -ENOMEM;
@@ -255,8 +260,15 @@ void __ref vmemmap_free(unsigned long start, unsigned long end,
 {
        unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
        unsigned long page_order = get_order(page_size);
+       unsigned long alt_start = ~0, alt_end = ~0;
+       unsigned long base_pfn;
 
        start = _ALIGN_DOWN(start, page_size);
+       if (altmap) {
+               alt_start = altmap->base_pfn;
+               alt_end = altmap->base_pfn + altmap->reserve +
+                         altmap->free + altmap->alloc + altmap->align;
+       }
 
        pr_debug("vmemmap_free %lx...%lx\n", start, end);
 
@@ -280,8 +292,9 @@ void __ref vmemmap_free(unsigned long start, unsigned long end,
                page = pfn_to_page(addr >> PAGE_SHIFT);
                section_base = pfn_to_page(vmemmap_section_start(start));
                nr_pages = 1 << page_order;
+               base_pfn = PHYS_PFN(addr);
 
-               if (altmap) {
+               if (base_pfn >= alt_start && base_pfn < alt_end) {
                        vmem_altmap_free(altmap, nr_pages);
                } else if (PageReserved(page)) {
                        /* allocated from bootmem */
index 2e4bd32..472b784 100644 (file)
@@ -140,8 +140,7 @@ config IBMEBUS
          Bus device driver for GX bus based adapters.
 
 config PAPR_SCM
-       depends on PPC_PSERIES && MEMORY_HOTPLUG
-       select LIBNVDIMM
+       depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
        tristate "Support for the PAPR Storage Class Memory interface"
        help
          Enable access to hypervisor provided storage class memory.
index ee9372b..7d6457a 100644 (file)
@@ -55,7 +55,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
        do {
                rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
                                p->blocks, BIND_ANY_ADDR, token);
-               token = be64_to_cpu(ret[0]);
+               token = ret[0];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -64,7 +64,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                return -ENXIO;
        }
 
-       p->bound_addr = be64_to_cpu(ret[1]);
+       p->bound_addr = ret[1];
 
        dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res);
 
@@ -82,7 +82,7 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)
        do {
                rc = plpar_hcall(H_SCM_UNBIND_MEM, ret, p->drc_index,
                                p->bound_addr, p->blocks, token);
-               token = be64_to_cpu(ret);
+               token = ret[0];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -223,6 +223,9 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
                goto err;
        }
 
+       if (nvdimm_bus_check_dimm_count(p->bus, 1))
+               goto err;
+
        /* now add the region */
 
        memset(&mapping, 0, sizeof(mapping));
@@ -257,9 +260,12 @@ err:       nvdimm_bus_unregister(p->bus);
 
 static int papr_scm_probe(struct platform_device *pdev)
 {
-       uint32_t drc_index, metadata_size, unit_cap[2];
        struct device_node *dn = pdev->dev.of_node;
+       u32 drc_index, metadata_size;
+       u64 blocks, block_size;
        struct papr_scm_priv *p;
+       const char *uuid_str;
+       u64 uuid[2];
        int rc;
 
        /* check we have all the required DT properties */
@@ -268,8 +274,18 @@ static int papr_scm_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (of_property_read_u32_array(dn, "ibm,unit-capacity", unit_cap, 2)) {
-               dev_err(&pdev->dev, "%pOF: missing unit-capacity!\n", dn);
+       if (of_property_read_u64(dn, "ibm,block-size", &block_size)) {
+               dev_err(&pdev->dev, "%pOF: missing block-size!\n", dn);
+               return -ENODEV;
+       }
+
+       if (of_property_read_u64(dn, "ibm,number-of-blocks", &blocks)) {
+               dev_err(&pdev->dev, "%pOF: missing number-of-blocks!\n", dn);
+               return -ENODEV;
+       }
+
+       if (of_property_read_string(dn, "ibm,unit-guid", &uuid_str)) {
+               dev_err(&pdev->dev, "%pOF: missing unit-guid!\n", dn);
                return -ENODEV;
        }
 
@@ -282,8 +298,13 @@ static int papr_scm_probe(struct platform_device *pdev)
 
        p->dn = dn;
        p->drc_index = drc_index;
-       p->block_size = unit_cap[0];
-       p->blocks     = unit_cap[1];
+       p->block_size = block_size;
+       p->blocks = blocks;
+
+       /* We just need to ensure that set cookies are unique across */
+       uuid_parse(uuid_str, (uuid_t *) uuid);
+       p->nd_set.cookie1 = uuid[0];
+       p->nd_set.cookie2 = uuid[1];
 
        /* might be zero */
        p->metadata_size = metadata_size;
@@ -296,7 +317,7 @@ static int papr_scm_probe(struct platform_device *pdev)
 
        /* setup the resource for the newly bound range */
        p->res.start = p->bound_addr;
-       p->res.end   = p->bound_addr + p->blocks * p->block_size;
+       p->res.end   = p->bound_addr + p->blocks * p->block_size - 1;
        p->res.name  = pdev->name;
        p->res.flags = IORESOURCE_MEM;
 
index 98cb8c8..4f7f235 100644 (file)
@@ -24,6 +24,7 @@
 #define __IO_PREFIX     generic
 #include <asm/io_generic.h>
 #include <asm/io_trapped.h>
+#include <asm-generic/pci_iomap.h>
 #include <mach/mangle-port.h>
 
 #define __raw_writeb(v,a)      (__chk_io_ptr(a), *(volatile u8  __force *)(a) = (v))
index c288b90..8281bfc 100644 (file)
@@ -1260,7 +1260,8 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
                if (ret)
                        goto cleanup;
        } else {
-               zero_fill_bio(bio);
+               if (bmd->is_our_pages)
+                       zero_fill_bio(bio);
                iov_iter_advance(iter, bio->bi_iter.bi_size);
        }
 
index e9c332b..2d98803 100644 (file)
@@ -378,7 +378,7 @@ static struct blk_zone *blk_alloc_zones(int node, unsigned int *nr_zones)
        struct page *page;
        int order;
 
-       for (order = get_order(size); order > 0; order--) {
+       for (order = get_order(size); order >= 0; order--) {
                page = alloc_pages_node(node, GFP_NOIO | __GFP_ZERO, order);
                if (page) {
                        *nr_zones = min_t(unsigned int, *nr_zones,
index ef1b267..64da032 100644 (file)
@@ -297,7 +297,7 @@ static struct clk_alpha_pll gpll0_out_main = {
                .hw.init = &(struct clk_init_data){
                        .name = "gpll0_out_main",
                        .parent_names = (const char *[])
-                                       { "gpll0_sleep_clk_src" },
+                                       { "cxo" },
                        .num_parents = 1,
                        .ops = &clk_alpha_pll_ops,
                },
index 8816c69..387f1cf 100644 (file)
@@ -330,7 +330,9 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                        case CHIP_TOPAZ:
                                if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
                                    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
-                                   ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87))) {
+                                   ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
+                                   ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
+                                   ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
                                        info->is_kicker = true;
                                        strcpy(fw_name, "amdgpu/topaz_k_smc.bin");
                                } else
@@ -351,7 +353,6 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                if (type == CGS_UCODE_ID_SMU) {
                                        if (((adev->pdev->device == 0x67ef) &&
                                             ((adev->pdev->revision == 0xe0) ||
-                                             (adev->pdev->revision == 0xe2) ||
                                              (adev->pdev->revision == 0xe5))) ||
                                            ((adev->pdev->device == 0x67ff) &&
                                             ((adev->pdev->revision == 0xcf) ||
@@ -359,8 +360,13 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                              (adev->pdev->revision == 0xff)))) {
                                                info->is_kicker = true;
                                                strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
-                                       } else
+                                       } else if ((adev->pdev->device == 0x67ef) &&
+                                                  (adev->pdev->revision == 0xe2)) {
+                                               info->is_kicker = true;
+                                               strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
+                                       } else {
                                                strcpy(fw_name, "amdgpu/polaris11_smc.bin");
+                                       }
                                } else if (type == CGS_UCODE_ID_SMU_SK) {
                                        strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
                                }
@@ -375,17 +381,35 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                              (adev->pdev->revision == 0xe7) ||
                                              (adev->pdev->revision == 0xef))) ||
                                            ((adev->pdev->device == 0x6fdf) &&
-                                            (adev->pdev->revision == 0xef))) {
+                                            ((adev->pdev->revision == 0xef) ||
+                                             (adev->pdev->revision == 0xff)))) {
                                                info->is_kicker = true;
                                                strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
-                                       } else
+                                       } else if ((adev->pdev->device == 0x67df) &&
+                                                  ((adev->pdev->revision == 0xe1) ||
+                                                   (adev->pdev->revision == 0xf7))) {
+                                               info->is_kicker = true;
+                                               strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
+                                       } else {
                                                strcpy(fw_name, "amdgpu/polaris10_smc.bin");
+                                       }
                                } else if (type == CGS_UCODE_ID_SMU_SK) {
                                        strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
                                }
                                break;
                        case CHIP_POLARIS12:
-                               strcpy(fw_name, "amdgpu/polaris12_smc.bin");
+                               if (((adev->pdev->device == 0x6987) &&
+                                    ((adev->pdev->revision == 0xc0) ||
+                                     (adev->pdev->revision == 0xc3))) ||
+                                   ((adev->pdev->device == 0x6981) &&
+                                    ((adev->pdev->revision == 0x00) ||
+                                     (adev->pdev->revision == 0x01) ||
+                                     (adev->pdev->revision == 0x10)))) {
+                                       info->is_kicker = true;
+                                       strcpy(fw_name, "amdgpu/polaris12_k_smc.bin");
+                               } else {
+                                       strcpy(fw_name, "amdgpu/polaris12_smc.bin");
+                               }
                                break;
                        case CHIP_VEGAM:
                                strcpy(fw_name, "amdgpu/vegam_smc.bin");
index 663043c..0acc8de 100644 (file)
@@ -124,14 +124,14 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs
                goto free_chunk;
        }
 
+       mutex_lock(&p->ctx->lock);
+
        /* skip guilty context job */
        if (atomic_read(&p->ctx->guilty) == 1) {
                ret = -ECANCELED;
                goto free_chunk;
        }
 
-       mutex_lock(&p->ctx->lock);
-
        /* get chunks */
        chunk_array_user = u64_to_user_ptr(cs->in.chunks);
        if (copy_from_user(chunk_array, chunk_array_user,
index 8de55f7..74b611e 100644 (file)
@@ -872,7 +872,13 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
        {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
        {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x6869, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x686a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x686b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
        {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x686d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x686e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
+       {0x1002, 0x686f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
        {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
        /* Vega 12 */
        {0x1002, 0x69A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
@@ -885,6 +891,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x66A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
        {0x1002, 0x66A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
        {0x1002, 0x66A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
+       {0x1002, 0x66A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
        {0x1002, 0x66A7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
        {0x1002, 0x66AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
        /* Raven */
index a9f18ea..e4ded89 100644 (file)
@@ -337,12 +337,19 @@ static const struct kfd_deviceid supported_devices[] = {
        { 0x6864, &vega10_device_info },        /* Vega10 */
        { 0x6867, &vega10_device_info },        /* Vega10 */
        { 0x6868, &vega10_device_info },        /* Vega10 */
+       { 0x6869, &vega10_device_info },        /* Vega10 */
+       { 0x686A, &vega10_device_info },        /* Vega10 */
+       { 0x686B, &vega10_device_info },        /* Vega10 */
        { 0x686C, &vega10_vf_device_info },     /* Vega10  vf*/
+       { 0x686D, &vega10_device_info },        /* Vega10 */
+       { 0x686E, &vega10_device_info },        /* Vega10 */
+       { 0x686F, &vega10_device_info },        /* Vega10 */
        { 0x687F, &vega10_device_info },        /* Vega10 */
        { 0x66a0, &vega20_device_info },        /* Vega20 */
        { 0x66a1, &vega20_device_info },        /* Vega20 */
        { 0x66a2, &vega20_device_info },        /* Vega20 */
        { 0x66a3, &vega20_device_info },        /* Vega20 */
+       { 0x66a4, &vega20_device_info },        /* Vega20 */
        { 0x66a7, &vega20_device_info },        /* Vega20 */
        { 0x66af, &vega20_device_info }         /* Vega20 */
 };
index 3367dd3..3b7fce5 100644 (file)
@@ -130,7 +130,7 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
        data->registry_data.disable_auto_wattman = 1;
        data->registry_data.auto_wattman_debug = 0;
        data->registry_data.auto_wattman_sample_period = 100;
-       data->registry_data.fclk_gfxclk_ratio = 0x3F6CCCCD;
+       data->registry_data.fclk_gfxclk_ratio = 0;
        data->registry_data.auto_wattman_threshold = 50;
        data->registry_data.gfxoff_controlled_by_driver = 1;
        data->gfxoff_allowed = false;
index 62f36ba..c1a99df 100644 (file)
@@ -386,6 +386,8 @@ typedef uint16_t PPSMC_Result;
 #define PPSMC_MSG_AgmResetPsm                 ((uint16_t) 0x403)
 #define PPSMC_MSG_ReadVftCell                 ((uint16_t) 0x404)
 
+#define PPSMC_MSG_ApplyAvfsCksOffVoltage      ((uint16_t) 0x415)
+
 #define PPSMC_MSG_GFX_CU_PG_ENABLE            ((uint16_t) 0x280)
 #define PPSMC_MSG_GFX_CU_PG_DISABLE           ((uint16_t) 0x281)
 #define PPSMC_MSG_GetCurrPkgPwr               ((uint16_t) 0x282)
index 872d382..a1e0ac9 100644 (file)
@@ -1985,6 +1985,12 @@ int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
 
        smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
 
+       /* Apply avfs cks-off voltages to avoid the overshoot
+        * when switching to the highest sclk frequency
+        */
+       if (data->apply_avfs_cks_off_voltage)
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ApplyAvfsCksOffVoltage);
+
        return 0;
 }
 
index 99d5e4f..a6edd5d 100644 (file)
@@ -37,10 +37,13 @@ MODULE_FIRMWARE("amdgpu/fiji_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_k_smc.bin");
+MODULE_FIRMWARE("amdgpu/polaris10_k2_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin");
+MODULE_FIRMWARE("amdgpu/polaris11_k2_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_k_smc.bin");
 MODULE_FIRMWARE("amdgpu/vegam_smc.bin");
 MODULE_FIRMWARE("amdgpu/vega10_smc.bin");
 MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin");
index 481896f..85e6736 100644 (file)
@@ -235,7 +235,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
                plane->bpp = skl_pixel_formats[fmt].bpp;
                plane->drm_format = skl_pixel_formats[fmt].drm_format;
        } else {
-               plane->tiled = !!(val & DISPPLANE_TILED);
+               plane->tiled = val & DISPPLANE_TILED;
                fmt = bdw_format_to_drm(val & DISPPLANE_PIXFORMAT_MASK);
                plane->bpp = bdw_pixel_formats[fmt].bpp;
                plane->drm_format = bdw_pixel_formats[fmt].drm_format;
index ffdbbac..47062ee 100644 (file)
@@ -1444,6 +1444,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 
        intel_uncore_sanitize(dev_priv);
 
+       intel_gt_init_workarounds(dev_priv);
        i915_gem_load_init_fences(dev_priv);
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
index 9102571..872a2e1 100644 (file)
@@ -67,6 +67,7 @@
 #include "intel_ringbuffer.h"
 #include "intel_uncore.h"
 #include "intel_wopcm.h"
+#include "intel_workarounds.h"
 #include "intel_uc.h"
 
 #include "i915_gem.h"
@@ -1805,6 +1806,7 @@ struct drm_i915_private {
        int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
        struct i915_workarounds workarounds;
+       struct i915_wa_list gt_wa_list;
 
        struct i915_frontbuffer_tracking fb_tracking;
 
@@ -2148,6 +2150,8 @@ struct drm_i915_private {
                struct delayed_work idle_work;
 
                ktime_t last_init_time;
+
+               struct i915_vma *scratch;
        } gt;
 
        /* perform PHY state sanity checks? */
@@ -3870,4 +3874,9 @@ static inline int intel_hws_csb_write_index(struct drm_i915_private *i915)
                return I915_HWS_CSB_WRITE_INDEX;
 }
 
+static inline u32 i915_scratch_offset(const struct drm_i915_private *i915)
+{
+       return i915_ggtt_offset(i915->gt.scratch);
+}
+
 #endif
index 0c8aa57..6ae9a60 100644 (file)
@@ -5305,7 +5305,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
                }
        }
 
-       intel_gt_workarounds_apply(dev_priv);
+       intel_gt_apply_workarounds(dev_priv);
 
        i915_gem_init_swizzling(dev_priv);
 
@@ -5500,6 +5500,44 @@ err_active:
        goto out_ctx;
 }
 
+static int
+i915_gem_init_scratch(struct drm_i915_private *i915, unsigned int size)
+{
+       struct drm_i915_gem_object *obj;
+       struct i915_vma *vma;
+       int ret;
+
+       obj = i915_gem_object_create_stolen(i915, size);
+       if (!obj)
+               obj = i915_gem_object_create_internal(i915, size);
+       if (IS_ERR(obj)) {
+               DRM_ERROR("Failed to allocate scratch page\n");
+               return PTR_ERR(obj);
+       }
+
+       vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+       if (IS_ERR(vma)) {
+               ret = PTR_ERR(vma);
+               goto err_unref;
+       }
+
+       ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
+       if (ret)
+               goto err_unref;
+
+       i915->gt.scratch = vma;
+       return 0;
+
+err_unref:
+       i915_gem_object_put(obj);
+       return ret;
+}
+
+static void i915_gem_fini_scratch(struct drm_i915_private *i915)
+{
+       i915_vma_unpin_and_release(&i915->gt.scratch, 0);
+}
+
 int i915_gem_init(struct drm_i915_private *dev_priv)
 {
        int ret;
@@ -5546,12 +5584,19 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
                goto err_unlock;
        }
 
-       ret = i915_gem_contexts_init(dev_priv);
+       ret = i915_gem_init_scratch(dev_priv,
+                                   IS_GEN2(dev_priv) ? SZ_256K : PAGE_SIZE);
        if (ret) {
                GEM_BUG_ON(ret == -EIO);
                goto err_ggtt;
        }
 
+       ret = i915_gem_contexts_init(dev_priv);
+       if (ret) {
+               GEM_BUG_ON(ret == -EIO);
+               goto err_scratch;
+       }
+
        ret = intel_engines_init(dev_priv);
        if (ret) {
                GEM_BUG_ON(ret == -EIO);
@@ -5624,6 +5669,8 @@ err_pm:
 err_context:
        if (ret != -EIO)
                i915_gem_contexts_fini(dev_priv);
+err_scratch:
+       i915_gem_fini_scratch(dev_priv);
 err_ggtt:
 err_unlock:
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -5675,8 +5722,11 @@ void i915_gem_fini(struct drm_i915_private *dev_priv)
        intel_uc_fini(dev_priv);
        i915_gem_cleanup_engines(dev_priv);
        i915_gem_contexts_fini(dev_priv);
+       i915_gem_fini_scratch(dev_priv);
        mutex_unlock(&dev_priv->drm.struct_mutex);
 
+       intel_wa_list_free(&dev_priv->gt_wa_list);
+
        intel_cleanup_gt_powersave(dev_priv);
 
        intel_uc_fini_misc(dev_priv);
index d4fac09..1aaccbe 100644 (file)
@@ -1268,7 +1268,7 @@ relocate_entry(struct i915_vma *vma,
                else if (gen >= 4)
                        len = 4;
                else
-                       len = 6;
+                       len = 3;
 
                batch = reloc_gpu(eb, vma, len);
                if (IS_ERR(batch))
@@ -1309,11 +1309,6 @@ relocate_entry(struct i915_vma *vma,
                        *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
                        *batch++ = addr;
                        *batch++ = target_offset;
-
-                       /* And again for good measure (blb/pnv) */
-                       *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
-                       *batch++ = addr;
-                       *batch++ = target_offset;
                }
 
                goto out;
index 3eb33e0..db4128d 100644 (file)
@@ -1495,7 +1495,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
                        if (HAS_BROKEN_CS_TLB(i915))
                                ee->wa_batchbuffer =
                                        i915_error_object_create(i915,
-                                                                engine->scratch);
+                                                                i915->gt.scratch);
                        request_record_user_bo(request, ee);
 
                        ee->ctx =
index 217ed3e..76b5f94 100644 (file)
@@ -490,46 +490,6 @@ void intel_engine_setup_common(struct intel_engine_cs *engine)
        intel_engine_init_cmd_parser(engine);
 }
 
-int intel_engine_create_scratch(struct intel_engine_cs *engine,
-                               unsigned int size)
-{
-       struct drm_i915_gem_object *obj;
-       struct i915_vma *vma;
-       int ret;
-
-       WARN_ON(engine->scratch);
-
-       obj = i915_gem_object_create_stolen(engine->i915, size);
-       if (!obj)
-               obj = i915_gem_object_create_internal(engine->i915, size);
-       if (IS_ERR(obj)) {
-               DRM_ERROR("Failed to allocate scratch page\n");
-               return PTR_ERR(obj);
-       }
-
-       vma = i915_vma_instance(obj, &engine->i915->ggtt.vm, NULL);
-       if (IS_ERR(vma)) {
-               ret = PTR_ERR(vma);
-               goto err_unref;
-       }
-
-       ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
-       if (ret)
-               goto err_unref;
-
-       engine->scratch = vma;
-       return 0;
-
-err_unref:
-       i915_gem_object_put(obj);
-       return ret;
-}
-
-void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
-{
-       i915_vma_unpin_and_release(&engine->scratch, 0);
-}
-
 static void cleanup_status_page(struct intel_engine_cs *engine)
 {
        if (HWS_NEEDS_PHYSICAL(engine->i915)) {
@@ -704,8 +664,6 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *i915 = engine->i915;
 
-       intel_engine_cleanup_scratch(engine);
-
        cleanup_status_page(engine);
 
        intel_engine_fini_breadcrumbs(engine);
@@ -720,6 +678,8 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
        __intel_context_unpin(i915->kernel_context, engine);
 
        i915_timeline_fini(&engine->timeline);
+
+       intel_wa_list_free(&engine->wa_list);
 }
 
 u64 intel_engine_get_active_head(const struct intel_engine_cs *engine)
index 37c94a5..58d1d3d 100644 (file)
@@ -442,8 +442,13 @@ static u64 execlists_update_context(struct i915_request *rq)
         * may not be visible to the HW prior to the completion of the UC
         * register write and that we may begin execution from the context
         * before its image is complete leading to invalid PD chasing.
+        *
+        * Furthermore, Braswell, at least, wants a full mb to be sure that
+        * the writes are coherent in memory (visible to the GPU) prior to
+        * execution, and not just visible to other CPUs (as is the result of
+        * wmb).
         */
-       wmb();
+       mb();
        return ce->lrc_desc;
 }
 
@@ -1443,9 +1448,10 @@ static int execlists_request_alloc(struct i915_request *request)
 static u32 *
 gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, u32 *batch)
 {
+       /* NB no one else is allowed to scribble over scratch + 256! */
        *batch++ = MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT;
        *batch++ = i915_mmio_reg_offset(GEN8_L3SQCREG4);
-       *batch++ = i915_ggtt_offset(engine->scratch) + 256;
+       *batch++ = i915_scratch_offset(engine->i915) + 256;
        *batch++ = 0;
 
        *batch++ = MI_LOAD_REGISTER_IMM(1);
@@ -1459,7 +1465,7 @@ gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, u32 *batch)
 
        *batch++ = MI_LOAD_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT;
        *batch++ = i915_mmio_reg_offset(GEN8_L3SQCREG4);
-       *batch++ = i915_ggtt_offset(engine->scratch) + 256;
+       *batch++ = i915_scratch_offset(engine->i915) + 256;
        *batch++ = 0;
 
        return batch;
@@ -1496,7 +1502,7 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
                                       PIPE_CONTROL_GLOBAL_GTT_IVB |
                                       PIPE_CONTROL_CS_STALL |
                                       PIPE_CONTROL_QW_WRITE,
-                                      i915_ggtt_offset(engine->scratch) +
+                                      i915_scratch_offset(engine->i915) +
                                       2 * CACHELINE_BYTES);
 
        *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
@@ -1573,7 +1579,7 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
                                               PIPE_CONTROL_GLOBAL_GTT_IVB |
                                               PIPE_CONTROL_CS_STALL |
                                               PIPE_CONTROL_QW_WRITE,
-                                              i915_ggtt_offset(engine->scratch)
+                                              i915_scratch_offset(engine->i915)
                                               + 2 * CACHELINE_BYTES);
        }
 
@@ -1793,6 +1799,8 @@ static bool unexpected_starting_state(struct intel_engine_cs *engine)
 
 static int gen8_init_common_ring(struct intel_engine_cs *engine)
 {
+       intel_engine_apply_workarounds(engine);
+
        intel_mocs_init_engine(engine);
 
        intel_engine_reset_breadcrumbs(engine);
@@ -2139,7 +2147,7 @@ static int gen8_emit_flush_render(struct i915_request *request,
 {
        struct intel_engine_cs *engine = request->engine;
        u32 scratch_addr =
-               i915_ggtt_offset(engine->scratch) + 2 * CACHELINE_BYTES;
+               i915_scratch_offset(engine->i915) + 2 * CACHELINE_BYTES;
        bool vf_flush_wa = false, dc_flush_wa = false;
        u32 *cs, flags = 0;
        int len;
@@ -2476,10 +2484,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
-       ret = intel_engine_create_scratch(engine, PAGE_SIZE);
-       if (ret)
-               goto err_cleanup_common;
-
        ret = intel_init_workaround_bb(engine);
        if (ret) {
                /*
@@ -2491,11 +2495,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
                          ret);
        }
 
-       return 0;
+       intel_engine_init_workarounds(engine);
 
-err_cleanup_common:
-       intel_engine_cleanup_common(engine);
-       return ret;
+       return 0;
 }
 
 int logical_xcs_ring_init(struct intel_engine_cs *engine)
index 187bb0c..1f8d2a6 100644 (file)
@@ -69,19 +69,28 @@ unsigned int intel_ring_update_space(struct intel_ring *ring)
 static int
 gen2_render_ring_flush(struct i915_request *rq, u32 mode)
 {
+       unsigned int num_store_dw;
        u32 cmd, *cs;
 
        cmd = MI_FLUSH;
-
+       num_store_dw = 0;
        if (mode & EMIT_INVALIDATE)
                cmd |= MI_READ_FLUSH;
+       if (mode & EMIT_FLUSH)
+               num_store_dw = 4;
 
-       cs = intel_ring_begin(rq, 2);
+       cs = intel_ring_begin(rq, 2 + 3 * num_store_dw);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
 
        *cs++ = cmd;
-       *cs++ = MI_NOOP;
+       while (num_store_dw--) {
+               *cs++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
+               *cs++ = i915_scratch_offset(rq->i915);
+               *cs++ = 0;
+       }
+       *cs++ = MI_FLUSH | MI_NO_WRITE_FLUSH;
+
        intel_ring_advance(rq, cs);
 
        return 0;
@@ -150,8 +159,7 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
         */
        if (mode & EMIT_INVALIDATE) {
                *cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
-               *cs++ = i915_ggtt_offset(rq->engine->scratch) |
-                       PIPE_CONTROL_GLOBAL_GTT;
+               *cs++ = i915_scratch_offset(rq->i915) | PIPE_CONTROL_GLOBAL_GTT;
                *cs++ = 0;
                *cs++ = 0;
 
@@ -159,8 +167,7 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
                        *cs++ = MI_FLUSH;
 
                *cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
-               *cs++ = i915_ggtt_offset(rq->engine->scratch) |
-                       PIPE_CONTROL_GLOBAL_GTT;
+               *cs++ = i915_scratch_offset(rq->i915) | PIPE_CONTROL_GLOBAL_GTT;
                *cs++ = 0;
                *cs++ = 0;
        }
@@ -212,8 +219,7 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
 static int
 intel_emit_post_sync_nonzero_flush(struct i915_request *rq)
 {
-       u32 scratch_addr =
-               i915_ggtt_offset(rq->engine->scratch) + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = i915_scratch_offset(rq->i915) + 2 * CACHELINE_BYTES;
        u32 *cs;
 
        cs = intel_ring_begin(rq, 6);
@@ -246,8 +252,7 @@ intel_emit_post_sync_nonzero_flush(struct i915_request *rq)
 static int
 gen6_render_ring_flush(struct i915_request *rq, u32 mode)
 {
-       u32 scratch_addr =
-               i915_ggtt_offset(rq->engine->scratch) + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = i915_scratch_offset(rq->i915) + 2 * CACHELINE_BYTES;
        u32 *cs, flags = 0;
        int ret;
 
@@ -316,8 +321,7 @@ gen7_render_ring_cs_stall_wa(struct i915_request *rq)
 static int
 gen7_render_ring_flush(struct i915_request *rq, u32 mode)
 {
-       u32 scratch_addr =
-               i915_ggtt_offset(rq->engine->scratch) + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = i915_scratch_offset(rq->i915) + 2 * CACHELINE_BYTES;
        u32 *cs, flags = 0;
 
        /*
@@ -971,7 +975,7 @@ i965_emit_bb_start(struct i915_request *rq,
 }
 
 /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
-#define I830_BATCH_LIMIT (256*1024)
+#define I830_BATCH_LIMIT SZ_256K
 #define I830_TLB_ENTRIES (2)
 #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
 static int
@@ -979,7 +983,9 @@ i830_emit_bb_start(struct i915_request *rq,
                   u64 offset, u32 len,
                   unsigned int dispatch_flags)
 {
-       u32 *cs, cs_offset = i915_ggtt_offset(rq->engine->scratch);
+       u32 *cs, cs_offset = i915_scratch_offset(rq->i915);
+
+       GEM_BUG_ON(rq->i915->gt.scratch->size < I830_WA_SIZE);
 
        cs = intel_ring_begin(rq, 6);
        if (IS_ERR(cs))
@@ -1437,7 +1443,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
 {
        struct i915_timeline *timeline;
        struct intel_ring *ring;
-       unsigned int size;
        int err;
 
        intel_engine_setup_common(engine);
@@ -1462,21 +1467,12 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
        GEM_BUG_ON(engine->buffer);
        engine->buffer = ring;
 
-       size = PAGE_SIZE;
-       if (HAS_BROKEN_CS_TLB(engine->i915))
-               size = I830_WA_SIZE;
-       err = intel_engine_create_scratch(engine, size);
-       if (err)
-               goto err_unpin;
-
        err = intel_engine_init_common(engine);
        if (err)
-               goto err_scratch;
+               goto err_unpin;
 
        return 0;
 
-err_scratch:
-       intel_engine_cleanup_scratch(engine);
 err_unpin:
        intel_ring_unpin(ring);
 err_ring:
@@ -1550,7 +1546,7 @@ static int flush_pd_dir(struct i915_request *rq)
        /* Stall until the page table load is complete */
        *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
        *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine));
-       *cs++ = i915_ggtt_offset(engine->scratch);
+       *cs++ = i915_scratch_offset(rq->i915);
        *cs++ = MI_NOOP;
 
        intel_ring_advance(rq, cs);
@@ -1659,7 +1655,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
                        /* Insert a delay before the next switch! */
                        *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
                        *cs++ = i915_mmio_reg_offset(last_reg);
-                       *cs++ = i915_ggtt_offset(engine->scratch);
+                       *cs++ = i915_scratch_offset(rq->i915);
                        *cs++ = MI_NOOP;
                }
                *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
index 2dfa585..767a719 100644 (file)
@@ -15,6 +15,7 @@
 #include "i915_selftest.h"
 #include "i915_timeline.h"
 #include "intel_gpu_commands.h"
+#include "intel_workarounds.h"
 
 struct drm_printer;
 struct i915_sched_attr;
@@ -440,7 +441,7 @@ struct intel_engine_cs {
 
        struct intel_hw_status_page status_page;
        struct i915_ctx_workarounds wa_ctx;
-       struct i915_vma *scratch;
+       struct i915_wa_list wa_list;
 
        u32             irq_keep_mask; /* always keep these interrupts */
        u32             irq_enable_mask; /* bitmask to enable ring interrupt */
@@ -898,10 +899,6 @@ void intel_engine_setup_common(struct intel_engine_cs *engine);
 int intel_engine_init_common(struct intel_engine_cs *engine);
 void intel_engine_cleanup_common(struct intel_engine_cs *engine);
 
-int intel_engine_create_scratch(struct intel_engine_cs *engine,
-                               unsigned int size);
-void intel_engine_cleanup_scratch(struct intel_engine_cs *engine);
-
 int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_blt_ring_buffer(struct intel_engine_cs *engine);
index 4bcdeaf..6e58089 100644 (file)
  * - Public functions to init or apply the given workaround type.
  */
 
+static void wa_init_start(struct i915_wa_list *wal, const char *name)
+{
+       wal->name = name;
+}
+
+static void wa_init_finish(struct i915_wa_list *wal)
+{
+       if (!wal->count)
+               return;
+
+       DRM_DEBUG_DRIVER("Initialized %u %s workarounds\n",
+                        wal->count, wal->name);
+}
+
 static void wa_add(struct drm_i915_private *i915,
                   i915_reg_t reg, const u32 mask, const u32 val)
 {
@@ -580,160 +594,175 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
        return 0;
 }
 
-static void bdw_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void
+wal_add(struct i915_wa_list *wal, const struct i915_wa *wa)
+{
+       const unsigned int grow = 1 << 4;
+
+       GEM_BUG_ON(!is_power_of_2(grow));
+
+       if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
+               struct i915_wa *list;
+
+               list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
+                                    GFP_KERNEL);
+               if (!list) {
+                       DRM_ERROR("No space for workaround init!\n");
+                       return;
+               }
+
+               if (wal->list)
+                       memcpy(list, wal->list, sizeof(*wa) * wal->count);
+
+               wal->list = list;
+       }
+
+       wal->list[wal->count++] = *wa;
+}
+
+static void
+wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
+{
+       struct i915_wa wa = {
+               .reg = reg,
+               .mask = val,
+               .val = _MASKED_BIT_ENABLE(val)
+       };
+
+       wal_add(wal, &wa);
+}
+
+static void
+wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
+                  u32 val)
 {
+       struct i915_wa wa = {
+               .reg = reg,
+               .mask = mask,
+               .val = val
+       };
+
+       wal_add(wal, &wa);
 }
 
-static void chv_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void
+wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
+       wa_write_masked_or(wal, reg, ~0, val);
 }
 
-static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void
+wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
-       /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
-       I915_WRITE(GEN9_CSFE_CHICKEN1_RCS,
-                  _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
+       wa_write_masked_or(wal, reg, val, val);
+}
 
-       /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
-       I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
-                  GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+static void gen9_gt_workarounds_init(struct drm_i915_private *i915)
+{
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
        /* WaDisableKillLogic:bxt,skl,kbl */
-       if (!IS_COFFEELAKE(dev_priv))
-               I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
-                          ECOCHK_DIS_TLB);
+       if (!IS_COFFEELAKE(i915))
+               wa_write_or(wal,
+                           GAM_ECOCHK,
+                           ECOCHK_DIS_TLB);
 
-       if (HAS_LLC(dev_priv)) {
+       if (HAS_LLC(i915)) {
                /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
                 *
                 * Must match Display Engine. See
                 * WaCompressedResourceDisplayNewHashMode.
                 */
-               I915_WRITE(MMCD_MISC_CTRL,
-                          I915_READ(MMCD_MISC_CTRL) |
-                          MMCD_PCLA |
-                          MMCD_HOTSPOT_EN);
+               wa_write_or(wal,
+                           MMCD_MISC_CTRL,
+                           MMCD_PCLA | MMCD_HOTSPOT_EN);
        }
 
        /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */
-       I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
-                  BDW_DISABLE_HDC_INVALIDATION);
-
-       /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */
-       if (IS_GEN9_LP(dev_priv)) {
-               u32 val = I915_READ(GEN8_L3SQCREG1);
-
-               val &= ~L3_PRIO_CREDITS_MASK;
-               val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2);
-               I915_WRITE(GEN8_L3SQCREG1, val);
-       }
-
-       /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
-       I915_WRITE(GEN8_L3SQCREG4,
-                  I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES);
-
-       /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */
-       I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
-                  _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
+       wa_write_or(wal,
+                   GAM_ECOCHK,
+                   BDW_DISABLE_HDC_INVALIDATION);
 }
 
-static void skl_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void skl_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       gen9_gt_workarounds_apply(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
-       /* WaEnableGapsTsvCreditFix:skl */
-       I915_WRITE(GEN8_GARBCNTL,
-                  I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE);
+       gen9_gt_workarounds_init(i915);
 
        /* WaDisableGafsUnitClkGating:skl */
-       I915_WRITE(GEN7_UCGCTL4,
-                  I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
+       wa_write_or(wal,
+                   GEN7_UCGCTL4,
+                   GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
 
        /* WaInPlaceDecompressionHang:skl */
-       if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
-               I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
-                          I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                          GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
+       if (IS_SKL_REVID(i915, SKL_REVID_H0, REVID_FOREVER))
+               wa_write_or(wal,
+                           GEN9_GAMT_ECO_REG_RW_IA,
+                           GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void bxt_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void bxt_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       gen9_gt_workarounds_apply(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
-       /* WaDisablePooledEuLoadBalancingFix:bxt */
-       I915_WRITE(FF_SLICE_CS_CHICKEN2,
-                  _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE));
+       gen9_gt_workarounds_init(i915);
 
        /* WaInPlaceDecompressionHang:bxt */
-       I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
-                  I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                  GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
+       wa_write_or(wal,
+                   GEN9_GAMT_ECO_REG_RW_IA,
+                   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void kbl_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void kbl_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       gen9_gt_workarounds_apply(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
-       /* WaEnableGapsTsvCreditFix:kbl */
-       I915_WRITE(GEN8_GARBCNTL,
-                  I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE);
+       gen9_gt_workarounds_init(i915);
 
        /* WaDisableDynamicCreditSharing:kbl */
-       if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
-               I915_WRITE(GAMT_CHKN_BIT_REG,
-                          I915_READ(GAMT_CHKN_BIT_REG) |
-                          GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
+       if (IS_KBL_REVID(i915, 0, KBL_REVID_B0))
+               wa_write_or(wal,
+                           GAMT_CHKN_BIT_REG,
+                           GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
 
        /* WaDisableGafsUnitClkGating:kbl */
-       I915_WRITE(GEN7_UCGCTL4,
-                  I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
+       wa_write_or(wal,
+                   GEN7_UCGCTL4,
+                   GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
 
        /* WaInPlaceDecompressionHang:kbl */
-       I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
-                  I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                  GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
-
-       /* WaKBLVECSSemaphoreWaitPoll:kbl */
-       if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_E0)) {
-               struct intel_engine_cs *engine;
-               unsigned int tmp;
-
-               for_each_engine(engine, dev_priv, tmp) {
-                       if (engine->id == RCS)
-                               continue;
-
-                       I915_WRITE(RING_SEMA_WAIT_POLL(engine->mmio_base), 1);
-               }
-       }
+       wa_write_or(wal,
+                   GEN9_GAMT_ECO_REG_RW_IA,
+                   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void glk_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void glk_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       gen9_gt_workarounds_apply(dev_priv);
+       gen9_gt_workarounds_init(i915);
 }
 
-static void cfl_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void cfl_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       gen9_gt_workarounds_apply(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
-       /* WaEnableGapsTsvCreditFix:cfl */
-       I915_WRITE(GEN8_GARBCNTL,
-                  I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE);
+       gen9_gt_workarounds_init(i915);
 
        /* WaDisableGafsUnitClkGating:cfl */
-       I915_WRITE(GEN7_UCGCTL4,
-                  I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
+       wa_write_or(wal,
+                   GEN7_UCGCTL4,
+                   GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
 
        /* WaInPlaceDecompressionHang:cfl */
-       I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
-                  I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                  GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
+       wa_write_or(wal,
+                   GEN9_GAMT_ECO_REG_RW_IA,
+                   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
 static void wa_init_mcr(struct drm_i915_private *dev_priv)
 {
        const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu);
-       u32 mcr;
+       struct i915_wa_list *wal = &dev_priv->gt_wa_list;
        u32 mcr_slice_subslice_mask;
 
        /*
@@ -770,8 +799,6 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv)
                WARN_ON((enabled_mask & disabled_mask) != enabled_mask);
        }
 
-       mcr = I915_READ(GEN8_MCR_SELECTOR);
-
        if (INTEL_GEN(dev_priv) >= 11)
                mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK |
                                          GEN11_MCR_SUBSLICE_MASK;
@@ -789,148 +816,170 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv)
         * occasions, such as INSTDONE, where this value is dependent
         * on s/ss combo, the read should be done with read_subslice_reg.
         */
-       mcr &= ~mcr_slice_subslice_mask;
-       mcr |= intel_calculate_mcr_s_ss_select(dev_priv);
-       I915_WRITE(GEN8_MCR_SELECTOR, mcr);
+       wa_write_masked_or(wal,
+                          GEN8_MCR_SELECTOR,
+                          mcr_slice_subslice_mask,
+                          intel_calculate_mcr_s_ss_select(dev_priv));
 }
 
-static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void cnl_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       wa_init_mcr(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
+
+       wa_init_mcr(i915);
 
        /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */
-       if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
-               I915_WRITE(GAMT_CHKN_BIT_REG,
-                          I915_READ(GAMT_CHKN_BIT_REG) |
-                          GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT);
+       if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0))
+               wa_write_or(wal,
+                           GAMT_CHKN_BIT_REG,
+                           GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT);
 
        /* WaInPlaceDecompressionHang:cnl */
-       I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA,
-                  I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                  GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
-
-       /* WaEnablePreemptionGranularityControlByUMD:cnl */
-       I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
-                  _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
+       wa_write_or(wal,
+                   GEN9_GAMT_ECO_REG_RW_IA,
+                   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void icl_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+static void icl_gt_workarounds_init(struct drm_i915_private *i915)
 {
-       wa_init_mcr(dev_priv);
+       struct i915_wa_list *wal = &i915->gt_wa_list;
 
-       /* This is not an Wa. Enable for better image quality */
-       I915_WRITE(_3D_CHICKEN3,
-                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE));
+       wa_init_mcr(i915);
 
        /* WaInPlaceDecompressionHang:icl */
-       I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, I915_READ(GEN9_GAMT_ECO_REG_RW_IA) |
-                                           GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
-
-       /* WaPipelineFlushCoherentLines:icl */
-       I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
-                                  GEN8_LQSC_FLUSH_COHERENT_LINES);
-
-       /* Wa_1405543622:icl
-        * Formerly known as WaGAPZPriorityScheme
-        */
-       I915_WRITE(GEN8_GARBCNTL, I915_READ(GEN8_GARBCNTL) |
-                                 GEN11_ARBITRATION_PRIO_ORDER_MASK);
-
-       /* Wa_1604223664:icl
-        * Formerly known as WaL3BankAddressHashing
-        */
-       I915_WRITE(GEN8_GARBCNTL,
-                  (I915_READ(GEN8_GARBCNTL) & ~GEN11_HASH_CTRL_EXCL_MASK) |
-                  GEN11_HASH_CTRL_EXCL_BIT0);
-       I915_WRITE(GEN11_GLBLINVL,
-                  (I915_READ(GEN11_GLBLINVL) & ~GEN11_BANK_HASH_ADDR_EXCL_MASK) |
-                  GEN11_BANK_HASH_ADDR_EXCL_BIT0);
+       wa_write_or(wal,
+                   GEN9_GAMT_ECO_REG_RW_IA,
+                   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 
        /* WaModifyGamTlbPartitioning:icl */
-       I915_WRITE(GEN11_GACB_PERF_CTRL,
-                  (I915_READ(GEN11_GACB_PERF_CTRL) & ~GEN11_HASH_CTRL_MASK) |
-                  GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4);
-
-       /* Wa_1405733216:icl
-        * Formerly known as WaDisableCleanEvicts
-        */
-       I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
-                                  GEN11_LQSC_CLEAN_EVICT_DISABLE);
+       wa_write_masked_or(wal,
+                          GEN11_GACB_PERF_CTRL,
+                          GEN11_HASH_CTRL_MASK,
+                          GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4);
 
        /* Wa_1405766107:icl
         * Formerly known as WaCL2SFHalfMaxAlloc
         */
-       I915_WRITE(GEN11_LSN_UNSLCVC, I915_READ(GEN11_LSN_UNSLCVC) |
-                                     GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC |
-                                     GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC);
+       wa_write_or(wal,
+                   GEN11_LSN_UNSLCVC,
+                   GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC |
+                   GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC);
 
        /* Wa_220166154:icl
         * Formerly known as WaDisCtxReload
         */
-       I915_WRITE(GAMW_ECO_DEV_RW_IA_REG, I915_READ(GAMW_ECO_DEV_RW_IA_REG) |
-                                          GAMW_ECO_DEV_CTX_RELOAD_DISABLE);
+       wa_write_or(wal,
+                   GEN8_GAMW_ECO_DEV_RW_IA,
+                   GAMW_ECO_DEV_CTX_RELOAD_DISABLE);
 
        /* Wa_1405779004:icl (pre-prod) */
-       if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0))
-               I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE,
-                          I915_READ(SLICE_UNIT_LEVEL_CLKGATE) |
-                          MSCUNIT_CLKGATE_DIS);
+       if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
+               wa_write_or(wal,
+                           SLICE_UNIT_LEVEL_CLKGATE,
+                           MSCUNIT_CLKGATE_DIS);
 
        /* Wa_1406680159:icl */
-       I915_WRITE(SUBSLICE_UNIT_LEVEL_CLKGATE,
-                  I915_READ(SUBSLICE_UNIT_LEVEL_CLKGATE) |
-                  GWUNIT_CLKGATE_DIS);
-
-       /* Wa_1604302699:icl */
-       I915_WRITE(GEN10_L3_CHICKEN_MODE_REGISTER,
-                  I915_READ(GEN10_L3_CHICKEN_MODE_REGISTER) |
-                  GEN11_I2M_WRITE_DISABLE);
+       wa_write_or(wal,
+                   SUBSLICE_UNIT_LEVEL_CLKGATE,
+                   GWUNIT_CLKGATE_DIS);
 
        /* Wa_1406838659:icl (pre-prod) */
-       if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0))
-               I915_WRITE(INF_UNIT_LEVEL_CLKGATE,
-                          I915_READ(INF_UNIT_LEVEL_CLKGATE) |
-                          CGPSF_CLKGATE_DIS);
-
-       /* WaForwardProgressSoftReset:icl */
-       I915_WRITE(GEN10_SCRATCH_LNCF2,
-                  I915_READ(GEN10_SCRATCH_LNCF2) |
-                  PMFLUSHDONE_LNICRSDROP |
-                  PMFLUSH_GAPL3UNBLOCK |
-                  PMFLUSHDONE_LNEBLK);
+       if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
+               wa_write_or(wal,
+                           INF_UNIT_LEVEL_CLKGATE,
+                           CGPSF_CLKGATE_DIS);
 
        /* Wa_1406463099:icl
         * Formerly known as WaGamTlbPendError
         */
-       I915_WRITE(GAMT_CHKN_BIT_REG,
-                  I915_READ(GAMT_CHKN_BIT_REG) |
-                  GAMT_CHKN_DISABLE_L3_COH_PIPE);
+       wa_write_or(wal,
+                   GAMT_CHKN_BIT_REG,
+                   GAMT_CHKN_DISABLE_L3_COH_PIPE);
 }
 
-void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv)
+void intel_gt_init_workarounds(struct drm_i915_private *i915)
 {
-       if (INTEL_GEN(dev_priv) < 8)
+       struct i915_wa_list *wal = &i915->gt_wa_list;
+
+       wa_init_start(wal, "GT");
+
+       if (INTEL_GEN(i915) < 8)
                return;
-       else if (IS_BROADWELL(dev_priv))
-               bdw_gt_workarounds_apply(dev_priv);
-       else if (IS_CHERRYVIEW(dev_priv))
-               chv_gt_workarounds_apply(dev_priv);
-       else if (IS_SKYLAKE(dev_priv))
-               skl_gt_workarounds_apply(dev_priv);
-       else if (IS_BROXTON(dev_priv))
-               bxt_gt_workarounds_apply(dev_priv);
-       else if (IS_KABYLAKE(dev_priv))
-               kbl_gt_workarounds_apply(dev_priv);
-       else if (IS_GEMINILAKE(dev_priv))
-               glk_gt_workarounds_apply(dev_priv);
-       else if (IS_COFFEELAKE(dev_priv))
-               cfl_gt_workarounds_apply(dev_priv);
-       else if (IS_CANNONLAKE(dev_priv))
-               cnl_gt_workarounds_apply(dev_priv);
-       else if (IS_ICELAKE(dev_priv))
-               icl_gt_workarounds_apply(dev_priv);
+       else if (IS_BROADWELL(i915))
+               return;
+       else if (IS_CHERRYVIEW(i915))
+               return;
+       else if (IS_SKYLAKE(i915))
+               skl_gt_workarounds_init(i915);
+       else if (IS_BROXTON(i915))
+               bxt_gt_workarounds_init(i915);
+       else if (IS_KABYLAKE(i915))
+               kbl_gt_workarounds_init(i915);
+       else if (IS_GEMINILAKE(i915))
+               glk_gt_workarounds_init(i915);
+       else if (IS_COFFEELAKE(i915))
+               cfl_gt_workarounds_init(i915);
+       else if (IS_CANNONLAKE(i915))
+               cnl_gt_workarounds_init(i915);
+       else if (IS_ICELAKE(i915))
+               icl_gt_workarounds_init(i915);
        else
-               MISSING_CASE(INTEL_GEN(dev_priv));
+               MISSING_CASE(INTEL_GEN(i915));
+
+       wa_init_finish(wal);
+}
+
+static enum forcewake_domains
+wal_get_fw_for_rmw(struct drm_i915_private *dev_priv,
+                  const struct i915_wa_list *wal)
+{
+       enum forcewake_domains fw = 0;
+       struct i915_wa *wa;
+       unsigned int i;
+
+       for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+               fw |= intel_uncore_forcewake_for_reg(dev_priv,
+                                                    wa->reg,
+                                                    FW_REG_READ |
+                                                    FW_REG_WRITE);
+
+       return fw;
+}
+
+static void
+wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal)
+{
+       enum forcewake_domains fw;
+       unsigned long flags;
+       struct i915_wa *wa;
+       unsigned int i;
+
+       if (!wal->count)
+               return;
+
+       fw = wal_get_fw_for_rmw(dev_priv, wal);
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, flags);
+       intel_uncore_forcewake_get__locked(dev_priv, fw);
+
+       for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
+               u32 val = I915_READ_FW(wa->reg);
+
+               val &= ~wa->mask;
+               val |= wa->val;
+
+               I915_WRITE_FW(wa->reg, val);
+       }
+
+       intel_uncore_forcewake_put__locked(dev_priv, fw);
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
+
+       DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
+}
+
+void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv)
+{
+       wa_list_apply(dev_priv, &dev_priv->gt_wa_list);
 }
 
 struct whitelist {
@@ -1077,6 +1126,146 @@ void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine)
        whitelist_apply(engine, whitelist_build(engine, &w));
 }
 
+static void rcs_engine_wa_init(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->wa_list;
+
+       if (IS_ICELAKE(i915)) {
+               /* This is not an Wa. Enable for better image quality */
+               wa_masked_en(wal,
+                            _3D_CHICKEN3,
+                            _3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE);
+
+               /* WaPipelineFlushCoherentLines:icl */
+               wa_write_or(wal,
+                           GEN8_L3SQCREG4,
+                           GEN8_LQSC_FLUSH_COHERENT_LINES);
+
+               /*
+                * Wa_1405543622:icl
+                * Formerly known as WaGAPZPriorityScheme
+                */
+               wa_write_or(wal,
+                           GEN8_GARBCNTL,
+                           GEN11_ARBITRATION_PRIO_ORDER_MASK);
+
+               /*
+                * Wa_1604223664:icl
+                * Formerly known as WaL3BankAddressHashing
+                */
+               wa_write_masked_or(wal,
+                                  GEN8_GARBCNTL,
+                                  GEN11_HASH_CTRL_EXCL_MASK,
+                                  GEN11_HASH_CTRL_EXCL_BIT0);
+               wa_write_masked_or(wal,
+                                  GEN11_GLBLINVL,
+                                  GEN11_BANK_HASH_ADDR_EXCL_MASK,
+                                  GEN11_BANK_HASH_ADDR_EXCL_BIT0);
+
+               /*
+                * Wa_1405733216:icl
+                * Formerly known as WaDisableCleanEvicts
+                */
+               wa_write_or(wal,
+                           GEN8_L3SQCREG4,
+                           GEN11_LQSC_CLEAN_EVICT_DISABLE);
+
+               /* Wa_1604302699:icl */
+               wa_write_or(wal,
+                           GEN10_L3_CHICKEN_MODE_REGISTER,
+                           GEN11_I2M_WRITE_DISABLE);
+
+               /* WaForwardProgressSoftReset:icl */
+               wa_write_or(wal,
+                           GEN10_SCRATCH_LNCF2,
+                           PMFLUSHDONE_LNICRSDROP |
+                           PMFLUSH_GAPL3UNBLOCK |
+                           PMFLUSHDONE_LNEBLK);
+       }
+
+       if (IS_GEN9(i915) || IS_CANNONLAKE(i915)) {
+               /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,cnl */
+               wa_masked_en(wal,
+                            GEN7_FF_SLICE_CS_CHICKEN1,
+                            GEN9_FFSC_PERCTX_PREEMPT_CTRL);
+       }
+
+       if (IS_SKYLAKE(i915) || IS_KABYLAKE(i915) || IS_COFFEELAKE(i915)) {
+               /* WaEnableGapsTsvCreditFix:skl,kbl,cfl */
+               wa_write_or(wal,
+                           GEN8_GARBCNTL,
+                           GEN9_GAPS_TSV_CREDIT_DISABLE);
+       }
+
+       if (IS_BROXTON(i915)) {
+               /* WaDisablePooledEuLoadBalancingFix:bxt */
+               wa_masked_en(wal,
+                            FF_SLICE_CS_CHICKEN2,
+                            GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
+       }
+
+       if (IS_GEN9(i915)) {
+               /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
+               wa_masked_en(wal,
+                            GEN9_CSFE_CHICKEN1_RCS,
+                            GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE);
+
+               /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
+               wa_write_or(wal,
+                           BDW_SCRATCH1,
+                           GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+
+               /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */
+               if (IS_GEN9_LP(i915))
+                       wa_write_masked_or(wal,
+                                          GEN8_L3SQCREG1,
+                                          L3_PRIO_CREDITS_MASK,
+                                          L3_GENERAL_PRIO_CREDITS(62) |
+                                          L3_HIGH_PRIO_CREDITS(2));
+
+               /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
+               wa_write_or(wal,
+                           GEN8_L3SQCREG4,
+                           GEN8_LQSC_FLUSH_COHERENT_LINES);
+       }
+}
+
+static void xcs_engine_wa_init(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->wa_list;
+
+       /* WaKBLVECSSemaphoreWaitPoll:kbl */
+       if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) {
+               wa_write(wal,
+                        RING_SEMA_WAIT_POLL(engine->mmio_base),
+                        1);
+       }
+}
+
+void intel_engine_init_workarounds(struct intel_engine_cs *engine)
+{
+       struct i915_wa_list *wal = &engine->wa_list;
+
+       if (GEM_WARN_ON(INTEL_GEN(engine->i915) < 8))
+               return;
+
+       wa_init_start(wal, engine->name);
+
+       if (engine->id == RCS)
+               rcs_engine_wa_init(engine);
+       else
+               xcs_engine_wa_init(engine);
+
+       wa_init_finish(wal);
+}
+
+void intel_engine_apply_workarounds(struct intel_engine_cs *engine)
+{
+       wa_list_apply(engine->i915, &engine->wa_list);
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/intel_workarounds.c"
 #endif
index b11d062..979695a 100644 (file)
@@ -7,11 +7,35 @@
 #ifndef _I915_WORKAROUNDS_H_
 #define _I915_WORKAROUNDS_H_
 
+#include <linux/slab.h>
+
+struct i915_wa {
+       i915_reg_t        reg;
+       u32               mask;
+       u32               val;
+};
+
+struct i915_wa_list {
+       const char      *name;
+       struct i915_wa  *list;
+       unsigned int    count;
+};
+
+static inline void intel_wa_list_free(struct i915_wa_list *wal)
+{
+       kfree(wal->list);
+       memset(wal, 0, sizeof(*wal));
+}
+
 int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv);
 int intel_ctx_workarounds_emit(struct i915_request *rq);
 
-void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv);
+void intel_gt_init_workarounds(struct drm_i915_private *dev_priv);
+void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);
 
 void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine);
 
+void intel_engine_init_workarounds(struct intel_engine_cs *engine);
+void intel_engine_apply_workarounds(struct intel_engine_cs *engine);
+
 #endif
index 66df1b1..27b507e 100644 (file)
@@ -818,10 +818,13 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
        dsi->encoder.possible_crtcs = 1;
 
        /* If there's a bridge, attach to it and let it create the connector */
-       ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
-       if (ret) {
-               DRM_ERROR("Failed to attach bridge to drm\n");
-
+       if (dsi->bridge) {
+               ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
+               if (ret) {
+                       DRM_ERROR("Failed to attach bridge to drm\n");
+                       goto err_encoder_cleanup;
+               }
+       } else {
                /* Otherwise create our own connector and attach to a panel */
                ret = mtk_dsi_create_connector(drm, dsi);
                if (ret)
index 6cbbae3..db1bf7f 100644 (file)
@@ -198,6 +198,22 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
 /******************************************************************************
  * EVO channel helpers
  *****************************************************************************/
+static void
+evo_flush(struct nv50_dmac *dmac)
+{
+       /* Push buffer fetches are not coherent with BAR1, we need to ensure
+        * writes have been flushed right through to VRAM before writing PUT.
+        */
+       if (dmac->push.type & NVIF_MEM_VRAM) {
+               struct nvif_device *device = dmac->base.device;
+               nvif_wr32(&device->object, 0x070000, 0x00000001);
+               nvif_msec(device, 2000,
+                       if (!(nvif_rd32(&device->object, 0x070000) & 0x00000002))
+                               break;
+               );
+       }
+}
+
 u32 *
 evo_wait(struct nv50_dmac *evoc, int nr)
 {
@@ -208,6 +224,7 @@ evo_wait(struct nv50_dmac *evoc, int nr)
        mutex_lock(&dmac->lock);
        if (put + nr >= (PAGE_SIZE / 4) - 8) {
                dmac->ptr[put] = 0x20000000;
+               evo_flush(dmac);
 
                nvif_wr32(&dmac->base.user, 0x0000, 0x00000000);
                if (nvif_msec(device, 2000,
@@ -230,17 +247,7 @@ evo_kick(u32 *push, struct nv50_dmac *evoc)
 {
        struct nv50_dmac *dmac = evoc;
 
-       /* Push buffer fetches are not coherent with BAR1, we need to ensure
-        * writes have been flushed right through to VRAM before writing PUT.
-        */
-       if (dmac->push.type & NVIF_MEM_VRAM) {
-               struct nvif_device *device = dmac->base.device;
-               nvif_wr32(&device->object, 0x070000, 0x00000001);
-               nvif_msec(device, 2000,
-                       if (!(nvif_rd32(&device->object, 0x070000) & 0x00000002))
-                               break;
-               );
-       }
+       evo_flush(dmac);
 
        nvif_wr32(&dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
        mutex_unlock(&dmac->lock);
@@ -1264,6 +1271,7 @@ nv50_mstm_del(struct nv50_mstm **pmstm)
 {
        struct nv50_mstm *mstm = *pmstm;
        if (mstm) {
+               drm_dp_mst_topology_mgr_destroy(&mstm->mgr);
                kfree(*pmstm);
                *pmstm = NULL;
        }
index 2b2baf6..d2928d4 100644 (file)
@@ -1171,10 +1171,16 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
                goto err_free;
        }
 
+       err = nouveau_drm_device_init(drm);
+       if (err)
+               goto err_put;
+
        platform_set_drvdata(pdev, drm);
 
        return drm;
 
+err_put:
+       drm_dev_put(drm);
 err_free:
        nvkm_device_del(pdevice);
 
index 941f352..5864cb4 100644 (file)
@@ -448,11 +448,6 @@ static int rockchip_drm_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
-static void rockchip_drm_platform_shutdown(struct platform_device *pdev)
-{
-       rockchip_drm_platform_remove(pdev);
-}
-
 static const struct of_device_id rockchip_drm_dt_ids[] = {
        { .compatible = "rockchip,display-subsystem", },
        { /* sentinel */ },
@@ -462,7 +457,6 @@ MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
 static struct platform_driver rockchip_drm_platform_driver = {
        .probe = rockchip_drm_platform_probe,
        .remove = rockchip_drm_platform_remove,
-       .shutdown = rockchip_drm_platform_shutdown,
        .driver = {
                .name = "rockchip-drm",
                .of_match_table = rockchip_drm_dt_ids,
index 61a84b9..d7a2dfb 100644 (file)
@@ -49,6 +49,8 @@
 
 #define VMWGFX_REPO "In Tree"
 
+#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE)
+
 
 /**
  * Fully encoded drm commands. Might move to vmw_drm.h
@@ -918,7 +920,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                spin_unlock(&dev_priv->cap_lock);
        }
 
-
+       vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN);
        ret = vmw_kms_init(dev_priv);
        if (unlikely(ret != 0))
                goto out_no_kms;
index 59f6142..aca974b 100644 (file)
@@ -606,6 +606,9 @@ struct vmw_private {
 
        struct vmw_cmdbuf_man *cman;
        DECLARE_BITMAP(irqthread_pending, VMW_IRQTHREAD_MAX);
+
+       /* Validation memory reservation */
+       struct vmw_validation_mem vvm;
 };
 
 static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
@@ -846,6 +849,8 @@ extern int vmw_ttm_global_init(struct vmw_private *dev_priv);
 extern void vmw_ttm_global_release(struct vmw_private *dev_priv);
 extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
 
+extern void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv,
+                                       size_t gran);
 /**
  * TTM buffer object driver - vmwgfx_ttm_buffer.c
  */
index 5a6b70b..f2d13a7 100644 (file)
@@ -1738,7 +1738,6 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
                                      void *buf)
 {
        struct vmw_buffer_object *vmw_bo;
-       int ret;
 
        struct {
                uint32_t header;
@@ -1748,7 +1747,6 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
        return vmw_translate_guest_ptr(dev_priv, sw_context,
                                       &cmd->body.ptr,
                                       &vmw_bo);
-       return ret;
 }
 
 
@@ -3837,6 +3835,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        struct sync_file *sync_file = NULL;
        DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
 
+       vmw_validation_set_val_mem(&val_ctx, &dev_priv->vvm);
+
        if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
                out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
                if (out_fence_fd < 0) {
index 7b1e5a5..f882470 100644 (file)
@@ -96,3 +96,39 @@ void vmw_ttm_global_release(struct vmw_private *dev_priv)
        drm_global_item_unref(&dev_priv->bo_global_ref.ref);
        drm_global_item_unref(&dev_priv->mem_global_ref);
 }
+
+/* struct vmw_validation_mem callback */
+static int vmw_vmt_reserve(struct vmw_validation_mem *m, size_t size)
+{
+       static struct ttm_operation_ctx ctx = {.interruptible = false,
+                                              .no_wait_gpu = false};
+       struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
+
+       return ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ctx);
+}
+
+/* struct vmw_validation_mem callback */
+static void vmw_vmt_unreserve(struct vmw_validation_mem *m, size_t size)
+{
+       struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
+
+       return ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_validation_mem_init_ttm - Interface the validation memory tracker
+ * to ttm.
+ * @dev_priv: Pointer to struct vmw_private. The reason we choose a vmw private
+ * rather than a struct vmw_validation_mem is to make sure assumption in the
+ * callbacks that struct vmw_private derives from struct vmw_validation_mem
+ * holds true.
+ * @gran: The recommended allocation granularity
+ */
+void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv, size_t gran)
+{
+       struct vmw_validation_mem *vvm = &dev_priv->vvm;
+
+       vvm->reserve_mem = vmw_vmt_reserve;
+       vvm->unreserve_mem = vmw_vmt_unreserve;
+       vvm->gran = gran;
+}
index 184025f..f116f09 100644 (file)
@@ -104,11 +104,25 @@ void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
                return NULL;
 
        if (ctx->mem_size_left < size) {
-               struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               struct page *page;
 
+               if (ctx->vm && ctx->vm_size_left < PAGE_SIZE) {
+                       int ret = ctx->vm->reserve_mem(ctx->vm, ctx->vm->gran);
+
+                       if (ret)
+                               return NULL;
+
+                       ctx->vm_size_left += ctx->vm->gran;
+                       ctx->total_mem += ctx->vm->gran;
+               }
+
+               page = alloc_page(GFP_KERNEL | __GFP_ZERO);
                if (!page)
                        return NULL;
 
+               if (ctx->vm)
+                       ctx->vm_size_left -= PAGE_SIZE;
+
                list_add_tail(&page->lru, &ctx->page_list);
                ctx->page_address = page_address(page);
                ctx->mem_size_left = PAGE_SIZE;
@@ -138,6 +152,11 @@ static void vmw_validation_mem_free(struct vmw_validation_context *ctx)
        }
 
        ctx->mem_size_left = 0;
+       if (ctx->vm && ctx->total_mem) {
+               ctx->vm->unreserve_mem(ctx->vm, ctx->total_mem);
+               ctx->total_mem = 0;
+               ctx->vm_size_left = 0;
+       }
 }
 
 /**
index b57e329..3b396fe 100644 (file)
 #include <drm/ttm/ttm_execbuf_util.h>
 
 /**
+ * struct vmw_validation_mem - Custom interface to provide memory reservations
+ * for the validation code.
+ * @reserve_mem: Callback to reserve memory
+ * @unreserve_mem: Callback to unreserve memory
+ * @gran: Reservation granularity. Contains a hint how much memory should
+ * be reserved in each call to @reserve_mem(). A slow implementation may want
+ * reservation to be done in large batches.
+ */
+struct vmw_validation_mem {
+       int (*reserve_mem)(struct vmw_validation_mem *m, size_t size);
+       void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size);
+       size_t gran;
+};
+
+/**
  * struct vmw_validation_context - Per command submission validation context
  * @ht: Hash table used to find resource- or buffer object duplicates
  * @resource_list: List head for resource validation metadata
  * buffer objects
  * @mem_size_left: Free memory left in the last page in @page_list
  * @page_address: Kernel virtual address of the last page in @page_list
+ * @vm: A pointer to the memory reservation interface or NULL if no
+ * memory reservation is needed.
+ * @vm_size_left: Amount of reserved memory that so far has not been allocated.
+ * @total_mem: Amount of reserved memory.
  */
 struct vmw_validation_context {
        struct drm_open_hash *ht;
@@ -59,6 +78,9 @@ struct vmw_validation_context {
        unsigned int merge_dups;
        unsigned int mem_size_left;
        u8 *page_address;
+       struct vmw_validation_mem *vm;
+       size_t vm_size_left;
+       size_t total_mem;
 };
 
 struct vmw_buffer_object;
@@ -102,6 +124,21 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
 }
 
 /**
+ * vmw_validation_set_val_mem - Register a validation mem object for
+ * validation memory reservation
+ * @ctx: The validation context
+ * @vm: Pointer to a struct vmw_validation_mem
+ *
+ * Must be set before the first attempt to allocate validation memory.
+ */
+static inline void
+vmw_validation_set_val_mem(struct vmw_validation_context *ctx,
+                          struct vmw_validation_mem *vm)
+{
+       ctx->vm = vm;
+}
+
+/**
  * vmw_validation_set_ht - Register a hash table for duplicate finding
  * @ctx: The validation context
  * @ht: Pointer to a hash table to use for duplicate finding
index ed35c9a..27519eb 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef HID_IDS_H_FILE
 #define HID_IDS_H_FILE
 
+#define USB_VENDOR_ID_258A             0x258a
+#define USB_DEVICE_ID_258A_6A88                0x6a88
+
 #define USB_VENDOR_ID_3M               0x0596
 #define USB_DEVICE_ID_3M1968           0x0500
 #define USB_DEVICE_ID_3M2256           0x0502
 #define USB_VENDOR_ID_REALTEK          0x0bda
 #define USB_DEVICE_ID_REALTEK_READER   0x0152
 
+#define USB_VENDOR_ID_RETROUSB         0xf000
+#define USB_DEVICE_ID_RETROUSB_SNES_RETROPAD   0x0003
+#define USB_DEVICE_ID_RETROUSB_SNES_RETROPORT  0x00f1
+
 #define USB_VENDOR_ID_ROCCAT           0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO      0x30d4
 #define USB_DEVICE_ID_ROCCAT_ISKU      0x319c
index 1882a4a..98b059d 100644 (file)
@@ -42,6 +42,7 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
 
 static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index c85a799..94088c0 100644 (file)
@@ -137,6 +137,8 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER), HID_QUIRK_NO_INIT_REPORTS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
        { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
index 25d43c8..558de0b 100644 (file)
@@ -267,6 +267,9 @@ is_upper_ndev_bond_master_filter(struct ib_device *ib_dev, u8 port,
        struct net_device *cookie_ndev = cookie;
        bool match = false;
 
+       if (!rdma_ndev)
+               return false;
+
        rcu_read_lock();
        if (netif_is_bond_master(cookie_ndev) &&
            rdma_is_upper_dev_rcu(rdma_ndev, cookie_ndev))
index 9b20479..7e6d709 100644 (file)
@@ -12500,7 +12500,8 @@ static int init_cntrs(struct hfi1_devdata *dd)
        }
 
        /* allocate space for the counter values */
-       dd->cntrs = kcalloc(dd->ndevcntrs, sizeof(u64), GFP_KERNEL);
+       dd->cntrs = kcalloc(dd->ndevcntrs + num_driver_cntrs, sizeof(u64),
+                           GFP_KERNEL);
        if (!dd->cntrs)
                goto bail;
 
index 1401b6e..2b88234 100644 (file)
@@ -155,6 +155,8 @@ struct hfi1_ib_stats {
 extern struct hfi1_ib_stats hfi1_stats;
 extern const struct pci_error_handlers hfi1_pci_err_handler;
 
+extern int num_driver_cntrs;
+
 /*
  * First-cut criterion for "device is active" is
  * two thousand dwords combined Tx, Rx traffic per
index 6f3bc4d..1a01624 100644 (file)
@@ -340,6 +340,13 @@ int hfi1_setup_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe, bool *call_send)
        default:
                break;
        }
+
+       /*
+        * System latency between send and schedule is large enough that
+        * forcing call_send to true for piothreshold packets is necessary.
+        */
+       if (wqe->length <= piothreshold)
+               *call_send = true;
        return 0;
 }
 
index 48e11e5..a365089 100644 (file)
@@ -1479,7 +1479,7 @@ static const char * const driver_cntr_names[] = {
 static DEFINE_MUTEX(cntr_names_lock); /* protects the *_cntr_names bufers */
 static const char **dev_cntr_names;
 static const char **port_cntr_names;
-static int num_driver_cntrs = ARRAY_SIZE(driver_cntr_names);
+int num_driver_cntrs = ARRAY_SIZE(driver_cntr_names);
 static int num_dev_cntrs;
 static int num_port_cntrs;
 static int cntr_names_initialized;
index 61aab7c..45c421c 100644 (file)
@@ -1066,7 +1066,9 @@ static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
 
        err = uverbs_get_flags32(&access, attrs,
                                 MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
-                                IB_ACCESS_SUPPORTED);
+                                IB_ACCESS_LOCAL_WRITE |
+                                IB_ACCESS_REMOTE_WRITE |
+                                IB_ACCESS_REMOTE_READ);
        if (err)
                return err;
 
index 2cc3d69..4dc6cc6 100644 (file)
@@ -506,14 +506,13 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
 static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                        u64 io_virt, size_t bcnt, u32 *bytes_mapped)
 {
+       int npages = 0, current_seq, page_shift, ret, np;
+       bool implicit = false;
        struct ib_umem_odp *odp_mr = to_ib_umem_odp(mr->umem);
        u64 access_mask = ODP_READ_ALLOWED_BIT;
-       int npages = 0, page_shift, np;
        u64 start_idx, page_mask;
        struct ib_umem_odp *odp;
-       int current_seq;
        size_t size;
-       int ret;
 
        if (!odp_mr->page_list) {
                odp = implicit_mr_get_data(mr, io_virt, bcnt);
@@ -521,7 +520,7 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                if (IS_ERR(odp))
                        return PTR_ERR(odp);
                mr = odp->private;
-
+               implicit = true;
        } else {
                odp = odp_mr;
        }
@@ -600,7 +599,7 @@ next_mr:
 
 out:
        if (ret == -EAGAIN) {
-               if (mr->parent || !odp->dying) {
+               if (implicit || !odp->dying) {
                        unsigned long timeout =
                                msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
 
index 5936de7..6fc9383 100644 (file)
@@ -930,6 +930,10 @@ static int blocks_are_clean_separate_dirty(struct dm_cache_metadata *cmd,
        bool dirty_flag;
        *result = true;
 
+       if (from_cblock(cmd->cache_blocks) == 0)
+               /* Nothing to do */
+               return 0;
+
        r = dm_bitset_cursor_begin(&cmd->dirty_info, cmd->dirty_root,
                                   from_cblock(cmd->cache_blocks), &cmd->dirty_cursor);
        if (r) {
index 0bd8d49..dadd969 100644 (file)
@@ -195,7 +195,7 @@ static void throttle_unlock(struct throttle *t)
 struct dm_thin_new_mapping;
 
 /*
- * The pool runs in 4 modes.  Ordered in degraded order for comparisons.
+ * The pool runs in various modes.  Ordered in degraded order for comparisons.
  */
 enum pool_mode {
        PM_WRITE,               /* metadata may be changed */
@@ -282,9 +282,38 @@ struct pool {
        mempool_t mapping_pool;
 };
 
-static enum pool_mode get_pool_mode(struct pool *pool);
 static void metadata_operation_failed(struct pool *pool, const char *op, int r);
 
+static enum pool_mode get_pool_mode(struct pool *pool)
+{
+       return pool->pf.mode;
+}
+
+static void notify_of_pool_mode_change(struct pool *pool)
+{
+       const char *descs[] = {
+               "write",
+               "out-of-data-space",
+               "read-only",
+               "read-only",
+               "fail"
+       };
+       const char *extra_desc = NULL;
+       enum pool_mode mode = get_pool_mode(pool);
+
+       if (mode == PM_OUT_OF_DATA_SPACE) {
+               if (!pool->pf.error_if_no_space)
+                       extra_desc = " (queue IO)";
+               else
+                       extra_desc = " (error IO)";
+       }
+
+       dm_table_event(pool->ti->table);
+       DMINFO("%s: switching pool to %s%s mode",
+              dm_device_name(pool->pool_md),
+              descs[(int)mode], extra_desc ? : "");
+}
+
 /*
  * Target context for a pool.
  */
@@ -2351,8 +2380,6 @@ static void do_waker(struct work_struct *ws)
        queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
 }
 
-static void notify_of_pool_mode_change_to_oods(struct pool *pool);
-
 /*
  * We're holding onto IO to allow userland time to react.  After the
  * timeout either the pool will have been resized (and thus back in
@@ -2365,7 +2392,7 @@ static void do_no_space_timeout(struct work_struct *ws)
 
        if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) {
                pool->pf.error_if_no_space = true;
-               notify_of_pool_mode_change_to_oods(pool);
+               notify_of_pool_mode_change(pool);
                error_retry_list_with_code(pool, BLK_STS_NOSPC);
        }
 }
@@ -2433,26 +2460,6 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *))
 
 /*----------------------------------------------------------------*/
 
-static enum pool_mode get_pool_mode(struct pool *pool)
-{
-       return pool->pf.mode;
-}
-
-static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode)
-{
-       dm_table_event(pool->ti->table);
-       DMINFO("%s: switching pool to %s mode",
-              dm_device_name(pool->pool_md), new_mode);
-}
-
-static void notify_of_pool_mode_change_to_oods(struct pool *pool)
-{
-       if (!pool->pf.error_if_no_space)
-               notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)");
-       else
-               notify_of_pool_mode_change(pool, "out-of-data-space (error IO)");
-}
-
 static bool passdown_enabled(struct pool_c *pt)
 {
        return pt->adjusted_pf.discard_passdown;
@@ -2501,8 +2508,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
 
        switch (new_mode) {
        case PM_FAIL:
-               if (old_mode != new_mode)
-                       notify_of_pool_mode_change(pool, "failure");
                dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_fail;
                pool->process_discard = process_bio_fail;
@@ -2516,8 +2521,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
 
        case PM_OUT_OF_METADATA_SPACE:
        case PM_READ_ONLY:
-               if (!is_read_only_pool_mode(old_mode))
-                       notify_of_pool_mode_change(pool, "read-only");
                dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_read_only;
                pool->process_discard = process_bio_success;
@@ -2538,8 +2541,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                 * alarming rate.  Adjust your low water mark if you're
                 * frequently seeing this mode.
                 */
-               if (old_mode != new_mode)
-                       notify_of_pool_mode_change_to_oods(pool);
                pool->out_of_data_space = true;
                pool->process_bio = process_bio_read_only;
                pool->process_discard = process_discard_bio;
@@ -2552,8 +2553,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                break;
 
        case PM_WRITE:
-               if (old_mode != new_mode)
-                       notify_of_pool_mode_change(pool, "write");
                if (old_mode == PM_OUT_OF_DATA_SPACE)
                        cancel_delayed_work_sync(&pool->no_space_timeout);
                pool->out_of_data_space = false;
@@ -2573,6 +2572,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
         * doesn't cause an unexpected mode transition on resume.
         */
        pt->adjusted_pf.mode = new_mode;
+
+       if (old_mode != new_mode)
+               notify_of_pool_mode_change(pool);
 }
 
 static void abort_transaction(struct pool *pool)
@@ -4023,7 +4025,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 20, 0},
+       .version = {1, 21, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -4397,7 +4399,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 20, 0},
+       .version = {1, 21, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
index 981154e..6af5bab 100644 (file)
@@ -20,7 +20,6 @@ struct dmz_bioctx {
        struct dm_zone          *zone;
        struct bio              *bio;
        refcount_t              ref;
-       blk_status_t            status;
 };
 
 /*
@@ -78,65 +77,66 @@ static inline void dmz_bio_endio(struct bio *bio, blk_status_t status)
 {
        struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
 
-       if (bioctx->status == BLK_STS_OK && status != BLK_STS_OK)
-               bioctx->status = status;
-       bio_endio(bio);
+       if (status != BLK_STS_OK && bio->bi_status == BLK_STS_OK)
+               bio->bi_status = status;
+
+       if (refcount_dec_and_test(&bioctx->ref)) {
+               struct dm_zone *zone = bioctx->zone;
+
+               if (zone) {
+                       if (bio->bi_status != BLK_STS_OK &&
+                           bio_op(bio) == REQ_OP_WRITE &&
+                           dmz_is_seq(zone))
+                               set_bit(DMZ_SEQ_WRITE_ERR, &zone->flags);
+                       dmz_deactivate_zone(zone);
+               }
+               bio_endio(bio);
+       }
 }
 
 /*
- * Partial clone read BIO completion callback. This terminates the
+ * Completion callback for an internally cloned target BIO. This terminates the
  * target BIO when there are no more references to its context.
  */
-static void dmz_read_bio_end_io(struct bio *bio)
+static void dmz_clone_endio(struct bio *clone)
 {
-       struct dmz_bioctx *bioctx = bio->bi_private;
-       blk_status_t status = bio->bi_status;
+       struct dmz_bioctx *bioctx = clone->bi_private;
+       blk_status_t status = clone->bi_status;
 
-       bio_put(bio);
+       bio_put(clone);
        dmz_bio_endio(bioctx->bio, status);
 }
 
 /*
- * Issue a BIO to a zone. The BIO may only partially process the
+ * Issue a clone of a target BIO. The clone may only partially process the
  * original target BIO.
  */
-static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone,
-                              struct bio *bio, sector_t chunk_block,
-                              unsigned int nr_blocks)
+static int dmz_submit_bio(struct dmz_target *dmz, struct dm_zone *zone,
+                         struct bio *bio, sector_t chunk_block,
+                         unsigned int nr_blocks)
 {
        struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-       sector_t sector;
        struct bio *clone;
 
-       /* BIO remap sector */
-       sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
-
-       /* If the read is not partial, there is no need to clone the BIO */
-       if (nr_blocks == dmz_bio_blocks(bio)) {
-               /* Setup and submit the BIO */
-               bio->bi_iter.bi_sector = sector;
-               refcount_inc(&bioctx->ref);
-               generic_make_request(bio);
-               return 0;
-       }
-
-       /* Partial BIO: we need to clone the BIO */
        clone = bio_clone_fast(bio, GFP_NOIO, &dmz->bio_set);
        if (!clone)
                return -ENOMEM;
 
-       /* Setup the clone */
-       clone->bi_iter.bi_sector = sector;
+       bio_set_dev(clone, dmz->dev->bdev);
+       clone->bi_iter.bi_sector =
+               dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
        clone->bi_iter.bi_size = dmz_blk2sect(nr_blocks) << SECTOR_SHIFT;
-       clone->bi_end_io = dmz_read_bio_end_io;
+       clone->bi_end_io = dmz_clone_endio;
        clone->bi_private = bioctx;
 
        bio_advance(bio, clone->bi_iter.bi_size);
 
-       /* Submit the clone */
        refcount_inc(&bioctx->ref);
        generic_make_request(clone);
 
+       if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone))
+               zone->wp_block += nr_blocks;
+
        return 0;
 }
 
@@ -214,7 +214,7 @@ static int dmz_handle_read(struct dmz_target *dmz, struct dm_zone *zone,
                if (nr_blocks) {
                        /* Valid blocks found: read them */
                        nr_blocks = min_t(unsigned int, nr_blocks, end_block - chunk_block);
-                       ret = dmz_submit_read_bio(dmz, rzone, bio, chunk_block, nr_blocks);
+                       ret = dmz_submit_bio(dmz, rzone, bio, chunk_block, nr_blocks);
                        if (ret)
                                return ret;
                        chunk_block += nr_blocks;
@@ -229,25 +229,6 @@ static int dmz_handle_read(struct dmz_target *dmz, struct dm_zone *zone,
 }
 
 /*
- * Issue a write BIO to a zone.
- */
-static void dmz_submit_write_bio(struct dmz_target *dmz, struct dm_zone *zone,
-                                struct bio *bio, sector_t chunk_block,
-                                unsigned int nr_blocks)
-{
-       struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-
-       /* Setup and submit the BIO */
-       bio_set_dev(bio, dmz->dev->bdev);
-       bio->bi_iter.bi_sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
-       refcount_inc(&bioctx->ref);
-       generic_make_request(bio);
-
-       if (dmz_is_seq(zone))
-               zone->wp_block += nr_blocks;
-}
-
-/*
  * Write blocks directly in a data zone, at the write pointer.
  * If a buffer zone is assigned, invalidate the blocks written
  * in place.
@@ -265,7 +246,9 @@ static int dmz_handle_direct_write(struct dmz_target *dmz,
                return -EROFS;
 
        /* Submit write */
-       dmz_submit_write_bio(dmz, zone, bio, chunk_block, nr_blocks);
+       ret = dmz_submit_bio(dmz, zone, bio, chunk_block, nr_blocks);
+       if (ret)
+               return ret;
 
        /*
         * Validate the blocks in the data zone and invalidate
@@ -301,7 +284,9 @@ static int dmz_handle_buffered_write(struct dmz_target *dmz,
                return -EROFS;
 
        /* Submit write */
-       dmz_submit_write_bio(dmz, bzone, bio, chunk_block, nr_blocks);
+       ret = dmz_submit_bio(dmz, bzone, bio, chunk_block, nr_blocks);
+       if (ret)
+               return ret;
 
        /*
         * Validate the blocks in the buffer zone
@@ -600,7 +585,6 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
        bioctx->zone = NULL;
        bioctx->bio = bio;
        refcount_set(&bioctx->ref, 1);
-       bioctx->status = BLK_STS_OK;
 
        /* Set the BIO pending in the flush list */
        if (!nr_sectors && bio_op(bio) == REQ_OP_WRITE) {
@@ -624,35 +608,6 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
 }
 
 /*
- * Completed target BIO processing.
- */
-static int dmz_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *error)
-{
-       struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-
-       if (bioctx->status == BLK_STS_OK && *error)
-               bioctx->status = *error;
-
-       if (!refcount_dec_and_test(&bioctx->ref))
-               return DM_ENDIO_INCOMPLETE;
-
-       /* Done */
-       bio->bi_status = bioctx->status;
-
-       if (bioctx->zone) {
-               struct dm_zone *zone = bioctx->zone;
-
-               if (*error && bio_op(bio) == REQ_OP_WRITE) {
-                       if (dmz_is_seq(zone))
-                               set_bit(DMZ_SEQ_WRITE_ERR, &zone->flags);
-               }
-               dmz_deactivate_zone(zone);
-       }
-
-       return DM_ENDIO_DONE;
-}
-
-/*
  * Get zoned device information.
  */
 static int dmz_get_zoned_device(struct dm_target *ti, char *path)
@@ -946,7 +901,6 @@ static struct target_type dmz_type = {
        .ctr             = dmz_ctr,
        .dtr             = dmz_dtr,
        .map             = dmz_map,
-       .end_io          = dmz_end_io,
        .io_hints        = dmz_io_hints,
        .prepare_ioctl   = dmz_prepare_ioctl,
        .postsuspend     = dmz_suspend,
index dddbca6..803c217 100644 (file)
@@ -1606,6 +1606,8 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
                return ret;
        }
 
+       blk_queue_split(md->queue, &bio);
+
        init_clone_info(&ci, md, map, bio);
 
        if (bio->bi_opf & REQ_PREFLUSH) {
index 8add62a..102eb35 100644 (file)
@@ -110,6 +110,19 @@ config MEDIA_CONTROLLER_DVB
 
          This is currently experimental.
 
+config MEDIA_CONTROLLER_REQUEST_API
+       bool "Enable Media controller Request API (EXPERIMENTAL)"
+       depends on MEDIA_CONTROLLER && STAGING_MEDIA
+       default n
+       ---help---
+         DO NOT ENABLE THIS OPTION UNLESS YOU KNOW WHAT YOU'RE DOING.
+
+         This option enables the Request API for the Media controller and V4L2
+         interfaces. It is currently needed by a few stateless codec drivers.
+
+         There is currently no intention to provide API or ABI stability for
+         this new API as of yet.
+
 #
 # Video4Linux support
 #      Only enables if one of the V4L2 types (ATV, webcam, radio) is selected
index 975ff56..8ff8722 100644 (file)
@@ -947,7 +947,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
        }
        atomic_dec(&q->owned_by_drv_count);
 
-       if (vb->req_obj.req) {
+       if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) {
                /* This is not supported at the moment */
                WARN_ON(state == VB2_BUF_STATE_REQUEUEING);
                media_request_object_unbind(&vb->req_obj);
@@ -1359,8 +1359,12 @@ static void vb2_req_release(struct media_request_object *obj)
 {
        struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
 
-       if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+       if (vb->state == VB2_BUF_STATE_IN_REQUEST) {
                vb->state = VB2_BUF_STATE_DEQUEUED;
+               if (vb->request)
+                       media_request_put(vb->request);
+               vb->request = NULL;
+       }
 }
 
 static const struct media_request_object_ops vb2_core_req_ops = {
@@ -1528,6 +1532,18 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
                        return ret;
 
                vb->state = VB2_BUF_STATE_IN_REQUEST;
+
+               /*
+                * Increment the refcount and store the request.
+                * The request refcount is decremented again when the
+                * buffer is dequeued. This is to prevent vb2_buffer_done()
+                * from freeing the request from interrupt context, which can
+                * happen if the application closed the request fd after
+                * queueing the request.
+                */
+               media_request_get(req);
+               vb->request = req;
+
                /* Fill buffer information for the userspace */
                if (pb) {
                        call_void_bufop(q, copy_timestamp, vb, pb);
@@ -1749,10 +1765,6 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
                        call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
                        vb->planes[i].dbuf_mapped = 0;
                }
-       if (vb->req_obj.req) {
-               media_request_object_unbind(&vb->req_obj);
-               media_request_object_put(&vb->req_obj);
-       }
        call_void_bufop(q, init_buffer, vb);
 }
 
@@ -1797,6 +1809,14 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
        /* go back to dequeued state */
        __vb2_dqbuf(vb);
 
+       if (WARN_ON(vb->req_obj.req)) {
+               media_request_object_unbind(&vb->req_obj);
+               media_request_object_put(&vb->req_obj);
+       }
+       if (vb->request)
+               media_request_put(vb->request);
+       vb->request = NULL;
+
        dprintk(2, "dqbuf of buffer %d, with state %d\n",
                        vb->index, vb->state);
 
@@ -1903,6 +1923,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
                        vb->prepared = false;
                }
                __vb2_dqbuf(vb);
+
+               if (vb->req_obj.req) {
+                       media_request_object_unbind(&vb->req_obj);
+                       media_request_object_put(&vb->req_obj);
+               }
+               if (vb->request)
+                       media_request_put(vb->request);
+               vb->request = NULL;
        }
 }
 
@@ -1940,10 +1968,8 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
                if (ret)
                        return ret;
                ret = vb2_start_streaming(q);
-               if (ret) {
-                       __vb2_queue_cancel(q);
+               if (ret)
                        return ret;
-               }
        }
 
        q->streaming = 1;
index a17033a..1d35aea 100644 (file)
@@ -333,10 +333,10 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
 }
 
 static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
-                                   struct v4l2_buffer *b,
-                                   const char *opname,
+                                   struct v4l2_buffer *b, bool is_prepare,
                                    struct media_request **p_req)
 {
+       const char *opname = is_prepare ? "prepare_buf" : "qbuf";
        struct media_request *req;
        struct vb2_v4l2_buffer *vbuf;
        struct vb2_buffer *vb;
@@ -378,6 +378,9 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
                        return ret;
        }
 
+       if (is_prepare)
+               return 0;
+
        if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
                if (q->uses_requests) {
                        dprintk(1, "%s: queue uses requests\n", opname);
@@ -631,8 +634,10 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
                *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR;
        if (q->io_modes & VB2_DMABUF)
                *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF;
+#ifdef CONFIG_MEDIA_CONTROLLER_REQUEST_API
        if (q->supports_requests)
                *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
+#endif
 }
 
 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
@@ -657,7 +662,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
        if (b->flags & V4L2_BUF_FLAG_REQUEST_FD)
                return -EINVAL;
 
-       ret = vb2_queue_or_prepare_buf(q, mdev, b, "prepare_buf", NULL);
+       ret = vb2_queue_or_prepare_buf(q, mdev, b, true, NULL);
 
        return ret ? ret : vb2_core_prepare_buf(q, b->index, b);
 }
@@ -729,7 +734,7 @@ int vb2_qbuf(struct vb2_queue *q, struct media_device *mdev,
                return -EBUSY;
        }
 
-       ret = vb2_queue_or_prepare_buf(q, mdev, b, "qbuf", &req);
+       ret = vb2_queue_or_prepare_buf(q, mdev, b, false, &req);
        if (ret)
                return ret;
        ret = vb2_core_qbuf(q, b->index, b, req);
index bed2437..b8ec886 100644 (file)
@@ -381,10 +381,14 @@ static long media_device_get_topology(struct media_device *mdev, void *arg)
 static long media_device_request_alloc(struct media_device *mdev,
                                       int *alloc_fd)
 {
+#ifdef CONFIG_MEDIA_CONTROLLER_REQUEST_API
        if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
                return -ENOTTY;
 
        return media_request_alloc(mdev, alloc_fd);
+#else
+       return -ENOTTY;
+#endif
 }
 
 static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int cmd)
index 013cdeb..13fb69c 100644 (file)
@@ -997,11 +997,18 @@ static int vicodec_start_streaming(struct vb2_queue *q,
 
        q_data->sequence = 0;
 
-       if (!V4L2_TYPE_IS_OUTPUT(q->type))
+       if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
+               if (!ctx->is_enc) {
+                       state->width = q_data->width;
+                       state->height = q_data->height;
+               }
                return 0;
+       }
 
-       state->width = q_data->width;
-       state->height = q_data->height;
+       if (ctx->is_enc) {
+               state->width = q_data->width;
+               state->height = q_data->height;
+       }
        state->ref_frame.width = state->ref_frame.height = 0;
        state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div,
                                         GFP_KERNEL);
index dcdc80e..9acc709 100644 (file)
@@ -276,8 +276,6 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
                list_for_each_entry_safe(buf, tmp, &dev->sdr_cap_active, list) {
                        list_del(&buf->list);
-                       v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
-                                                  &dev->ctrl_hdl_sdr_cap);
                        vb2_buffer_done(&buf->vb.vb2_buf,
                                        VB2_BUF_STATE_QUEUED);
                }
index 903cebe..d666271 100644 (file)
@@ -204,8 +204,6 @@ static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
                list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) {
                        list_del(&buf->list);
-                       v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
-                                                  &dev->ctrl_hdl_vbi_cap);
                        vb2_buffer_done(&buf->vb.vb2_buf,
                                        VB2_BUF_STATE_QUEUED);
                }
index 9357c07..cd56476 100644 (file)
@@ -96,8 +96,6 @@ static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count)
 
                list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) {
                        list_del(&buf->list);
-                       v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
-                                                  &dev->ctrl_hdl_vbi_out);
                        vb2_buffer_done(&buf->vb.vb2_buf,
                                        VB2_BUF_STATE_QUEUED);
                }
index 9c8e8be..673772c 100644 (file)
@@ -243,8 +243,6 @@ static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
                list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) {
                        list_del(&buf->list);
-                       v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
-                                                  &dev->ctrl_hdl_vid_cap);
                        vb2_buffer_done(&buf->vb.vb2_buf,
                                        VB2_BUF_STATE_QUEUED);
                }
index aaf13f0..628eae1 100644 (file)
@@ -162,8 +162,6 @@ static int vid_out_start_streaming(struct vb2_queue *vq, unsigned count)
 
                list_for_each_entry_safe(buf, tmp, &dev->vid_out_active, list) {
                        list_del(&buf->list);
-                       v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
-                                                  &dev->ctrl_hdl_vid_out);
                        vb2_buffer_done(&buf->vb.vb2_buf,
                                        VB2_BUF_STATE_QUEUED);
                }
index 0b18f0b..8b0a263 100644 (file)
@@ -95,7 +95,7 @@ static void lif_configure_stream(struct vsp1_entity *entity,
        format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
                                            LIF_PAD_SOURCE);
 
-       switch (entity->vsp1->version & VI6_IP_VERSION_SOC_MASK) {
+       switch (entity->vsp1->version & VI6_IP_VERSION_MODEL_MASK) {
        case VI6_IP_VERSION_MODEL_VSPD_GEN2:
        case VI6_IP_VERSION_MODEL_VSPD_V2H:
                hbth = 1536;
index 5f2b033..10b8d94 100644 (file)
@@ -1563,7 +1563,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
        u64 offset;
        s64 val;
 
-       switch (ctrl->type) {
+       switch ((u32)ctrl->type) {
        case V4L2_CTRL_TYPE_INTEGER:
                return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
        case V4L2_CTRL_TYPE_INTEGER64:
@@ -2232,7 +2232,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
        is_array = nr_of_dims > 0;
 
        /* Prefill elem_size for all types handled by std_type_ops */
-       switch (type) {
+       switch ((u32)type) {
        case V4L2_CTRL_TYPE_INTEGER64:
                elem_size = sizeof(s64);
                break;
index 2c329a3..62e7619 100644 (file)
@@ -471,7 +471,7 @@ out:
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
                               struct mmc_blk_ioc_data *idata)
 {
-       struct mmc_command cmd = {};
+       struct mmc_command cmd = {}, sbc = {};
        struct mmc_data data = {};
        struct mmc_request mrq = {};
        struct scatterlist sg;
@@ -549,10 +549,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
        }
 
        if (idata->rpmb) {
-               err = mmc_set_blockcount(card, data.blocks,
-                       idata->ic.write_flag & (1 << 31));
-               if (err)
-                       return err;
+               sbc.opcode = MMC_SET_BLOCK_COUNT;
+               /*
+                * We don't do any blockcount validation because the max size
+                * may be increased by a future standard. We just copy the
+                * 'Reliable Write' bit here.
+                */
+               sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
+               sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
+               mrq.sbc = &sbc;
        }
 
        if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
index adf3268..c60a762 100644 (file)
@@ -104,6 +104,7 @@ struct mmc_omap_slot {
        unsigned int            vdd;
        u16                     saved_con;
        u16                     bus_mode;
+       u16                     power_mode;
        unsigned int            fclk_freq;
 
        struct tasklet_struct   cover_tasklet;
@@ -1157,7 +1158,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        struct mmc_omap_slot *slot = mmc_priv(mmc);
        struct mmc_omap_host *host = slot->host;
        int i, dsor;
-       int clk_enabled;
+       int clk_enabled, init_stream;
 
        mmc_omap_select_slot(slot, 0);
 
@@ -1167,6 +1168,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                slot->vdd = ios->vdd;
 
        clk_enabled = 0;
+       init_stream = 0;
        switch (ios->power_mode) {
        case MMC_POWER_OFF:
                mmc_omap_set_power(slot, 0, ios->vdd);
@@ -1174,13 +1176,17 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_POWER_UP:
                /* Cannot touch dsor yet, just power up MMC */
                mmc_omap_set_power(slot, 1, ios->vdd);
+               slot->power_mode = ios->power_mode;
                goto exit;
        case MMC_POWER_ON:
                mmc_omap_fclk_enable(host, 1);
                clk_enabled = 1;
                dsor |= 1 << 11;
+               if (slot->power_mode != MMC_POWER_ON)
+                       init_stream = 1;
                break;
        }
+       slot->power_mode = ios->power_mode;
 
        if (slot->bus_mode != ios->bus_mode) {
                if (slot->pdata->set_bus_mode != NULL)
@@ -1196,7 +1202,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        for (i = 0; i < 2; i++)
                OMAP_MMC_WRITE(host, CON, dsor);
        slot->saved_con = dsor;
-       if (ios->power_mode == MMC_POWER_ON) {
+       if (init_stream) {
                /* worst case at 400kHz, 80 cycles makes 200 microsecs */
                int usecs = 250;
 
@@ -1234,6 +1240,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
        slot->host = host;
        slot->mmc = mmc;
        slot->id = id;
+       slot->power_mode = MMC_POWER_UNDEFINED;
        slot->pdata = &host->pdata->slots[id];
 
        host->slots[id] = slot;
index 88347ce..d264391 100644 (file)
@@ -288,9 +288,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
        struct device *dev = omap_host->dev;
        struct mmc_ios *ios = &mmc->ios;
        u32 start_window = 0, max_window = 0;
+       bool dcrc_was_enabled = false;
        u8 cur_match, prev_match = 0;
        u32 length = 0, max_len = 0;
-       u32 ier = host->ier;
        u32 phase_delay = 0;
        int ret = 0;
        u32 reg;
@@ -317,9 +317,10 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * during the tuning procedure. So disable it during the
         * tuning procedure.
         */
-       ier &= ~SDHCI_INT_DATA_CRC;
-       sdhci_writel(host, ier, SDHCI_INT_ENABLE);
-       sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+       if (host->ier & SDHCI_INT_DATA_CRC) {
+               host->ier &= ~SDHCI_INT_DATA_CRC;
+               dcrc_was_enabled = true;
+       }
 
        while (phase_delay <= MAX_PHASE_DELAY) {
                sdhci_omap_set_dll(omap_host, phase_delay);
@@ -366,6 +367,9 @@ tuning_error:
 
 ret:
        sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+       /* Reenable forbidden interrupt */
+       if (dcrc_was_enabled)
+               host->ier |= SDHCI_INT_DATA_CRC;
        sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
        sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
        return ret;
index 99bdae5..451b08a 100644 (file)
@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
        timeout = ktime_add_ms(ktime_get(), 100);
 
        /* hw clears the bit when it's done */
-       while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
-               if (ktime_after(ktime_get(), timeout)) {
+       while (1) {
+               bool timedout = ktime_after(ktime_get(), timeout);
+
+               if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
+                       break;
+               if (timedout) {
                        pr_err("%s: Reset 0x%x never completed.\n",
                                mmc_hostname(host->mmc), (int)mask);
                        sdhci_dumpregs(host);
@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
 
        /* Wait max 20 ms */
        timeout = ktime_add_ms(ktime_get(), 20);
-       while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
-               & SDHCI_CLOCK_INT_STABLE)) {
-               if (ktime_after(ktime_get(), timeout)) {
+       while (1) {
+               bool timedout = ktime_after(ktime_get(), timeout);
+
+               clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+               if (clk & SDHCI_CLOCK_INT_STABLE)
+                       break;
+               if (timedout) {
                        pr_err("%s: Internal clock never stabilised.\n",
                               mmc_hostname(host->mmc));
                        sdhci_dumpregs(host);
index 53d4490..ea87d73 100644 (file)
@@ -191,7 +191,8 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
                case PIN_CONFIG_BIAS_DISABLE:
                        dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
 
-                       meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
+                       meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg,
+                                              &bit);
                        ret = regmap_update_bits(pc->reg_pullen, reg,
                                                 BIT(bit), 0);
                        if (ret)
index 6838b38..1bfb0ae 100644 (file)
@@ -33,7 +33,7 @@ enum {
        }
 
 
-#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9)        \
        {                                               \
                .name = "gpio" #id,                     \
                .pins = gpio##id##_pins,                \
@@ -51,11 +51,12 @@ enum {
                        msm_mux_##f9                    \
                },                                      \
                .nfuncs = 10,                           \
-               .ctl_reg = base + REG_SIZE * id,        \
-               .io_reg = base + 0x4 + REG_SIZE * id,           \
-               .intr_cfg_reg = base + 0x8 + REG_SIZE * id,             \
-               .intr_status_reg = base + 0xc + REG_SIZE * id,  \
-               .intr_target_reg = base + 0x8 + REG_SIZE * id,  \
+               .ctl_reg = REG_SIZE * id,               \
+               .io_reg = 0x4 + REG_SIZE * id,          \
+               .intr_cfg_reg = 0x8 + REG_SIZE * id,    \
+               .intr_status_reg = 0xc + REG_SIZE * id, \
+               .intr_target_reg = 0x8 + REG_SIZE * id, \
+               .tile = _tile,                  \
                .mux_bit = 2,                   \
                .pull_bit = 0,                  \
                .drv_bit = 6,                   \
@@ -82,6 +83,7 @@ enum {
                .intr_cfg_reg = 0,                      \
                .intr_status_reg = 0,                   \
                .intr_target_reg = 0,                   \
+               .tile = NORTH,                          \
                .mux_bit = -1,                          \
                .pull_bit = pull,                       \
                .drv_bit = drv,                         \
@@ -1397,13 +1399,13 @@ static const struct msm_pingroup sdm660_groups[] = {
        PINGROUP(111, SOUTH, _, _, _, _, _, _, _, _, _),
        PINGROUP(112, SOUTH, _, _, _, _, _, _, _, _, _),
        PINGROUP(113, SOUTH, _, _, _, _, _, _, _, _, _),
-       SDC_QDSD_PINGROUP(sdc1_clk, 0x99a000, 13, 6),
-       SDC_QDSD_PINGROUP(sdc1_cmd, 0x99a000, 11, 3),
-       SDC_QDSD_PINGROUP(sdc1_data, 0x99a000, 9, 0),
-       SDC_QDSD_PINGROUP(sdc2_clk, 0x99b000, 14, 6),
-       SDC_QDSD_PINGROUP(sdc2_cmd, 0x99b000, 11, 3),
-       SDC_QDSD_PINGROUP(sdc2_data, 0x99b000, 9, 0),
-       SDC_QDSD_PINGROUP(sdc1_rclk, 0x99a000, 15, 0),
+       SDC_QDSD_PINGROUP(sdc1_clk, 0x9a000, 13, 6),
+       SDC_QDSD_PINGROUP(sdc1_cmd, 0x9a000, 11, 3),
+       SDC_QDSD_PINGROUP(sdc1_data, 0x9a000, 9, 0),
+       SDC_QDSD_PINGROUP(sdc2_clk, 0x9b000, 14, 6),
+       SDC_QDSD_PINGROUP(sdc2_cmd, 0x9b000, 11, 3),
+       SDC_QDSD_PINGROUP(sdc2_data, 0x9b000, 9, 0),
+       SDC_QDSD_PINGROUP(sdc1_rclk, 0x9a000, 15, 0),
 };
 
 static const struct msm_pinctrl_soc_data sdm660_pinctrl = {
index 6624499..4ada803 100644 (file)
@@ -568,7 +568,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
        SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),  /* PH_EINT11 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)), /* PH_EINT11 */
 };
 
 static const struct sunxi_pinctrl_desc sun8i_a83t_pinctrl_data = {
index a7a34e8..3252efa 100644 (file)
@@ -3,6 +3,7 @@ config VIDEO_SUNXI_CEDRUS
        depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
        depends on HAS_DMA
        depends on OF
+       depends on MEDIA_CONTROLLER_REQUEST_API
        select SUNXI_SRAM
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
index 32adbcb..07520a2 100644 (file)
@@ -255,10 +255,10 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
 
        res = platform_get_resource(dev->pdev, IORESOURCE_MEM, 0);
        dev->base = devm_ioremap_resource(dev->dev, res);
-       if (!dev->base) {
+       if (IS_ERR(dev->base)) {
                v4l2_err(&dev->v4l2_dev, "Failed to map registers\n");
 
-               ret = -ENOMEM;
+               ret = PTR_ERR(dev->base);
                goto err_sram;
        }
 
index c4111a9..2d26ae8 100644 (file)
@@ -424,7 +424,7 @@ static int hi3660_thermal_probe(struct hisi_thermal_data *data)
        struct platform_device *pdev = data->pdev;
        struct device *dev = &pdev->dev;
 
-       data->nr_sensors = 2;
+       data->nr_sensors = 1;
 
        data->sensor = devm_kzalloc(dev, sizeof(*data->sensor) *
                                    data->nr_sensors, GFP_KERNEL);
@@ -589,7 +589,7 @@ static int hisi_thermal_probe(struct platform_device *pdev)
                        return ret;
                }
 
-               ret = platform_get_irq_byname(pdev, sensor->irq_name);
+               ret = platform_get_irq(pdev, 0);
                if (ret < 0)
                        return ret;
 
index 47623da..bbd73c5 100644 (file)
@@ -241,8 +241,8 @@ static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor)
                sensor->t0 = TS1_T0_VAL1;
 
        /* Retrieve fmt0 and put it on Hz */
-       sensor->fmt0 = ADJUST * readl_relaxed(sensor->base + DTS_T0VALR1_OFFSET)
-                                             & TS1_FMT0_MASK;
+       sensor->fmt0 = ADJUST * (readl_relaxed(sensor->base +
+                                DTS_T0VALR1_OFFSET) & TS1_FMT0_MASK);
 
        /* Retrieve ramp coefficient */
        sensor->ramp_coeff = readl_relaxed(sensor->base + DTS_RAMPVALR_OFFSET) &
@@ -532,6 +532,10 @@ static int stm_thermal_prepare(struct stm_thermal_sensor *sensor)
        if (ret)
                return ret;
 
+       ret = stm_thermal_read_factory_settings(sensor);
+       if (ret)
+               goto thermal_unprepare;
+
        ret = stm_thermal_calibration(sensor);
        if (ret)
                goto thermal_unprepare;
@@ -636,10 +640,6 @@ static int stm_thermal_probe(struct platform_device *pdev)
        /* Populate sensor */
        sensor->base = base;
 
-       ret = stm_thermal_read_factory_settings(sensor);
-       if (ret)
-               return ret;
-
        sensor->clk = devm_clk_get(&pdev->dev, "pclk");
        if (IS_ERR(sensor->clk)) {
                dev_err(&pdev->dev, "%s: failed to fetch PCLK clock\n",
index 678b270..f9ef067 100644 (file)
@@ -562,7 +562,30 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
-       if (!data->levels) {
+       if (data->levels) {
+               /*
+                * For the DT case, only when brightness levels is defined
+                * data->levels is filled. For the non-DT case, data->levels
+                * can come from platform data, however is not usual.
+                */
+               for (i = 0; i <= data->max_brightness; i++) {
+                       if (data->levels[i] > pb->scale)
+                               pb->scale = data->levels[i];
+
+                       pb->levels = data->levels;
+               }
+       } else if (!data->max_brightness) {
+               /*
+                * If no brightness levels are provided and max_brightness is
+                * not set, use the default brightness table. For the DT case,
+                * max_brightness is set to 0 when brightness levels is not
+                * specified. For the non-DT case, max_brightness is usually
+                * set to some value.
+                */
+
+               /* Get the PWM period (in nanoseconds) */
+               pwm_get_state(pb->pwm, &state);
+
                ret = pwm_backlight_brightness_default(&pdev->dev, data,
                                                       state.period);
                if (ret < 0) {
@@ -570,13 +593,19 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                                "failed to setup default brightness table\n");
                        goto err_alloc;
                }
-       }
 
-       for (i = 0; i <= data->max_brightness; i++) {
-               if (data->levels[i] > pb->scale)
-                       pb->scale = data->levels[i];
+               for (i = 0; i <= data->max_brightness; i++) {
+                       if (data->levels[i] > pb->scale)
+                               pb->scale = data->levels[i];
 
-               pb->levels = data->levels;
+                       pb->levels = data->levels;
+               }
+       } else {
+               /*
+                * That only happens for the non-DT case, where platform data
+                * sets the max_brightness value.
+                */
+               pb->scale = data->max_brightness;
        }
 
        pb->lth_brightness = data->lth_brightness * (state.period / pb->scale);
index 05647d3..09eeb6c 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -45,6 +45,7 @@
 
 #include <asm/kmap_types.h>
 #include <linux/uaccess.h>
+#include <linux/nospec.h>
 
 #include "internal.h"
 
@@ -1038,6 +1039,7 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
        if (!table || id >= table->nr)
                goto out;
 
+       id = array_index_nospec(id, table->nr);
        ctx = rcu_dereference(table->table[id]);
        if (ctx && ctx->user_id == ctx_id) {
                if (percpu_ref_tryget_live(&ctx->users))
index b5ecd6f..4e9a7cc 100644 (file)
@@ -563,8 +563,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_puts(m, ",noacl");
 #endif
 
-       if (fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM)
-               seq_puts(m, ",nocopyfrom");
+       if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0)
+               seq_puts(m, ",copyfrom");
 
        if (fsopt->mds_namespace)
                seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
index c005a54..79a265b 100644 (file)
@@ -42,7 +42,9 @@
 #define CEPH_MOUNT_OPT_NOQUOTADF       (1<<13) /* no root dir quota in statfs */
 #define CEPH_MOUNT_OPT_NOCOPYFROM      (1<<14) /* don't use RADOS 'copy-from' op */
 
-#define CEPH_MOUNT_OPT_DEFAULT    CEPH_MOUNT_OPT_DCACHE
+#define CEPH_MOUNT_OPT_DEFAULT                 \
+       (CEPH_MOUNT_OPT_DCACHE |                \
+        CEPH_MOUNT_OPT_NOCOPYFROM)
 
 #define ceph_set_mount_opt(fsc, opt) \
        (fsc)->mount_options->flags |= CEPH_MOUNT_OPT_##opt;
index 47395b0..e909678 100644 (file)
@@ -1119,8 +1119,10 @@ static int fuse_permission(struct inode *inode, int mask)
        if (fc->default_permissions ||
            ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
                struct fuse_inode *fi = get_fuse_inode(inode);
+               u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
 
-               if (time_before64(fi->i_time, get_jiffies_64())) {
+               if (perm_mask & READ_ONCE(fi->inval_mask) ||
+                   time_before64(fi->i_time, get_jiffies_64())) {
                        refreshed = true;
 
                        err = fuse_perm_getattr(inode, mask);
@@ -1241,7 +1243,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
 
 static int fuse_dir_release(struct inode *inode, struct file *file)
 {
-       fuse_release_common(file, FUSE_RELEASEDIR);
+       fuse_release_common(file, true);
 
        return 0;
 }
@@ -1249,7 +1251,25 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
 static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
                          int datasync)
 {
-       return fuse_fsync_common(file, start, end, datasync, 1);
+       struct inode *inode = file->f_mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       int err;
+
+       if (is_bad_inode(inode))
+               return -EIO;
+
+       if (fc->no_fsyncdir)
+               return 0;
+
+       inode_lock(inode);
+       err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
+       if (err == -ENOSYS) {
+               fc->no_fsyncdir = 1;
+               err = 0;
+       }
+       inode_unlock(inode);
+
+       return err;
 }
 
 static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
index b52f9ba..ffaffe1 100644 (file)
@@ -89,12 +89,12 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
        iput(req->misc.release.inode);
 }
 
-static void fuse_file_put(struct fuse_file *ff, bool sync)
+static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
 {
        if (refcount_dec_and_test(&ff->count)) {
                struct fuse_req *req = ff->reserved_req;
 
-               if (ff->fc->no_open) {
+               if (ff->fc->no_open && !isdir) {
                        /*
                         * Drop the release request when client does not
                         * implement 'open'
@@ -247,10 +247,11 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
        req->in.args[0].value = inarg;
 }
 
-void fuse_release_common(struct file *file, int opcode)
+void fuse_release_common(struct file *file, bool isdir)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req = ff->reserved_req;
+       int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
 
        fuse_prepare_release(ff, file->f_flags, opcode);
 
@@ -272,7 +273,7 @@ void fuse_release_common(struct file *file, int opcode)
         * synchronous RELEASE is allowed (and desirable) in this case
         * because the server can be trusted not to screw up.
         */
-       fuse_file_put(ff, ff->fc->destroy_req != NULL);
+       fuse_file_put(ff, ff->fc->destroy_req != NULL, isdir);
 }
 
 static int fuse_open(struct inode *inode, struct file *file)
@@ -288,7 +289,7 @@ static int fuse_release(struct inode *inode, struct file *file)
        if (fc->writeback_cache)
                write_inode_now(inode, 1);
 
-       fuse_release_common(file, FUSE_RELEASE);
+       fuse_release_common(file, false);
 
        /* return value is ignored by VFS */
        return 0;
@@ -302,7 +303,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
         * iput(NULL) is a no-op and since the refcount is 1 and everything's
         * synchronous, we are fine with not doing igrab() here"
         */
-       fuse_file_put(ff, true);
+       fuse_file_put(ff, true, false);
 }
 EXPORT_SYMBOL_GPL(fuse_sync_release);
 
@@ -441,13 +442,30 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 }
 
 int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
-                     int datasync, int isdir)
+                     int datasync, int opcode)
 {
        struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        FUSE_ARGS(args);
        struct fuse_fsync_in inarg;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.fh = ff->fh;
+       inarg.fsync_flags = datasync ? 1 : 0;
+       args.in.h.opcode = opcode;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       return fuse_simple_request(fc, &args);
+}
+
+static int fuse_fsync(struct file *file, loff_t start, loff_t end,
+                     int datasync)
+{
+       struct inode *inode = file->f_mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
        if (is_bad_inode(inode))
@@ -479,34 +497,18 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
        if (err)
                goto out;
 
-       if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
+       if (fc->no_fsync)
                goto out;
 
-       memset(&inarg, 0, sizeof(inarg));
-       inarg.fh = ff->fh;
-       inarg.fsync_flags = datasync ? 1 : 0;
-       args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
-       args.in.h.nodeid = get_node_id(inode);
-       args.in.numargs = 1;
-       args.in.args[0].size = sizeof(inarg);
-       args.in.args[0].value = &inarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNC);
        if (err == -ENOSYS) {
-               if (isdir)
-                       fc->no_fsyncdir = 1;
-               else
-                       fc->no_fsync = 1;
+               fc->no_fsync = 1;
                err = 0;
        }
 out:
        inode_unlock(inode);
-       return err;
-}
 
-static int fuse_fsync(struct file *file, loff_t start, loff_t end,
-                     int datasync)
-{
-       return fuse_fsync_common(file, start, end, datasync, 0);
+       return err;
 }
 
 void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
@@ -807,7 +809,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
                put_page(page);
        }
        if (req->ff)
-               fuse_file_put(req->ff, false);
+               fuse_file_put(req->ff, false, false);
 }
 
 static void fuse_send_readpages(struct fuse_req *req, struct file *file)
@@ -1460,7 +1462,7 @@ static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
                __free_page(req->pages[i]);
 
        if (req->ff)
-               fuse_file_put(req->ff, false);
+               fuse_file_put(req->ff, false, false);
 }
 
 static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
@@ -1619,7 +1621,7 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
        ff = __fuse_write_file_get(fc, fi);
        err = fuse_flush_times(inode, ff);
        if (ff)
-               fuse_file_put(ff, 0);
+               fuse_file_put(ff, false, false);
 
        return err;
 }
@@ -1940,7 +1942,7 @@ static int fuse_writepages(struct address_space *mapping,
                err = 0;
        }
        if (data.ff)
-               fuse_file_put(data.ff, false);
+               fuse_file_put(data.ff, false, false);
 
        kfree(data.orig_pages);
 out:
index e9f712e..2f2c92e 100644 (file)
@@ -822,13 +822,13 @@ void fuse_sync_release(struct fuse_file *ff, int flags);
 /**
  * Send RELEASE or RELEASEDIR request
  */
-void fuse_release_common(struct file *file, int opcode);
+void fuse_release_common(struct file *file, bool isdir);
 
 /**
  * Send FSYNC or FSYNCDIR request
  */
 int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
-                     int datasync, int isdir);
+                     int datasync, int opcode);
 
 /**
  * Notify poll wakeup
index 0b94b23..568abed 100644 (file)
@@ -115,7 +115,7 @@ static void fuse_i_callback(struct rcu_head *head)
 static void fuse_destroy_inode(struct inode *inode)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
-       if (S_ISREG(inode->i_mode)) {
+       if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) {
                WARN_ON(!list_empty(&fi->write_files));
                WARN_ON(!list_empty(&fi->queued_writes));
        }
@@ -1068,6 +1068,7 @@ void fuse_dev_free(struct fuse_dev *fud)
 
                fuse_conn_put(fc);
        }
+       kfree(fud->pq.processing);
        kfree(fud);
 }
 EXPORT_SYMBOL_GPL(fuse_dev_free);
index 9a5bf1e..99f545e 100644 (file)
@@ -116,6 +116,12 @@ iomap_page_create(struct inode *inode, struct page *page)
        atomic_set(&iop->read_count, 0);
        atomic_set(&iop->write_count, 0);
        bitmap_zero(iop->uptodate, PAGE_SIZE / SECTOR_SIZE);
+
+       /*
+        * migrate_page_move_mapping() assumes that pages with private data have
+        * their count elevated by 1.
+        */
+       get_page(page);
        set_page_private(page, (unsigned long)iop);
        SetPagePrivate(page);
        return iop;
@@ -132,6 +138,7 @@ iomap_page_release(struct page *page)
        WARN_ON_ONCE(atomic_read(&iop->write_count));
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       put_page(page);
        kfree(iop);
 }
 
index c628914..82c129b 100644 (file)
@@ -651,6 +651,18 @@ static int ovl_symlink(struct inode *dir, struct dentry *dentry,
        return ovl_create_object(dentry, S_IFLNK, 0, link);
 }
 
+static int ovl_set_link_redirect(struct dentry *dentry)
+{
+       const struct cred *old_cred;
+       int err;
+
+       old_cred = ovl_override_creds(dentry->d_sb);
+       err = ovl_set_redirect(dentry, false);
+       revert_creds(old_cred);
+
+       return err;
+}
+
 static int ovl_link(struct dentry *old, struct inode *newdir,
                    struct dentry *new)
 {
@@ -670,7 +682,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
                goto out_drop_write;
 
        if (ovl_is_metacopy_dentry(old)) {
-               err = ovl_set_redirect(old, false);
+               err = ovl_set_link_redirect(old);
                if (err)
                        goto out_drop_write;
        }
index 8fa37cd..54e5d17 100644 (file)
@@ -754,9 +754,8 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
                goto out;
        }
 
-       /* Otherwise, get a connected non-upper dir or disconnected non-dir */
-       if (d_is_dir(origin.dentry) &&
-           (origin.dentry->d_flags & DCACHE_DISCONNECTED)) {
+       /* Find origin.dentry again with ovl_acceptable() layer check */
+       if (d_is_dir(origin.dentry)) {
                dput(origin.dentry);
                origin.dentry = NULL;
                err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack);
@@ -769,6 +768,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
                        goto out_err;
        }
 
+       /* Get a connected non-upper dir or disconnected non-dir */
        dentry = ovl_get_dentry(sb, NULL, &origin, index);
 
 out:
index 6bcc9de..3b7ed5d 100644 (file)
@@ -286,22 +286,13 @@ int ovl_permission(struct inode *inode, int mask)
        if (err)
                return err;
 
-       /* No need to do any access on underlying for special files */
-       if (special_file(realinode->i_mode))
-               return 0;
-
-       /* No need to access underlying for execute */
-       mask &= ~MAY_EXEC;
-       if ((mask & (MAY_READ | MAY_WRITE)) == 0)
-               return 0;
-
-       /* Lower files get copied up, so turn write access into read */
-       if (!upperinode && mask & MAY_WRITE) {
+       old_cred = ovl_override_creds(inode->i_sb);
+       if (!upperinode &&
+           !special_file(realinode->i_mode) && mask & MAY_WRITE) {
                mask &= ~(MAY_WRITE | MAY_APPEND);
+               /* Make sure mounter can read file for copy up later */
                mask |= MAY_READ;
        }
-
-       old_cred = ovl_override_creds(inode->i_sb);
        err = inode_permission(realinode, mask);
        revert_creds(old_cred);
 
index cd58939..7a85e60 100644 (file)
@@ -1566,7 +1566,6 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                cond_resched();
 
                BUG_ON(!vma_can_userfault(vma));
-               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
 
                /*
                 * Nothing to do: this vma is already registered into this
@@ -1575,6 +1574,8 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                if (!vma->vm_userfaultfd_ctx.ctx)
                        goto skip;
 
+               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
+
                if (vma->vm_start > start)
                        start = vma->vm_start;
                vma_end = min(end, vma->vm_end);
index 827e4d3..8cc7b09 100644 (file)
@@ -16,6 +16,7 @@
 #define __ASM_GENERIC_FIXMAP_H
 
 #include <linux/bug.h>
+#include <linux/mm_types.h>
 
 #define __fix_to_virt(x)       (FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)       ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
index 5ed8f62..2c471a2 100644 (file)
@@ -206,6 +206,11 @@ struct page {
 #endif
 } _struct_page_alignment;
 
+/*
+ * Used for sizing the vmemmap region on some architectures
+ */
+#define STRUCT_PAGE_MAX_SHIFT  (order_base_2(sizeof(struct page)))
+
 #define PAGE_FRAG_CACHE_MAX_SIZE       __ALIGN_MASK(32768, ~PAGE_MASK)
 #define PAGE_FRAG_CACHE_MAX_ORDER      get_order(PAGE_FRAG_CACHE_MAX_SIZE)
 
index 847705a..db023a9 100644 (file)
@@ -783,6 +783,12 @@ void memory_present(int nid, unsigned long start, unsigned long end);
 static inline void memory_present(int nid, unsigned long start, unsigned long end) {}
 #endif
 
+#if defined(CONFIG_SPARSEMEM)
+void memblocks_present(void);
+#else
+static inline void memblocks_present(void) {}
+#endif
+
 #ifdef CONFIG_HAVE_MEMORYLESS_NODES
 int local_memory_node(int node_id);
 #else
index 564892e..f492e21 100644 (file)
@@ -554,6 +554,60 @@ static inline void *xa_cmpxchg(struct xarray *xa, unsigned long index,
 }
 
 /**
+ * xa_cmpxchg_bh() - Conditionally replace an entry in the XArray.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @old: Old value to test against.
+ * @entry: New value to place in array.
+ * @gfp: Memory allocation flags.
+ *
+ * This function is like calling xa_cmpxchg() except it disables softirqs
+ * while holding the array lock.
+ *
+ * Context: Any context.  Takes and releases the xa_lock while
+ * disabling softirqs.  May sleep if the @gfp flags permit.
+ * Return: The old value at this index or xa_err() if an error happened.
+ */
+static inline void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index,
+                       void *old, void *entry, gfp_t gfp)
+{
+       void *curr;
+
+       xa_lock_bh(xa);
+       curr = __xa_cmpxchg(xa, index, old, entry, gfp);
+       xa_unlock_bh(xa);
+
+       return curr;
+}
+
+/**
+ * xa_cmpxchg_irq() - Conditionally replace an entry in the XArray.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @old: Old value to test against.
+ * @entry: New value to place in array.
+ * @gfp: Memory allocation flags.
+ *
+ * This function is like calling xa_cmpxchg() except it disables interrupts
+ * while holding the array lock.
+ *
+ * Context: Process context.  Takes and releases the xa_lock while
+ * disabling interrupts.  May sleep if the @gfp flags permit.
+ * Return: The old value at this index or xa_err() if an error happened.
+ */
+static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
+                       void *old, void *entry, gfp_t gfp)
+{
+       void *curr;
+
+       xa_lock_irq(xa);
+       curr = __xa_cmpxchg(xa, index, old, entry, gfp);
+       xa_unlock_irq(xa);
+
+       return curr;
+}
+
+/**
  * xa_insert() - Store this entry in the XArray unless another entry is
  *                     already present.
  * @xa: XArray.
diff --git a/include/media/mpeg2-ctrls.h b/include/media/mpeg2-ctrls.h
new file mode 100644 (file)
index 0000000..d21f40e
--- /dev/null
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the MPEG2 state controls for use with stateless MPEG-2
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _MPEG2_CTRLS_H_
+#define _MPEG2_CTRLS_H_
+
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS         (V4L2_CID_MPEG_BASE+250)
+#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION         (V4L2_CID_MPEG_BASE+251)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS 0x0103
+#define        V4L2_CTRL_TYPE_MPEG2_QUANTIZATION 0x0104
+
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_I       1
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_P       2
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_B       3
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_D       4
+
+struct v4l2_mpeg2_sequence {
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+       __u16   horizontal_size;
+       __u16   vertical_size;
+       __u32   vbv_buffer_size;
+
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+       __u8    profile_and_level_indication;
+       __u8    progressive_sequence;
+       __u8    chroma_format;
+       __u8    pad;
+};
+
+struct v4l2_mpeg2_picture {
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+       __u8    picture_coding_type;
+
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+       __u8    f_code[2][2];
+       __u8    intra_dc_precision;
+       __u8    picture_structure;
+       __u8    top_field_first;
+       __u8    frame_pred_frame_dct;
+       __u8    concealment_motion_vectors;
+       __u8    q_scale_type;
+       __u8    intra_vlc_format;
+       __u8    alternate_scan;
+       __u8    repeat_first_field;
+       __u8    progressive_frame;
+       __u8    pad;
+};
+
+struct v4l2_ctrl_mpeg2_slice_params {
+       __u32   bit_size;
+       __u32   data_bit_offset;
+
+       struct v4l2_mpeg2_sequence sequence;
+       struct v4l2_mpeg2_picture picture;
+
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+       __u8    quantiser_scale_code;
+
+       __u8    backward_ref_index;
+       __u8    forward_ref_index;
+       __u8    pad;
+};
+
+struct v4l2_ctrl_mpeg2_quantization {
+       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+       __u8    load_intra_quantiser_matrix;
+       __u8    load_non_intra_quantiser_matrix;
+       __u8    load_chroma_intra_quantiser_matrix;
+       __u8    load_chroma_non_intra_quantiser_matrix;
+
+       __u8    intra_quantiser_matrix[64];
+       __u8    non_intra_quantiser_matrix[64];
+       __u8    chroma_intra_quantiser_matrix[64];
+       __u8    chroma_non_intra_quantiser_matrix[64];
+};
+
+#endif
index 83ce059..d63cf22 100644 (file)
 #include <linux/videodev2.h>
 #include <media/media-request.h>
 
+/*
+ * Include the mpeg2 stateless codec compound control definitions.
+ * This will move to the public headers once this API is fully stable.
+ */
+#include <media/mpeg2-ctrls.h>
+
 /* forward references */
 struct file;
 struct v4l2_ctrl_handler;
index e86981d..4a737b2 100644 (file)
@@ -239,6 +239,7 @@ struct vb2_queue;
  * @num_planes:                number of planes in the buffer
  *                     on an internal driver queue.
  * @timestamp:         frame timestamp in ns.
+ * @request:           the request this buffer is associated with.
  * @req_obj:           used to bind this buffer to a request. This
  *                     request object has a refcount.
  */
@@ -249,6 +250,7 @@ struct vb2_buffer {
        unsigned int            memory;
        unsigned int            num_planes;
        u64                     timestamp;
+       struct media_request    *request;
        struct media_request_object     req_obj;
 
        /* private: internal use only
index 3eb5a4c..ae366b8 100644 (file)
 
 #define ABS_MISC               0x28
 
+/*
+ * 0x2e is reserved and should not be used in input drivers.
+ * It was used by HID as ABS_MISC+6 and userspace needs to detect if
+ * the next ABS_* event is correct or is just ABS_MISC + n.
+ * We define here ABS_RESERVED so userspace can rely on it and detect
+ * the situation described above.
+ */
+#define ABS_RESERVED           0x2e
+
 #define ABS_MT_SLOT            0x2f    /* MT slot being modified */
 #define ABS_MT_TOUCH_MAJOR     0x30    /* Major axis of touching ellipse */
 #define ABS_MT_TOUCH_MINOR     0x31    /* Minor axis (omit if circular) */
index 998983a..3dcfc61 100644 (file)
@@ -404,9 +404,6 @@ enum v4l2_mpeg_video_multi_slice_mode {
 #define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE          (V4L2_CID_MPEG_BASE+228)
 #define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME            (V4L2_CID_MPEG_BASE+229)
 
-#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS         (V4L2_CID_MPEG_BASE+250)
-#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION         (V4L2_CID_MPEG_BASE+251)
-
 #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
 #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
 #define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP            (V4L2_CID_MPEG_BASE+302)
@@ -1097,69 +1094,4 @@ enum v4l2_detect_md_mode {
 #define V4L2_CID_DETECT_MD_THRESHOLD_GRID      (V4L2_CID_DETECT_CLASS_BASE + 3)
 #define V4L2_CID_DETECT_MD_REGION_GRID         (V4L2_CID_DETECT_CLASS_BASE + 4)
 
-#define V4L2_MPEG2_PICTURE_CODING_TYPE_I       1
-#define V4L2_MPEG2_PICTURE_CODING_TYPE_P       2
-#define V4L2_MPEG2_PICTURE_CODING_TYPE_B       3
-#define V4L2_MPEG2_PICTURE_CODING_TYPE_D       4
-
-struct v4l2_mpeg2_sequence {
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
-       __u16   horizontal_size;
-       __u16   vertical_size;
-       __u32   vbv_buffer_size;
-
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
-       __u8    profile_and_level_indication;
-       __u8    progressive_sequence;
-       __u8    chroma_format;
-       __u8    pad;
-};
-
-struct v4l2_mpeg2_picture {
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
-       __u8    picture_coding_type;
-
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
-       __u8    f_code[2][2];
-       __u8    intra_dc_precision;
-       __u8    picture_structure;
-       __u8    top_field_first;
-       __u8    frame_pred_frame_dct;
-       __u8    concealment_motion_vectors;
-       __u8    q_scale_type;
-       __u8    intra_vlc_format;
-       __u8    alternate_scan;
-       __u8    repeat_first_field;
-       __u8    progressive_frame;
-       __u8    pad;
-};
-
-struct v4l2_ctrl_mpeg2_slice_params {
-       __u32   bit_size;
-       __u32   data_bit_offset;
-
-       struct v4l2_mpeg2_sequence sequence;
-       struct v4l2_mpeg2_picture picture;
-
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
-       __u8    quantiser_scale_code;
-
-       __u8    backward_ref_index;
-       __u8    forward_ref_index;
-       __u8    pad;
-};
-
-struct v4l2_ctrl_mpeg2_quantization {
-       /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
-       __u8    load_intra_quantiser_matrix;
-       __u8    load_non_intra_quantiser_matrix;
-       __u8    load_chroma_intra_quantiser_matrix;
-       __u8    load_chroma_non_intra_quantiser_matrix;
-
-       __u8    intra_quantiser_matrix[64];
-       __u8    non_intra_quantiser_matrix[64];
-       __u8    chroma_intra_quantiser_matrix[64];
-       __u8    chroma_non_intra_quantiser_matrix[64];
-};
-
 #endif
index c8e8ff8..2ba2ad0 100644 (file)
@@ -1622,8 +1622,6 @@ struct v4l2_ext_control {
                __u8 __user *p_u8;
                __u16 __user *p_u16;
                __u32 __user *p_u32;
-               struct v4l2_ctrl_mpeg2_slice_params __user *p_mpeg2_slice_params;
-               struct v4l2_ctrl_mpeg2_quantization __user *p_mpeg2_quantization;
                void __user *ptr;
        };
 } __attribute__ ((packed));
@@ -1669,8 +1667,6 @@ enum v4l2_ctrl_type {
        V4L2_CTRL_TYPE_U8            = 0x0100,
        V4L2_CTRL_TYPE_U16           = 0x0101,
        V4L2_CTRL_TYPE_U32           = 0x0102,
-       V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS = 0x0103,
-       V4L2_CTRL_TYPE_MPEG2_QUANTIZATION = 0x0104,
 };
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
index cf5b5a0..ed93525 100644 (file)
@@ -515,8 +515,8 @@ config PSI_DEFAULT_DISABLED
        depends on PSI
        help
          If set, pressure stall information tracking will be disabled
-         per default but can be enabled through passing psi_enable=1
-         on the kernel commandline during boot.
+         per default but can be enabled through passing psi=1 on the
+         kernel commandline during boot.
 
 endmenu # "CPU/Task time and stats accounting"
 
index 7773445..e23eb9f 100644 (file)
@@ -5460,6 +5460,7 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops)
        if (ops->flags & FTRACE_OPS_FL_ENABLED)
                ftrace_shutdown(ops, 0);
        ops->flags |= FTRACE_OPS_FL_DELETED;
+       ftrace_free_filter(ops);
        mutex_unlock(&ftrace_lock);
 }
 
index 84a6517..5574e86 100644 (file)
@@ -570,11 +570,13 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
                }
        }
 
+       kfree(op_stack);
+       kfree(inverts);
        return prog;
 out_free:
        kfree(op_stack);
-       kfree(prog_stack);
        kfree(inverts);
+       kfree(prog_stack);
        return ERR_PTR(ret);
 }
 
@@ -1718,6 +1720,7 @@ static int create_filter(struct trace_event_call *call,
        err = process_preds(call, filter_string, *filterp, pe);
        if (err && set_str)
                append_filter_err(pe, *filterp);
+       create_filter_finish(pe);
 
        return err;
 }
index 2152d1e..cd12ecb 100644 (file)
@@ -732,8 +732,10 @@ int set_trigger_filter(char *filter_str,
 
        /* The filter is for the 'trigger' event, not the triggered event */
        ret = create_event_filter(file->event_call, filter_str, false, &filter);
-       if (ret)
-               goto out;
+       /*
+        * If create_event_filter() fails, filter still needs to be freed.
+        * Which the calling code will do with data->filter.
+        */
  assign:
        tmp = rcu_access_pointer(data->filter);
 
index 1106bb6..14d5154 100644 (file)
@@ -784,11 +784,11 @@ void *__radix_tree_lookup(const struct radix_tree_root *root,
        while (radix_tree_is_internal_node(node)) {
                unsigned offset;
 
-               if (node == RADIX_TREE_RETRY)
-                       goto restart;
                parent = entry_to_node(node);
                offset = radix_tree_descend(parent, &node, index);
                slot = parent->slots + offset;
+               if (node == RADIX_TREE_RETRY)
+                       goto restart;
                if (parent->shift == 0)
                        break;
        }
index 0598e86..4676c0a 100644 (file)
@@ -28,23 +28,28 @@ void xa_dump(const struct xarray *xa) { }
 } while (0)
 #endif
 
+static void *xa_mk_index(unsigned long index)
+{
+       return xa_mk_value(index & LONG_MAX);
+}
+
 static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp)
 {
-       return xa_store(xa, index, xa_mk_value(index & LONG_MAX), gfp);
+       return xa_store(xa, index, xa_mk_index(index), gfp);
 }
 
 static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp)
 {
        u32 id = 0;
 
-       XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_value(index & LONG_MAX),
+       XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_index(index),
                                gfp) != 0);
        XA_BUG_ON(xa, id != index);
 }
 
 static void xa_erase_index(struct xarray *xa, unsigned long index)
 {
-       XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_value(index & LONG_MAX));
+       XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_index(index));
        XA_BUG_ON(xa, xa_load(xa, index) != NULL);
 }
 
@@ -118,7 +123,7 @@ static noinline void check_xas_retry(struct xarray *xa)
 
        xas_set(&xas, 0);
        xas_for_each(&xas, entry, ULONG_MAX) {
-               xas_store(&xas, xa_mk_value(xas.xa_index));
+               xas_store(&xas, xa_mk_index(xas.xa_index));
        }
        xas_unlock(&xas);
 
@@ -196,7 +201,7 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
                xa_set_mark(xa, index + 2, XA_MARK_1);
                XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
-               xa_store_order(xa, index, order, xa_mk_value(index),
+               xa_store_order(xa, index, order, xa_mk_index(index),
                                GFP_KERNEL);
                for (i = base; i < next; i++) {
                        XA_STATE(xas, xa, i);
@@ -405,7 +410,7 @@ static noinline void check_xas_erase(struct xarray *xa)
                        xas_set(&xas, j);
                        do {
                                xas_lock(&xas);
-                               xas_store(&xas, xa_mk_value(j));
+                               xas_store(&xas, xa_mk_index(j));
                                xas_unlock(&xas);
                        } while (xas_nomem(&xas, GFP_KERNEL));
                }
@@ -423,7 +428,7 @@ static noinline void check_xas_erase(struct xarray *xa)
                xas_set(&xas, 0);
                j = i;
                xas_for_each(&xas, entry, ULONG_MAX) {
-                       XA_BUG_ON(xa, entry != xa_mk_value(j));
+                       XA_BUG_ON(xa, entry != xa_mk_index(j));
                        xas_store(&xas, NULL);
                        j++;
                }
@@ -440,17 +445,17 @@ static noinline void check_multi_store_1(struct xarray *xa, unsigned long index,
        unsigned long min = index & ~((1UL << order) - 1);
        unsigned long max = min + (1UL << order);
 
-       xa_store_order(xa, index, order, xa_mk_value(index), GFP_KERNEL);
-       XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_value(index));
-       XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_value(index));
+       xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL);
+       XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_index(index));
+       XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_index(index));
        XA_BUG_ON(xa, xa_load(xa, max) != NULL);
        XA_BUG_ON(xa, xa_load(xa, min - 1) != NULL);
 
        xas_lock(&xas);
-       XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(min)) != xa_mk_value(index));
+       XA_BUG_ON(xa, xas_store(&xas, xa_mk_index(min)) != xa_mk_index(index));
        xas_unlock(&xas);
-       XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_value(min));
-       XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_value(min));
+       XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_index(min));
+       XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_index(min));
        XA_BUG_ON(xa, xa_load(xa, max) != NULL);
        XA_BUG_ON(xa, xa_load(xa, min - 1) != NULL);
 
@@ -471,6 +476,32 @@ static noinline void check_multi_store_2(struct xarray *xa, unsigned long index,
        xas_unlock(&xas);
        XA_BUG_ON(xa, !xa_empty(xa));
 }
+
+static noinline void check_multi_store_3(struct xarray *xa, unsigned long index,
+               unsigned int order)
+{
+       XA_STATE(xas, xa, 0);
+       void *entry;
+       int n = 0;
+
+       xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL);
+
+       xas_lock(&xas);
+       xas_for_each(&xas, entry, ULONG_MAX) {
+               XA_BUG_ON(xa, entry != xa_mk_index(index));
+               n++;
+       }
+       XA_BUG_ON(xa, n != 1);
+       xas_set(&xas, index + 1);
+       xas_for_each(&xas, entry, ULONG_MAX) {
+               XA_BUG_ON(xa, entry != xa_mk_index(index));
+               n++;
+       }
+       XA_BUG_ON(xa, n != 2);
+       xas_unlock(&xas);
+
+       xa_destroy(xa);
+}
 #endif
 
 static noinline void check_multi_store(struct xarray *xa)
@@ -523,15 +554,15 @@ static noinline void check_multi_store(struct xarray *xa)
 
        for (i = 0; i < max_order; i++) {
                for (j = 0; j < max_order; j++) {
-                       xa_store_order(xa, 0, i, xa_mk_value(i), GFP_KERNEL);
-                       xa_store_order(xa, 0, j, xa_mk_value(j), GFP_KERNEL);
+                       xa_store_order(xa, 0, i, xa_mk_index(i), GFP_KERNEL);
+                       xa_store_order(xa, 0, j, xa_mk_index(j), GFP_KERNEL);
 
                        for (k = 0; k < max_order; k++) {
                                void *entry = xa_load(xa, (1UL << k) - 1);
                                if ((i < k) && (j < k))
                                        XA_BUG_ON(xa, entry != NULL);
                                else
-                                       XA_BUG_ON(xa, entry != xa_mk_value(j));
+                                       XA_BUG_ON(xa, entry != xa_mk_index(j));
                        }
 
                        xa_erase(xa, 0);
@@ -545,6 +576,11 @@ static noinline void check_multi_store(struct xarray *xa)
                check_multi_store_1(xa, (1UL << i) + 1, i);
        }
        check_multi_store_2(xa, 4095, 9);
+
+       for (i = 1; i < 20; i++) {
+               check_multi_store_3(xa, 0, i);
+               check_multi_store_3(xa, 1UL << i, i);
+       }
 #endif
 }
 
@@ -587,16 +623,25 @@ static noinline void check_xa_alloc(void)
        xa_destroy(&xa0);
 
        id = 0xfffffffeU;
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
+       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
                                GFP_KERNEL) != 0);
        XA_BUG_ON(&xa0, id != 0xfffffffeU);
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
+       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
                                GFP_KERNEL) != 0);
        XA_BUG_ON(&xa0, id != 0xffffffffU);
-       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
+       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id),
                                GFP_KERNEL) != -ENOSPC);
        XA_BUG_ON(&xa0, id != 0xffffffffU);
        xa_destroy(&xa0);
+
+       id = 10;
+       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
+                               GFP_KERNEL) != -ENOSPC);
+       XA_BUG_ON(&xa0, xa_store_index(&xa0, 3, GFP_KERNEL) != 0);
+       XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
+                               GFP_KERNEL) != -ENOSPC);
+       xa_erase_index(&xa0, 3);
+       XA_BUG_ON(&xa0, !xa_empty(&xa0));
 }
 
 static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
@@ -610,11 +655,11 @@ retry:
        xas_lock(&xas);
        xas_for_each_conflict(&xas, entry) {
                XA_BUG_ON(xa, !xa_is_value(entry));
-               XA_BUG_ON(xa, entry < xa_mk_value(start));
-               XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1));
+               XA_BUG_ON(xa, entry < xa_mk_index(start));
+               XA_BUG_ON(xa, entry > xa_mk_index(start + (1UL << order) - 1));
                count++;
        }
-       xas_store(&xas, xa_mk_value(start));
+       xas_store(&xas, xa_mk_index(start));
        xas_unlock(&xas);
        if (xas_nomem(&xas, GFP_KERNEL)) {
                count = 0;
@@ -622,9 +667,9 @@ retry:
        }
        XA_BUG_ON(xa, xas_error(&xas));
        XA_BUG_ON(xa, count != present);
-       XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start));
+       XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_index(start));
        XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) !=
-                       xa_mk_value(start));
+                       xa_mk_index(start));
        xa_erase_index(xa, start);
 }
 
@@ -703,7 +748,7 @@ static noinline void check_multi_find_2(struct xarray *xa)
                for (j = 0; j < index; j++) {
                        XA_STATE(xas, xa, j + index);
                        xa_store_index(xa, index - 1, GFP_KERNEL);
-                       xa_store_order(xa, index, i, xa_mk_value(index),
+                       xa_store_order(xa, index, i, xa_mk_index(index),
                                        GFP_KERNEL);
                        rcu_read_lock();
                        xas_for_each(&xas, entry, ULONG_MAX) {
@@ -778,7 +823,7 @@ static noinline void check_find_2(struct xarray *xa)
                j = 0;
                index = 0;
                xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
-                       XA_BUG_ON(xa, xa_mk_value(index) != entry);
+                       XA_BUG_ON(xa, xa_mk_index(index) != entry);
                        XA_BUG_ON(xa, index != j++);
                }
        }
@@ -786,10 +831,34 @@ static noinline void check_find_2(struct xarray *xa)
        xa_destroy(xa);
 }
 
+static noinline void check_find_3(struct xarray *xa)
+{
+       XA_STATE(xas, xa, 0);
+       unsigned long i, j, k;
+       void *entry;
+
+       for (i = 0; i < 100; i++) {
+               for (j = 0; j < 100; j++) {
+                       for (k = 0; k < 100; k++) {
+                               xas_set(&xas, j);
+                               xas_for_each_marked(&xas, entry, k, XA_MARK_0)
+                                       ;
+                               if (j > k)
+                                       XA_BUG_ON(xa,
+                                               xas.xa_node != XAS_RESTART);
+                       }
+               }
+               xa_store_index(xa, i, GFP_KERNEL);
+               xa_set_mark(xa, i, XA_MARK_0);
+       }
+       xa_destroy(xa);
+}
+
 static noinline void check_find(struct xarray *xa)
 {
        check_find_1(xa);
        check_find_2(xa);
+       check_find_3(xa);
        check_multi_find(xa);
        check_multi_find_2(xa);
 }
@@ -829,11 +898,11 @@ static noinline void check_find_entry(struct xarray *xa)
                        for (index = 0; index < (1UL << (order + 5));
                             index += (1UL << order)) {
                                xa_store_order(xa, index, order,
-                                               xa_mk_value(index), GFP_KERNEL);
+                                               xa_mk_index(index), GFP_KERNEL);
                                XA_BUG_ON(xa, xa_load(xa, index) !=
-                                               xa_mk_value(index));
+                                               xa_mk_index(index));
                                XA_BUG_ON(xa, xa_find_entry(xa,
-                                               xa_mk_value(index)) != index);
+                                               xa_mk_index(index)) != index);
                        }
                        XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
                        xa_destroy(xa);
@@ -844,7 +913,7 @@ static noinline void check_find_entry(struct xarray *xa)
        XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
        xa_store_index(xa, ULONG_MAX, GFP_KERNEL);
        XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
-       XA_BUG_ON(xa, xa_find_entry(xa, xa_mk_value(LONG_MAX)) != -1);
+       XA_BUG_ON(xa, xa_find_entry(xa, xa_mk_index(ULONG_MAX)) != -1);
        xa_erase_index(xa, ULONG_MAX);
        XA_BUG_ON(xa, !xa_empty(xa));
 }
@@ -864,7 +933,7 @@ static noinline void check_move_small(struct xarray *xa, unsigned long idx)
                        XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
                XA_BUG_ON(xa, xas.xa_index != i);
                if (i == 0 || i == idx)
-                       XA_BUG_ON(xa, entry != xa_mk_value(i));
+                       XA_BUG_ON(xa, entry != xa_mk_index(i));
                else
                        XA_BUG_ON(xa, entry != NULL);
        }
@@ -878,7 +947,7 @@ static noinline void check_move_small(struct xarray *xa, unsigned long idx)
                        XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
                XA_BUG_ON(xa, xas.xa_index != i);
                if (i == 0 || i == idx)
-                       XA_BUG_ON(xa, entry != xa_mk_value(i));
+                       XA_BUG_ON(xa, entry != xa_mk_index(i));
                else
                        XA_BUG_ON(xa, entry != NULL);
        } while (i > 0);
@@ -909,7 +978,7 @@ static noinline void check_move(struct xarray *xa)
        do {
                void *entry = xas_prev(&xas);
                i--;
-               XA_BUG_ON(xa, entry != xa_mk_value(i));
+               XA_BUG_ON(xa, entry != xa_mk_index(i));
                XA_BUG_ON(xa, i != xas.xa_index);
        } while (i != 0);
 
@@ -918,7 +987,7 @@ static noinline void check_move(struct xarray *xa)
 
        do {
                void *entry = xas_next(&xas);
-               XA_BUG_ON(xa, entry != xa_mk_value(i));
+               XA_BUG_ON(xa, entry != xa_mk_index(i));
                XA_BUG_ON(xa, i != xas.xa_index);
                i++;
        } while (i < (1 << 16));
@@ -934,7 +1003,7 @@ static noinline void check_move(struct xarray *xa)
                void *entry = xas_prev(&xas);
                i--;
                if ((i < (1 << 8)) || (i >= (1 << 15)))
-                       XA_BUG_ON(xa, entry != xa_mk_value(i));
+                       XA_BUG_ON(xa, entry != xa_mk_index(i));
                else
                        XA_BUG_ON(xa, entry != NULL);
                XA_BUG_ON(xa, i != xas.xa_index);
@@ -946,7 +1015,7 @@ static noinline void check_move(struct xarray *xa)
        do {
                void *entry = xas_next(&xas);
                if ((i < (1 << 8)) || (i >= (1 << 15)))
-                       XA_BUG_ON(xa, entry != xa_mk_value(i));
+                       XA_BUG_ON(xa, entry != xa_mk_index(i));
                else
                        XA_BUG_ON(xa, entry != NULL);
                XA_BUG_ON(xa, i != xas.xa_index);
@@ -976,7 +1045,7 @@ static noinline void xa_store_many_order(struct xarray *xa,
                if (xas_error(&xas))
                        goto unlock;
                for (i = 0; i < (1U << order); i++) {
-                       XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(index + i)));
+                       XA_BUG_ON(xa, xas_store(&xas, xa_mk_index(index + i)));
                        xas_next(&xas);
                }
 unlock:
@@ -1031,9 +1100,9 @@ static noinline void check_create_range_4(struct xarray *xa,
                if (xas_error(&xas))
                        goto unlock;
                for (i = 0; i < (1UL << order); i++) {
-                       void *old = xas_store(&xas, xa_mk_value(base + i));
+                       void *old = xas_store(&xas, xa_mk_index(base + i));
                        if (xas.xa_index == index)
-                               XA_BUG_ON(xa, old != xa_mk_value(base + i));
+                               XA_BUG_ON(xa, old != xa_mk_index(base + i));
                        else
                                XA_BUG_ON(xa, old != NULL);
                        xas_next(&xas);
@@ -1085,10 +1154,10 @@ static noinline void __check_store_range(struct xarray *xa, unsigned long first,
                unsigned long last)
 {
 #ifdef CONFIG_XARRAY_MULTI
-       xa_store_range(xa, first, last, xa_mk_value(first), GFP_KERNEL);
+       xa_store_range(xa, first, last, xa_mk_index(first), GFP_KERNEL);
 
-       XA_BUG_ON(xa, xa_load(xa, first) != xa_mk_value(first));
-       XA_BUG_ON(xa, xa_load(xa, last) != xa_mk_value(first));
+       XA_BUG_ON(xa, xa_load(xa, first) != xa_mk_index(first));
+       XA_BUG_ON(xa, xa_load(xa, last) != xa_mk_index(first));
        XA_BUG_ON(xa, xa_load(xa, first - 1) != NULL);
        XA_BUG_ON(xa, xa_load(xa, last + 1) != NULL);
 
@@ -1195,7 +1264,7 @@ static noinline void check_account(struct xarray *xa)
                XA_BUG_ON(xa, xas.xa_node->nr_values != 0);
                rcu_read_unlock();
 
-               xa_store_order(xa, 1 << order, order, xa_mk_value(1 << order),
+               xa_store_order(xa, 1 << order, order, xa_mk_index(1UL << order),
                                GFP_KERNEL);
                XA_BUG_ON(xa, xas.xa_node->count != xas.xa_node->nr_values * 2);
 
index bbacca5..5f3f931 100644 (file)
@@ -1131,7 +1131,7 @@ void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)
                entry = xa_head(xas->xa);
                xas->xa_node = NULL;
                if (xas->xa_index > max_index(entry))
-                       goto bounds;
+                       goto out;
                if (!xa_is_node(entry)) {
                        if (xa_marked(xas->xa, mark))
                                return entry;
@@ -1180,11 +1180,9 @@ void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)
        }
 
 out:
-       if (!max)
+       if (xas->xa_index > max)
                goto max;
-bounds:
-       xas->xa_node = XAS_BOUNDS;
-       return NULL;
+       return set_bounds(xas);
 max:
        xas->xa_node = XAS_RESTART;
        return NULL;
index 705a3e9..a808324 100644 (file)
@@ -1248,10 +1248,11 @@ void free_huge_page(struct page *page)
                (struct hugepage_subpool *)page_private(page);
        bool restore_reserve;
 
-       set_page_private(page, 0);
-       page->mapping = NULL;
        VM_BUG_ON_PAGE(page_count(page), page);
        VM_BUG_ON_PAGE(page_mapcount(page), page);
+
+       set_page_private(page, 0);
+       page->mapping = NULL;
        restore_reserve = PagePrivate(page);
        ClearPagePrivate(page);
 
index 9a2d5ae..81ae63c 100644 (file)
@@ -1727,7 +1727,7 @@ static int __init_memblock memblock_search(struct memblock_type *type, phys_addr
        return -1;
 }
 
-bool __init memblock_is_reserved(phys_addr_t addr)
+bool __init_memblock memblock_is_reserved(phys_addr_t addr)
 {
        return memblock_search(&memblock.reserved, addr) != -1;
 }
index 921f804..5d07e0b 100644 (file)
@@ -661,9 +661,7 @@ static int shmem_free_swap(struct address_space *mapping,
 {
        void *old;
 
-       xa_lock_irq(&mapping->i_pages);
-       old = __xa_cmpxchg(&mapping->i_pages, index, radswap, NULL, 0);
-       xa_unlock_irq(&mapping->i_pages);
+       old = xa_cmpxchg_irq(&mapping->i_pages, index, radswap, NULL, 0);
        if (old != radswap)
                return -ENOENT;
        free_swap_and_cache(radix_to_swp_entry(radswap));
index 33307fc..3abc8cc 100644 (file)
@@ -240,6 +240,22 @@ void __init memory_present(int nid, unsigned long start, unsigned long end)
 }
 
 /*
+ * Mark all memblocks as present using memory_present(). This is a
+ * convienence function that is useful for a number of arches
+ * to mark all of the systems memory as present during initialization.
+ */
+void __init memblocks_present(void)
+{
+       struct memblock_region *reg;
+
+       for_each_memblock(memory, reg) {
+               memory_present(memblock_get_region_node(reg),
+                              memblock_region_memory_base_pfn(reg),
+                              memblock_region_memory_end_pfn(reg));
+       }
+}
+
+/*
  * Subtle, we encode the real pfn into the mem_map such that
  * the identity pfn - section_mem_map will return the actual
  * physical page frame number.
index 8081b6c..34414c6 100755 (executable)
@@ -47,8 +47,8 @@ my (@stack, $re, $dre, $x, $xs, $funcre);
        $xs     = "[0-9a-f ]";  # hex character or space
        $funcre = qr/^$x* <(.*)>:$/;
        if ($arch eq 'aarch64') {
-               #ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp,#-80]!
-               $re = qr/^.*stp.*sp,\#-([0-9]{1,8})\]\!/o;
+               #ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp, #-80]!
+               $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;
        } elsif ($arch eq 'arm') {
                #c0008ffc:      e24dd064        sub     sp, sp, #100    ; 0x64
                $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
index 5056fb3..e559c62 100755 (executable)
@@ -168,6 +168,7 @@ class id_parser(object):
         self.curline = 0
         try:
             for line in fd:
+                line = line.decode(locale.getpreferredencoding(False), errors='ignore')
                 self.curline += 1
                 if self.curline > maxlines:
                     break
@@ -249,12 +250,13 @@ if __name__ == '__main__':
 
     try:
         if len(args.path) and args.path[0] == '-':
-            parser.parse_lines(sys.stdin, args.maxlines, '-')
+            stdin = os.fdopen(sys.stdin.fileno(), 'rb')
+            parser.parse_lines(stdin, args.maxlines, '-')
         else:
             if args.path:
                 for p in args.path:
                     if os.path.isfile(p):
-                        parser.parse_lines(open(p), args.maxlines, p)
+                        parser.parse_lines(open(p, 'rb'), args.maxlines, p)
                     elif os.path.isdir(p):
                         scan_git_subtree(repo.head.reference.commit.tree, p)
                     else:
index 8c94998..7489cb7 100644 (file)
@@ -580,9 +580,9 @@ void ima_update_policy(void)
        ima_update_policy_flag();
 }
 
+/* Keep the enumeration in sync with the policy_tokens! */
 enum {
-       Opt_err = -1,
-       Opt_measure = 1, Opt_dont_measure,
+       Opt_measure, Opt_dont_measure,
        Opt_appraise, Opt_dont_appraise,
        Opt_audit, Opt_hash, Opt_dont_hash,
        Opt_obj_user, Opt_obj_role, Opt_obj_type,
@@ -592,10 +592,10 @@ enum {
        Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
        Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
        Opt_appraise_type, Opt_permit_directio,
-       Opt_pcr
+       Opt_pcr, Opt_err
 };
 
-static match_table_t policy_tokens = {
+static const match_table_t policy_tokens = {
        {Opt_measure, "measure"},
        {Opt_dont_measure, "dont_measure"},
        {Opt_appraise, "appraise"},
@@ -1103,7 +1103,7 @@ void ima_policy_stop(struct seq_file *m, void *v)
 {
 }
 
-#define pt(token)      policy_tokens[token + Opt_err].pattern
+#define pt(token)      policy_tokens[token].pattern
 #define mt(token)      mask_tokens[token]
 
 /*
index 7839788..70e65a2 100644 (file)
@@ -25,7 +25,7 @@ static void keyctl_pkey_params_free(struct kernel_pkey_params *params)
 }
 
 enum {
-       Opt_err = -1,
+       Opt_err,
        Opt_enc,                /* "enc=<encoding>" eg. "enc=oaep" */
        Opt_hash,               /* "hash=<digest-name>" eg. "hash=sha1" */
 };
index ff67893..697bfc6 100644 (file)
@@ -711,7 +711,7 @@ static int key_unseal(struct trusted_key_payload *p,
 }
 
 enum {
-       Opt_err = -1,
+       Opt_err,
        Opt_new, Opt_load, Opt_update,
        Opt_keyhandle, Opt_keyauth, Opt_blobauth,
        Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
index 64c3cb0..654a503 100644 (file)
@@ -30,7 +30,7 @@ static int ff400_get_clock(struct snd_ff *ff, unsigned int *rate,
        int err;
 
        err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
-                                FF400_SYNC_STATUS, &reg, sizeof(reg), 0);
+                                FF400_CLOCK_CONFIG, &reg, sizeof(reg), 0);
        if (err < 0)
                return err;
        data = le32_to_cpu(reg);
index 8d75597..15021c8 100644 (file)
@@ -5520,6 +5520,9 @@ enum {
        ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
        ALC295_FIXUP_HP_AUTO_MUTE,
        ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
+       ALC294_FIXUP_ASUS_MIC,
+       ALC294_FIXUP_ASUS_HEADSET_MIC,
+       ALC294_FIXUP_ASUS_SPK,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6392,6 +6395,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_invalidate_dacs,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
        },
        [ALC295_FIXUP_HP_AUTO_MUTE] = {
                .type = HDA_FIXUP_FUNC,
@@ -6406,6 +6411,36 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
+       [ALC294_FIXUP_ASUS_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x13, 0x90a60160 }, /* use as internal mic */
+                       { 0x19, 0x04a11120 }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
+       [ALC294_FIXUP_ASUS_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x01a1113c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
+       [ALC294_FIXUP_ASUS_SPK] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Set EAPD high */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6548,6 +6583,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
+       SND_PCI_QUIRK(0x1043, 0x14a1, "ASUS UX533FD", ALC294_FIXUP_ASUS_SPK),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -7155,6 +7191,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
        SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC292_STANDARD_PINS,
                {0x13, 0x90a60140}),
+       SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC,
+               {0x14, 0x90170110},
+               {0x1b, 0x90a70130},
+               {0x21, 0x04211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
+               {0x12, 0x90a60130},
+               {0x17, 0x90170110},
+               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC295_STANDARD_PINS,
                {0x17, 0x21014020},
@@ -7227,6 +7271,37 @@ static void alc269_fill_coef(struct hda_codec *codec)
        alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
 
+static void alc294_hp_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       int i, val;
+
+       if (!hp_pin)
+               return;
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+       msleep(100);
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+       /* Wait for depop procedure finish  */
+       val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       for (i = 0; i < 20 && val & 0x0080; i++) {
+               msleep(50);
+               val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       }
+       /* Set HP depop to auto mode */
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+       msleep(50);
+}
+
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -7352,6 +7427,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC294;
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
+               alc294_hp_init(codec);
                break;
        case 0x10ec0300:
                spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7363,6 +7439,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC700;
                spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
+               alc294_hp_init(codec);
                break;
 
        }
index acf1afa..397d6b6 100644 (file)
@@ -7,6 +7,7 @@ LDLIBS+= -lpthread -lurcu
 TARGETS = main idr-test multiorder xarray
 CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o
 OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \
+        regression4.o \
         tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o
 
 ifndef SHIFT
index 77a44c5..7a22d6e 100644 (file)
@@ -308,6 +308,7 @@ int main(int argc, char **argv)
        regression1_test();
        regression2_test();
        regression3_test();
+       regression4_test();
        iteration_test(0, 10 + 90 * long_run);
        iteration_test(7, 10 + 90 * long_run);
        single_thread_tests(long_run);
index 3c8a158..135145a 100644 (file)
@@ -5,5 +5,6 @@
 void regression1_test(void);
 void regression2_test(void);
 void regression3_test(void);
+void regression4_test(void);
 
 #endif
diff --git a/tools/testing/radix-tree/regression4.c b/tools/testing/radix-tree/regression4.c
new file mode 100644 (file)
index 0000000..cf4e5ab
--- /dev/null
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/radix-tree.h>
+#include <linux/rcupdate.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "regression.h"
+
+static pthread_barrier_t worker_barrier;
+static int obj0, obj1;
+static RADIX_TREE(mt_tree, GFP_KERNEL);
+
+static void *reader_fn(void *arg)
+{
+       int i;
+       void *entry;
+
+       rcu_register_thread();
+       pthread_barrier_wait(&worker_barrier);
+
+       for (i = 0; i < 1000000; i++) {
+               rcu_read_lock();
+               entry = radix_tree_lookup(&mt_tree, 0);
+               rcu_read_unlock();
+               if (entry != &obj0) {
+                       printf("iteration %d bad entry = %p\n", i, entry);
+                       abort();
+               }
+       }
+
+       rcu_unregister_thread();
+
+       return NULL;
+}
+
+static void *writer_fn(void *arg)
+{
+       int i;
+
+       rcu_register_thread();
+       pthread_barrier_wait(&worker_barrier);
+
+       for (i = 0; i < 1000000; i++) {
+               radix_tree_insert(&mt_tree, 1, &obj1);
+               radix_tree_delete(&mt_tree, 1);
+       }
+
+       rcu_unregister_thread();
+
+       return NULL;
+}
+
+void regression4_test(void)
+{
+       pthread_t reader, writer;
+
+       printv(1, "regression test 4 starting\n");
+
+       radix_tree_insert(&mt_tree, 0, &obj0);
+       pthread_barrier_init(&worker_barrier, NULL, 2);
+
+       if (pthread_create(&reader, NULL, reader_fn, NULL) ||
+           pthread_create(&writer, NULL, writer_fn, NULL)) {
+               perror("pthread_create");
+               exit(1);
+       }
+
+       if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) {
+               perror("pthread_join");
+               exit(1);
+       }
+
+       printv(1, "regression test 4 passed\n");
+}
index e147323..c9a2abf 100644 (file)
@@ -2731,9 +2731,14 @@ TEST(syscall_restart)
        ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
        ASSERT_EQ(true, WIFSTOPPED(status));
        ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
-       /* Verify signal delivery came from parent now. */
        ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
-       EXPECT_EQ(getpid(), info.si_pid);
+       /*
+        * There is no siginfo on SIGSTOP any more, so we can't verify
+        * signal delivery came from parent now (getpid() == info.si_pid).
+        * https://lkml.kernel.org/r/CAGXu5jJaZAOzP1qFz66tYrtbuywqb+UN2SOA1VLHpCCOiYvYeg@mail.gmail.com
+        * At least verify the SIGSTOP via PTRACE_GETSIGINFO.
+        */
+       EXPECT_EQ(SIGSTOP, info.si_signo);
 
        /* Restart nanosleep with SIGCONT, which triggers restart_syscall. */
        ASSERT_EQ(0, kill(child_pid, SIGCONT));