]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge tag 'drm-misc-next-2017-09-20' of git://anongit.freedesktop.org/git/drm-misc...
authorDave Airlie <airlied@redhat.com>
Wed, 27 Sep 2017 19:45:27 +0000 (05:45 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 27 Sep 2017 19:46:15 +0000 (05:46 +1000)
UAPI Changes:

Cross-subsystem Changes:

Core Changes:
- DP SDP defines (Ville)
- polish for scdc helpers (Thierry Reding)
- fix lifetimes for connector/plane state across crtc changes (Maarten
  Lankhorst).
- sparse fixes (Ville+Thierry)
- make legacy kms ioctls all interruptible (Maarten)
- push edid override into the edid helpers (out of probe helpers)
  (Jani)
- DP ESI defines for link status (DK)

Driver Changes:
- drm-panel is now in drm-misc!
- minor panel-simple cleanups/refactoring by various folks
- drm_bridge_add cleanup (Inki Dae)
- constify a few i2c_device_id structs (Arvind Yadav)
- More patches from Noralf's fb/gem helper cleanup
- bridge/synopsis: reset fix (Philippe Cornu)
- fix tracepoint include handling in drivers (Thierry)
- rockchip: lvds support (Sandy Huang)
- move sun4i into drm-misc fold (Maxime Ripard)
- sun4i: refactor driver load + support TCON backend/layer muxing
  (Chen-Yu Tsai)
- pl111: support more pl11x variants (Linus Walleij)
- bridge/adv7511: robustify probing/edid handling (Lars-Petersen
  Clausen)

New hw support:
- S6E63J0X03 panel (Hoegeun Kwon)
- OTM8009A panel (Philippe CORNU)
- Seiko 43WVF1G panel (Marco Franchi)
- tve200 driver (Linus Walleij)

Plus assorted of tiny patches all over, including our first outreachy
patches from applicants for the winter round!

* tag 'drm-misc-next-2017-09-20' of git://anongit.freedesktop.org/git/drm-misc: (101 commits)
  drm: add backwards compatibility support for drm_kms_helper.edid_firmware
  drm: handle override and firmware EDID at drm_do_get_edid() level
  drm/dp: DPCD register defines for link status within ESI field
  drm/rockchip: Replace dev_* with DRM_DEV_*
  drm/tinydrm: Drop driver registered message
  drm/gem-fb-helper: Use debug message on gem lookup failure
  drm/imx: Use drm_gem_fb_create() and drm_gem_fb_prepare_fb()
  drm/bridge: adv7511: Constify HDMI CODEC platform data
  drm/bridge: adv7511: Enable connector polling when no interrupt is specified
  drm/bridge: adv7511: Remove private copy of the EDID
  drm/bridge: adv7511: Properly update EDID when no EDID was found
  drm/crtc: Convert setcrtc ioctl locking to interruptible.
  drm/atomic: Convert pageflip ioctl locking to interruptible.
  drm/legacy: Convert setplane ioctl locking to interruptible.
  drm/legacy: Convert cursor ioctl locking to interruptible.
  drm/atomic: Convert atomic ioctl locking to interruptible.
  drm/atomic: Prepare drm_modeset_lock infrastructure for interruptible waiting, v2.
  drm/tve200: Clean up panel bridging
  drm/doc: Update todo.rst
  drm/dp/mst: Sideband message transaction to power up/down nodes
  ...

17 files changed:
1  2 
Documentation/admin-guide/kernel-parameters.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
MAINTAINERS
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_scdc_helper.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
include/uapi/drm/drm_mode.h

index 05496622b4effb8212eb2175bea67f9a7bebe0d0,9b393c29953f2c3e71abb5bce304e6bd69c3e804..b24108f2a438d83ca88622ff51fca2279c8d8639
                        The filter can be disabled or changed to another
                        driver later using sysfs.
  
-       drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
+       drm.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
                        Broken monitors, graphic adapters, KVMs and EDIDless
                        panels may send no or incorrect EDID data sets.
                        This parameter allows to specify an EDID data sets
                        memory contents and reserves bad memory
                        regions that are detected.
  
 +      mem_encrypt=    [X86-64] AMD Secure Memory Encryption (SME) control
 +                      Valid arguments: on, off
 +                      Default (depends on kernel configuration option):
 +                        on  (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y)
 +                        off (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=n)
 +                      mem_encrypt=on:         Activate SME
 +                      mem_encrypt=off:        Do not activate SME
 +
 +                      Refer to Documentation/x86/amd-memory-encryption.txt
 +                      for details on when memory encryption can be activated.
 +
        mem_sleep_default=      [SUSPEND] Default system suspend mode:
                        s2idle  - Suspend-To-Idle
                        shallow - Power-On Suspend or equivalent (if supported)
                        In kernels built with CONFIG_NO_HZ_FULL=y, set
                        the specified list of CPUs whose tick will be stopped
                        whenever possible. The boot CPU will be forced outside
 -                      the range to maintain the timekeeping.
 -                      The CPUs in this range must also be included in the
 -                      rcu_nocbs= set.
 +                      the range to maintain the timekeeping.  Any CPUs
 +                      in this list will have their RCU callbacks offloaded,
 +                      just as if they had also been called out in the
 +                      rcu_nocbs= boot parameter.
  
        noiotrap        [SH] Disables trapped I/O port accesses.
  
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
  
 +      nopcid          [X86-64] Disable the PCID cpu feature.
 +
        norandmaps      Don't use address space randomization.  Equivalent to
                        echo 0 > /proc/sys/kernel/randomize_va_space
  
                        If the dependencies are under your control, you can
                        turn on cpu0_hotplug.
  
 +      nps_mtm_hs_ctr= [KNL,ARC]
 +                      This parameter sets the maximum duration, in
 +                      cycles, each HW thread of the CTOP can run
 +                      without interruptions, before HW switches it.
 +                      The actual maximum duration is 16 times this
 +                      parameter's value.
 +                      Format: integer between 1 and 255
 +                      Default: 255
 +
        nptcg=          [IA-64] Override max number of concurrent global TLB
                        purges which is reported from either PAL_VM_SUMMARY or
                        SAL PALO.
                        Allowed values are enable and disable
  
        numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
 -                      one of ['zone', 'node', 'default'] can be specified
 +                      'node', 'default' can be specified
                        This can be set from sysctl after boot.
                        See Documentation/sysctl/vm.txt for details.
  
                        Run specified binary instead of /init from the ramdisk,
                        used for early userspace startup. See initrd.
  
 +      rdt=            [HW,X86,RDT]
 +                      Turn on/off individual RDT features. List is:
 +                      cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, mba.
 +                      E.g. to turn on cmt and turn off mba use:
 +                              rdt=cmt,!mba
 +
        reboot=         [KNL]
                        Format (x86 or x86_64):
                                [w[arm] | c[old] | h[ard] | s[oft] | g[pio]] \
                        decrease the size and leave more room for directly
                        mapped kernel RAM.
  
 +      vmcp_cma=nn[MG] [KNL,S390]
 +                      Sets the memory size reserved for contiguous memory
 +                      allocations for the vmcp device driver.
 +
        vmhalt=         [KNL,S390] Perform z/VM CP command after system halt.
                        Format: <command>
  
index 1afd298eddd73147ebf6a1dcbc56bf404559cff1,1dff0b5ca6e4bbf5a50e4a60d13183b097e1dafe..6cf1dc5bc77ed4a38a19385dcbeac5541b21c3a0
@@@ -3,13 -3,12 +3,13 @@@ Device tree binding vendor prefix regis
  This isn't an exhaustive list, but you should add new prefixes to it before
  using them to avoid name-space collisions.
  
 -abcn  Abracon Corporation
  abilis        Abilis Systems
 +abracon       Abracon Corporation
  actions       Actions Semiconductor Co., Ltd.
  active-semi   Active-Semi International Inc
  ad    Avionic Design GmbH
  adapteva      Adapteva, Inc.
 +adaptrum      Adaptrum, Inc.
  adh   AD Holdings Plc.
  adi   Analog Devices, Inc.
  advantech     Advantech Corporation
@@@ -48,7 -47,6 +48,7 @@@ avic  Shanghai AVIC Optoelectronics Co.
  axentia       Axentia Technologies AB
  axis  Axis Communications AB
  bananapi BIPAI KEJI LIMITED
 +bhf   Beckhoff Automation GmbH & Co. KG
  boe   BOE Technology Group Co., Ltd.
  bosch Bosch Sensortec GmbH
  boundary      Boundary Devices Inc.
@@@ -90,7 -88,6 +90,7 @@@ dlg   Dialog Semiconducto
  dlink D-Link Corporation
  dmo   Data Modul AG
  domintech     Domintech Co., Ltd.
 +dongwoon      Dongwoon Anatech
  dptechnics    DPTechnics
  dragino       Dragino Technology Co., Limited
  ea    Embedded Artists AB
@@@ -178,7 -175,6 +178,7 @@@ kosagi     Sutajio Ko-Usagi PTE Ltd
  kyo   Kyocera Corporation
  lacie LaCie
  lantiq        Lantiq Semiconductor
 +lattice       Lattice Semiconductor
  lego  LEGO Systems A/S
  lenovo        Lenovo Group Ltd.
  lg    LG Corporation
@@@ -199,7 -195,6 +199,7 @@@ mediatek   MediaTek Inc
  megachips     MegaChips
  melexis       Melexis N.V.
  melfas        MELFAS Inc.
 +mellanox      Mellanox Technologies
  memsic        MEMSIC Inc.
  merrii        Merrii Technology Co., Ltd.
  micrel        Micrel Inc.
@@@ -211,7 -206,7 +211,7 @@@ miramems   MiraMEMS Sensing Technology Co
  mitsubishi    Mitsubishi Electric Corporation
  mosaixtech    Mosaix Technologies, Inc.
  motorola      Motorola, Inc.
 -moxa  Moxa
 +moxa  Moxa Inc.
  mpl   MPL AG
  mqmaker       mqmaker Inc.
  msi   Micro-Star International Co. Ltd.
@@@ -248,6 -243,7 +248,7 @@@ ontat      On Tat Industrial Compan
  opencores     OpenCores.org
  option        Option NV
  ORCL  Oracle Corporation
+ orisetech     Orise Technology
  ortustech     Ortus Technology Co., Ltd.
  ovti  OmniVision Technologies
  oxsemi        Oxford Semiconductor, Ltd.
@@@ -293,7 -289,6 +294,7 @@@ schindler  Schindle
  seagate       Seagate Technology PLC
  semtech       Semtech Corporation
  sensirion     Sensirion AG
 +sff   Small Form Factor Committee
  sgx   SGX Sensortech
  sharp Sharp Corporation
  si-en Si-En Technology Ltd.
@@@ -348,7 -343,6 +349,7 @@@ tpo        TP
  tronfy        Tronfy
  tronsmart     Tronsmart
  truly Truly Semiconductors Limited
 +tsd   Theobroma Systems Design und Consulting GmbH
  tyan  Tyan Computer Corporation
  ucrobotics    uCRobotics
  udoo  Udoo
@@@ -361,7 -355,6 +362,7 @@@ variscite  Variscite Ltd
  via   VIA Technologies, Inc.
  virtio        Virtual I/O Device Specification, developed by the OASIS consortium
  vivante       Vivante Corporation
 +vocore VoCore Studio
  voipac        Voipac Technologies s.r.o.
  wd    Western Digital Corp.
  wetek WeTek Electronics, limited.
diff --combined MAINTAINERS
index 6671f375f7fcdd1cf9e40f62c884f1ef9592dab9,e4b83f3819ec4595b4052a4087e7fb545036c834..7ab4c373c37031f54923bc6dc76ad91e8978600d
@@@ -301,7 -301,6 +301,7 @@@ S: Supporte
  F:    drivers/acpi/
  F:    drivers/pnp/pnpacpi/
  F:    include/linux/acpi.h
 +F:    include/linux/fwnode.h
  F:    include/acpi/
  F:    Documentation/acpi/
  F:    Documentation/ABI/testing/sysfs-bus-acpi
@@@ -311,14 -310,6 +311,14 @@@ F:       drivers/pci/*/*acpi
  F:    drivers/pci/*/*/*acpi*
  F:    tools/power/acpi/
  
 +ACPI APEI
 +M:    "Rafael J. Wysocki" <rjw@rjwysocki.net>
 +M:    Len Brown <lenb@kernel.org>
 +L:    linux-acpi@vger.kernel.org
 +R:    Tony Luck <tony.luck@intel.com>
 +R:    Borislav Petkov <bp@alien8.de>
 +F:    drivers/acpi/apei/
 +
  ACPI COMPONENT ARCHITECTURE (ACPICA)
  M:    Robert Moore <robert.moore@intel.com>
  M:    Lv Zheng <lv.zheng@intel.com>
@@@ -352,18 -343,6 +352,18 @@@ L:       linux-acpi@vger.kernel.or
  S:    Maintained
  F:    drivers/acpi/arm64
  
 +ACPI PMIC DRIVERS
 +M:    "Rafael J. Wysocki" <rjw@rjwysocki.net>
 +M:    Len Brown <lenb@kernel.org>
 +R:    Andy Shevchenko <andy@infradead.org>
 +R:    Mika Westerberg <mika.westerberg@linux.intel.com>
 +L:    linux-acpi@vger.kernel.org
 +Q:    https://patchwork.kernel.org/project/linux-acpi/list/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 +B:    https://bugzilla.kernel.org
 +S:    Supported
 +F:    drivers/acpi/pmic/
 +
  ACPI THERMAL DRIVER
  M:    Zhang Rui <rui.zhang@intel.com>
  L:    linux-acpi@vger.kernel.org
@@@ -656,11 -635,6 +656,11 @@@ ALPS PS/2 TOUCHPAD DRIVE
  R:    Pali Rohár <pali.rohar@gmail.com>
  F:    drivers/input/mouse/alps.*
  
 +ALTERA I2C CONTROLLER DRIVER
 +M:    Thor Thayer <thor.thayer@linux.intel.com>
 +S:    Maintained
 +F:    drivers/i2c/busses/i2c-altera.c
 +
  ALTERA MAILBOX DRIVER
  M:    Ley Foon Tan <lftan@altera.com>
  L:    nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
@@@ -795,12 -769,6 +795,12 @@@ W:       http://ez.analog.com/community/linux
  S:    Supported
  F:    drivers/media/i2c/adv7180.c
  
 +ANALOG DEVICES INC ADV748X DRIVER
 +M:    Kieran Bingham <kieran.bingham@ideasonboard.com>
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    drivers/media/i2c/adv748x/*
 +
  ANALOG DEVICES INC ADV7511 DRIVER
  M:    Hans Verkuil <hans.verkuil@cisco.com>
  L:    linux-media@vger.kernel.org
@@@ -872,12 -840,6 +872,12 @@@ S:       Supporte
  F:    drivers/android/
  F:    drivers/staging/android/
  
 +ANDROID GOLDFISH RTC DRIVER
 +M:    Miodrag Dinic <miodrag.dinic@imgtec.com>
 +S:    Supported
 +F:    Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt
 +F:    drivers/rtc/rtc-goldfish.c
 +
  ANDROID ION DRIVER
  M:    Laura Abbott <labbott@redhat.com>
  M:    Sumit Semwal <sumit.semwal@linaro.org>
@@@ -1191,7 -1153,6 +1191,7 @@@ L:      linux-arm-kernel@axis.co
  F:    arch/arm/mach-artpec
  F:    arch/arm/boot/dts/artpec6*
  F:    drivers/clk/axis
 +F:    drivers/crypto/axis
  F:    drivers/pinctrl/pinctrl-artpec*
  F:    Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt
  
@@@ -1321,15 -1282,10 +1321,15 @@@ S:   Maintaine
  
  ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
  M:    Hans Ulli Kroll <ulli.kroll@googlemail.com>
 +M:    Linus Walleij <linus.walleij@linaro.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  T:    git git://github.com/ulli-kroll/linux.git
  S:    Maintained
 +F:    Documentation/devicetree/bindings/arm/gemini.txt
 +F:    Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
 +F:    Documentation/devicetree/bindings/rtc/faraday,ftrtc010.txt
  F:    arch/arm/mach-gemini/
 +F:    drivers/pinctrl/pinctrl-gemini.c
  F:    drivers/rtc/rtc-ftrtc010.c
  
  ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
@@@ -1614,7 -1570,7 +1614,7 @@@ M:      Chunfeng Yun <chunfeng.yun@mediatek.
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  L:    linux-mediatek@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 -F:    drivers/phy/phy-mt65xx-usb3.c
 +F:    drivers/phy/mediatek/phy-mtk-tphy.c
  
  ARM/MICREL KS8695 ARCHITECTURE
  M:    Greg Ungerer <gerg@uclinux.org>
@@@ -2037,7 -1993,6 +2037,7 @@@ F:      arch/arm64/boot/dts/socionext
  F:    drivers/bus/uniphier-system-bus.c
  F:    drivers/clk/uniphier/
  F:    drivers/i2c/busses/i2c-uniphier*
 +F:    drivers/irqchip/irq-uniphier-aidet.c
  F:    drivers/pinctrl/uniphier/
  F:    drivers/reset/reset-uniphier.c
  F:    drivers/tty/serial/8250/8250_uniphier.c
@@@ -2124,38 -2079,17 +2124,38 @@@ F:   arch/arm/mach-pxa/include/mach/z2.
  ARM/ZTE ARCHITECTURE
  M:    Jun Nie <jun.nie@linaro.org>
  M:    Baoyou Xie <baoyou.xie@linaro.org>
 +M:    Shawn Guo <shawnguo@kernel.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 +F:    arch/arm/boot/dts/zx2967*
  F:    arch/arm/mach-zx/
 +F:    arch/arm64/boot/dts/zte/
  F:    drivers/clk/zte/
 +F:    drivers/dma/zx_dma.c
 +F:    drivers/gpio/gpio-zx.c
 +F:    drivers/i2c/busses/i2c-zx2967.c
 +F:    drivers/mmc/host/dw_mmc-zx.*
 +F:    drivers/pinctrl/zte/
  F:    drivers/reset/reset-zx2967.c
  F:    drivers/soc/zte/
 +F:    drivers/thermal/zx2967_thermal.c
 +F:    drivers/watchdog/zx2967_wdt.c
  F:    Documentation/devicetree/bindings/arm/zte.txt
 -F:    Documentation/devicetree/bindings/clock/zx296702-clk.txt
 +F:    Documentation/devicetree/bindings/clock/zx2967*.txt
 +F:    Documentation/devicetree/bindings/dma/zxdma.txt
 +F:    Documentation/devicetree/bindings/gpio/zx296702-gpio.txt
 +F:    Documentation/devicetree/bindings/i2c/i2c-zx2967.txt
 +F:    Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt
 +F:    Documentation/devicetree/bindings/pinctrl/pinctrl-zx.txt
  F:    Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt
  F:    Documentation/devicetree/bindings/soc/zte/
 -F:    include/dt-bindings/soc/zx*.h
 +F:    Documentation/devicetree/bindings/sound/zte,*.txt
 +F:    Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
 +F:    Documentation/devicetree/bindings/watchdog/zte,zx2967-wdt.txt
 +F:    include/dt-bindings/clock/zx2967*.h
 +F:    include/dt-bindings/soc/zte,*.h
 +F:    sound/soc/codecs/zx_aud96p22.c
 +F:    sound/soc/zte/
  
  ARM/ZYNQ ARCHITECTURE
  M:    Michal Simek <michal.simek@xilinx.com>
@@@ -2183,12 -2117,6 +2183,12 @@@ S:    Maintaine
  F:    arch/arm64/
  F:    Documentation/arm64/
  
 +AS3645A LED FLASH CONTROLLER DRIVER
 +M:    Sakari Ailus <sakari.ailus@iki.fi>
 +L:    linux-leds@vger.kernel.org
 +S:    Maintained
 +F:    drivers/leds/leds-as3645a.c
 +
  AS3645A LED FLASH CONTROLLER DRIVER
  M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  L:    linux-media@vger.kernel.org
@@@ -2457,10 -2385,9 +2457,10 @@@ AUDIT SUBSYSTE
  M:    Paul Moore <paul@paul-moore.com>
  M:    Eric Paris <eparis@redhat.com>
  L:    linux-audit@redhat.com (moderated for non-subscribers)
 -W:    http://people.redhat.com/sgrubb/audit/
 -T:    git git://git.infradead.org/users/pcmoore/audit
 -S:    Maintained
 +W:    https://github.com/linux-audit
 +W:    https://people.redhat.com/sgrubb/audit
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git
 +S:    Supported
  F:    include/linux/audit.h
  F:    include/uapi/linux/audit.h
  F:    kernel/audit*
@@@ -2550,7 -2477,7 +2550,7 @@@ Q:      https://patchwork.open-mesh.org/proj
  S:    Maintained
  F:    Documentation/ABI/testing/sysfs-class-net-batman-adv
  F:    Documentation/ABI/testing/sysfs-class-net-mesh
 -F:    Documentation/networking/batman-adv.txt
 +F:    Documentation/networking/batman-adv.rst
  F:    include/uapi/linux/batman_adv.h
  F:    net/batman-adv/
  
@@@ -2619,6 -2546,13 +2619,6 @@@ W:     http://blackfin.uclinux.or
  S:    Supported
  F:    drivers/net/ethernet/adi/
  
 -BLACKFIN I2C TWI DRIVER
 -M:    Sonic Zhang <sonic.zhang@analog.com>
 -L:    adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
 -W:    http://blackfin.uclinux.org/
 -S:    Supported
 -F:    drivers/i2c/busses/i2c-bfin-twi.c
 -
  BLACKFIN MEDIA DRIVER
  M:    Scott Jiang <scott.jiang.linux@gmail.com>
  L:    adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
@@@ -2635,12 -2569,14 +2635,12 @@@ S:   Supporte
  F:    drivers/rtc/rtc-bfin.c
  
  BLACKFIN SDH DRIVER
 -M:    Sonic Zhang <sonic.zhang@analog.com>
  L:    adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
  W:    http://blackfin.uclinux.org
  S:    Supported
  F:    drivers/mmc/host/bfin_sdh.c
  
  BLACKFIN SERIAL DRIVER
 -M:    Sonic Zhang <sonic.zhang@analog.com>
  L:    adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
  W:    http://blackfin.uclinux.org
  S:    Supported
@@@ -2865,6 -2801,7 +2865,6 @@@ S:      Supporte
  F:    drivers/scsi/bnx2i/
  
  BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
 -M:    Yuval Mintz <Yuval.Mintz@cavium.com>
  M:    Ariel Elior <ariel.elior@cavium.com>
  M:    everest-linux-l2@cavium.com
  L:    netdev@vger.kernel.org
@@@ -3218,7 -3155,6 +3218,7 @@@ S:      Supporte
  F:    drivers/crypto/cavium/cpt/
  
  CAVIUM THUNDERX2 ARM64 SOC
 +M:    Robert Richter <rrichter@cavium.com>
  M:    Jayachandran C <jnair@caviumnetworks.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
@@@ -4172,9 -4108,7 +4172,9 @@@ F:      include/linux/dax.
  F:    include/trace/events/fs_dax.h
  
  DIRECTORY NOTIFICATION (DNOTIFY)
 -M:    Eric Paris <eparis@parisplace.org>
 +M:    Jan Kara <jack@suse.cz>
 +R:    Amir Goldstein <amir73il@gmail.com>
 +L:    linux-fsdevel@vger.kernel.org
  S:    Maintained
  F:    Documentation/filesystems/dnotify.txt
  F:    fs/notify/dnotify/
@@@ -4241,7 -4175,7 +4241,7 @@@ DMA MAPPING HELPER
  M:    Christoph Hellwig <hch@lst.de>
  M:    Marek Szyprowski <m.szyprowski@samsung.com>
  R:    Robin Murphy <robin.murphy@arm.com>
 -L:    linux-kernel@vger.kernel.org
 +L:    iommu@lists.linux-foundation.org
  T:    git git://git.infradead.org/users/hch/dma-mapping.git
  W:    http://git.infradead.org/users/hch/dma-mapping.git
  S:    Supported
@@@ -4366,6 -4300,12 +4366,12 @@@ T:    git git://anongit.freedesktop.org/dr
  S:    Maintained
  F:    drivers/gpu/drm/bochs/
  
+ DRM DRIVER FOR FARADAY TVE200 TV ENCODER
+ M:    Linus Walleij <linus.walleij@linaro.org>
+ T:    git git://anongit.freedesktop.org/drm/drm-misc
+ S:    Maintained
+ F:    drivers/gpu/drm/tve200/
  DRM DRIVER FOR INTEL I810 VIDEO CARDS
  S:    Orphan / Obsolete
  F:    drivers/gpu/drm/i810/
@@@ -4407,12 -4347,6 +4413,12 @@@ S:    Supporte
  F:    drivers/gpu/drm/nouveau/
  F:    include/uapi/drm/nouveau_drm.h
  
 +DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS
 +M:    Noralf Trønnes <noralf@tronnes.org>
 +S:    Maintained
 +F:    drivers/gpu/drm/tinydrm/repaper.c
 +F:    Documentation/devicetree/bindings/display/repaper.txt
 +
  DRM DRIVER FOR QEMU'S CIRRUS DEVICE
  M:    Dave Airlie <airlied@redhat.com>
  M:    Gerd Hoffmann <kraxel@redhat.com>
@@@ -4431,6 -4365,12 +4437,6 @@@ S:     Maintaine
  F:    drivers/gpu/drm/qxl/
  F:    include/uapi/drm/qxl_drm.h
  
 -DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS
 -M:    Noralf Trønnes <noralf@tronnes.org>
 -S:    Maintained
 -F:    drivers/gpu/drm/tinydrm/repaper.c
 -F:    Documentation/devicetree/bindings/display/repaper.txt
 -
  DRM DRIVER FOR RAGE 128 VIDEO CARDS
  S:    Orphan / Obsolete
  F:    drivers/gpu/drm/r128/
@@@ -4509,7 -4449,7 +4515,7 @@@ L:      dri-devel@lists.freedesktop.or
  S:    Supported
  F:    drivers/gpu/drm/sun4i/
  F:    Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git
+ T:    git git://anongit.freedesktop.org/drm/drm-misc
  
  DRM DRIVERS FOR AMLOGIC SOCS
  M:    Neil Armstrong <narmstrong@baylibre.com>
@@@ -4693,7 -4633,7 +4699,7 @@@ T:      git git://anongit.freedesktop.org/dr
  DRM PANEL DRIVERS
  M:    Thierry Reding <thierry.reding@gmail.com>
  L:    dri-devel@lists.freedesktop.org
- T:    git git://anongit.freedesktop.org/tegra/linux.git
+ T:    git git://anongit.freedesktop.org/drm/drm-misc
  S:    Maintained
  F:    drivers/gpu/drm/drm_panel.c
  F:    drivers/gpu/drm/panel/
@@@ -5187,7 -5127,6 +5193,7 @@@ F:      include/linux/of_net.
  F:    include/linux/phy.h
  F:    include/linux/phy_fixed.h
  F:    include/linux/platform_data/mdio-gpio.h
 +F:    include/linux/platform_data/mdio-bcm-unimac.h
  F:    include/trace/events/mdio.h
  F:    include/uapi/linux/mdio.h
  F:    include/uapi/linux/mii.h
@@@ -5285,9 -5224,7 +5291,9 @@@ F:      Documentation/hwmon/f71805
  F:    drivers/hwmon/f71805f.c
  
  FANOTIFY
 -M:    Eric Paris <eparis@redhat.com>
 +M:    Jan Kara <jack@suse.cz>
 +R:    Amir Goldstein <amir73il@gmail.com>
 +L:    linux-fsdevel@vger.kernel.org
  S:    Maintained
  F:    fs/notify/fanotify/
  F:    include/linux/fanotify.h
@@@ -5430,11 -5367,10 +5436,11 @@@ K:   fmc_d.*registe
  
  FPGA MANAGER FRAMEWORK
  M:    Alan Tull <atull@kernel.org>
 -R:    Moritz Fischer <moritz.fischer@ettus.com>
 +R:    Moritz Fischer <mdf@kernel.org>
  L:    linux-fpga@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
 +Q:    http://patchwork.kernel.org/project/linux-fpga/list/
  F:    Documentation/fpga/
  F:    Documentation/devicetree/bindings/fpga/
  F:    drivers/fpga/
@@@ -5853,12 -5789,6 +5859,12 @@@ S:    Maintaine
  F:    Documentation/acpi/gpio-properties.txt
  F:    drivers/gpio/gpiolib-acpi.c
  
 +GPIO IR Transmitter
 +M:    Sean Young <sean@mess.org>
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    drivers/media/rc/gpio-ir-tx.c
 +
  GPIO MOCKUP DRIVER
  M:    Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
  L:    linux-gpio@vger.kernel.org
@@@ -6128,6 -6058,16 +6134,6 @@@ F:     drivers/scsi/hpsa*.[ch
  F:    include/linux/cciss*.h
  F:    include/uapi/linux/cciss*.h
  
 -HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
 -M:    Don Brace <don.brace@microsemi.com>
 -L:    esc.storagedev@microsemi.com
 -L:    linux-scsi@vger.kernel.org
 -S:    Supported
 -F:    Documentation/blockdev/cciss.txt
 -F:    drivers/block/cciss*
 -F:    include/linux/cciss_ioctl.h
 -F:    include/uapi/linux/cciss_ioctl.h
 -
  HFI1 DRIVER
  M:    Mike Marciniszyn <mike.marciniszyn@intel.com>
  M:    Dennis Dalessandro <dennis.dalessandro@intel.com>
@@@ -6224,14 -6164,6 +6230,14 @@@ F:    include/uapi/linux/if_hippi.
  F:    net/802/hippi.c
  F:    drivers/net/hippi/
  
 +HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
 +M:    Yisen Zhuang <yisen.zhuang@huawei.com>
 +M:    Salil Mehta <salil.mehta@huawei.com>
 +L:    netdev@vger.kernel.org
 +W:    http://www.hisilicon.com
 +S:    Maintained
 +F:    drivers/net/ethernet/hisilicon/hns3/
 +
  HISILICON NETWORK SUBSYSTEM DRIVER
  M:    Yisen Zhuang <yisen.zhuang@huawei.com>
  M:    Salil Mehta <salil.mehta@huawei.com>
@@@ -6256,13 -6188,6 +6262,13 @@@ S:    Supporte
  F:    drivers/scsi/hisi_sas/
  F:    Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
  
 +HMM - Heterogeneous Memory Management
 +M:    Jérôme Glisse <jglisse@redhat.com>
 +L:    linux-mm@kvack.org
 +S:    Maintained
 +F:    mm/hmm*
 +F:    include/linux/hmm*
 +
  HOST AP DRIVER
  M:    Jouni Malinen <j@w1.fi>
  L:    linux-wireless@vger.kernel.org
@@@ -6332,13 -6257,6 +6338,13 @@@ L:    linux-input@vger.kernel.or
  S:    Maintained
  F:    drivers/input/touchscreen/htcpen.c
  
 +HUAWEI ETHERNET DRIVER
 +M:    Aviad Krawczyk <aviad.krawczyk@huawei.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    Documentation/networking/hinic.txt
 +F:    drivers/net/ethernet/huawei/hinic/
 +
  HUGETLB FILESYSTEM
  M:    Nadia Yvette Chambers <nyc@holomorphy.com>
  S:    Maintained
@@@ -6365,9 -6283,7 +6371,9 @@@ M:      Haiyang Zhang <haiyangz@microsoft.co
  M:    Stephen Hemminger <sthemmin@microsoft.com>
  L:    devel@linuxdriverproject.org
  S:    Maintained
 +F:    Documentation/networking/netvsc.txt
  F:    arch/x86/include/asm/mshyperv.h
 +F:    arch/x86/include/asm/trace/hyperv.h
  F:    arch/x86/include/uapi/asm/hyperv.h
  F:    arch/x86/kernel/cpu/mshyperv.c
  F:    arch/x86/hyperv
@@@ -6379,9 -6295,7 +6385,9 @@@ F:      drivers/net/hyperv
  F:    drivers/scsi/storvsc_drv.c
  F:    drivers/uio/uio_hv_generic.c
  F:    drivers/video/fbdev/hyperv_fb.c
 +F:    net/vmw_vsock/hyperv_transport.c
  F:    include/linux/hyperv.h
 +F:    include/uapi/linux/hyperv.h
  F:    tools/hv/
  F:    Documentation/ABI/stable/sysfs-bus-vmbus
  
@@@ -6483,12 -6397,6 +6489,12 @@@ F:    drivers/i2c/busses/i2c-sis96x.
  F:    drivers/i2c/busses/i2c-via.c
  F:    drivers/i2c/busses/i2c-viapro.c
  
 +I2C/SMBUS INTEL CHT WHISKEY COVE PMIC DRIVER
 +M:    Hans de Goede <hdegoede@redhat.com>
 +L:    linux-i2c@vger.kernel.org
 +S:    Maintained
 +F:    drivers/i2c/busses/i2c-cht-wc.c
 +
  I2C/SMBUS ISMT DRIVER
  M:    Seth Heasley <seth.heasley@intel.com>
  M:    Neil Horman <nhorman@tuxdriver.com>
@@@ -6555,15 -6463,6 +6561,15 @@@ L:    netdev@vger.kernel.or
  S:    Supported
  F:    drivers/net/ethernet/ibm/ibmvnic.*
  
 +IBM Power Virtual Accelerator Switchboard
 +M:    Sukadev Bhattiprolu
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Supported
 +F:    arch/powerpc/platforms/powernv/vas*
 +F:    arch/powerpc/platforms/powernv/copy-paste.h
 +F:    arch/powerpc/include/asm/vas.h
 +F:    arch/powerpc/include/uapi/asm/vas.h
 +
  IBM Power Virtual Ethernet Device Driver
  M:    Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
  L:    netdev@vger.kernel.org
@@@ -6654,8 -6553,8 +6660,8 @@@ M:      Alexander Aring <alex.aring@gmail.co
  M:    Stefan Schmidt <stefan@osg.samsung.com>
  L:    linux-wpan@vger.kernel.org
  W:    http://wpan.cakelab.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
  S:    Maintained
  F:    net/ieee802154/
  F:    net/mac802154/
@@@ -6800,9 -6699,9 +6806,9 @@@ S:      Maintaine
  F:    drivers/mtd/nand/jz4780_*
  
  INOTIFY
 -M:    John McCutchan <john@johnmccutchan.com>
 -M:    Robert Love <rlove@rlove.org>
 -M:    Eric Paris <eparis@parisplace.org>
 +M:    Jan Kara <jack@suse.cz>
 +R:    Amir Goldstein <amir73il@gmail.com>
 +L:    linux-fsdevel@vger.kernel.org
  S:    Maintained
  F:    Documentation/filesystems/inotify.txt
  F:    fs/notify/inotify/
@@@ -6871,9 -6770,8 +6877,9 @@@ S:      Supporte
  F:    drivers/scsi/isci/
  
  INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 -M:    Daniel Vetter <daniel.vetter@intel.com>
  M:    Jani Nikula <jani.nikula@linux.intel.com>
 +M:    Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
 +M:    Rodrigo Vivi <rodrigo.vivi@intel.com>
  L:    intel-gfx@lists.freedesktop.org
  W:    https://01.org/linuxgraphics/
  B:    https://01.org/linuxgraphics/documentation/how-report-bugs
@@@ -7211,7 -7109,9 +7217,7 @@@ W:      http://irda.sourceforge.net
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
  F:    Documentation/networking/irda.txt
 -F:    drivers/net/irda/
 -F:    include/net/irda/
 -F:    net/irda/
 +F:    drivers/staging/irda/
  
  IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
  M:    Marc Zyngier <marc.zyngier@arm.com>
@@@ -7236,6 -7136,7 +7242,6 @@@ M:      Marc Zyngier <marc.zyngier@arm.com
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 -T:    git git://git.infradead.org/users/jcooper/linux.git irqchip/core
  F:    Documentation/devicetree/bindings/interrupt-controller/
  F:    drivers/irqchip/
  
@@@ -7505,13 -7406,6 +7511,13 @@@ S:    Maintaine
  F:    tools/testing/selftests/
  F:    Documentation/dev-tools/kselftest*
  
 +KERNEL USERMODE HELPER
 +M:    "Luis R. Rodriguez" <mcgrof@kernel.org>
 +L:    linux-kernel@vger.kernel.org
 +S:    Maintained
 +F:    kernel/umh.c
 +F:    include/linux/umh.h
 +
  KERNEL VIRTUAL MACHINE (KVM)
  M:    Paolo Bonzini <pbonzini@redhat.com>
  M:    Radim Krčmář <rkrcmar@redhat.com>
@@@ -7519,17 -7413,18 +7525,17 @@@ L:   kvm@vger.kernel.or
  W:    http://www.linux-kvm.org
  T:    git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
  S:    Supported
 -F:    Documentation/*/kvm*.txt
  F:    Documentation/virtual/kvm/
 -F:    arch/*/kvm/
 -F:    arch/x86/kernel/kvm.c
 -F:    arch/x86/kernel/kvmclock.c
 -F:    arch/*/include/asm/kvm*
 -F:    include/linux/kvm*
 +F:    include/trace/events/kvm.h
 +F:    include/uapi/asm-generic/kvm*
  F:    include/uapi/linux/kvm*
 -F:    virt/kvm/
 +F:    include/asm-generic/kvm*
 +F:    include/linux/kvm*
 +F:    include/kvm/iodev.h
 +F:    virt/kvm/*
  F:    tools/kvm/
  
 -KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
 +KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd)
  M:    Joerg Roedel <joro@8bytes.org>
  L:    kvm@vger.kernel.org
  W:    http://www.linux-kvm.org/
@@@ -7537,7 -7432,7 +7543,7 @@@ S:      Maintaine
  F:    arch/x86/include/asm/svm.h
  F:    arch/x86/kvm/svm.c
  
 -KERNEL VIRTUAL MACHINE (KVM) FOR ARM
 +KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm)
  M:    Christoffer Dall <christoffer.dall@linaro.org>
  M:    Marc Zyngier <marc.zyngier@arm.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -7551,6 -7446,15 +7557,6 @@@ F:     arch/arm/kvm
  F:    virt/kvm/arm/
  F:    include/kvm/arm_*
  
 -KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
 -M:    Alexander Graf <agraf@suse.com>
 -L:    kvm-ppc@vger.kernel.org
 -W:    http://www.linux-kvm.org/
 -T:    git git://github.com/agraf/linux-2.6.git
 -S:    Supported
 -F:    arch/powerpc/include/asm/kvm*
 -F:    arch/powerpc/kvm/
 -
  KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
  M:    Christoffer Dall <christoffer.dall@linaro.org>
  M:    Marc Zyngier <marc.zyngier@arm.com>
@@@ -7569,17 -7473,6 +7575,17 @@@ F:    arch/mips/include/uapi/asm/kvm
  F:    arch/mips/include/asm/kvm*
  F:    arch/mips/kvm/
  
 +KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc)
 +M:    Alexander Graf <agraf@suse.com>
 +L:    kvm-ppc@vger.kernel.org
 +W:    http://www.linux-kvm.org/
 +T:    git git://github.com/agraf/linux-2.6.git
 +S:    Supported
 +F:    arch/powerpc/include/uapi/asm/kvm*
 +F:    arch/powerpc/include/asm/kvm*
 +F:    arch/powerpc/kvm/
 +F:    arch/powerpc/kernel/kvm*
 +
  KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
  M:    Christian Borntraeger <borntraeger@de.ibm.com>
  M:    Cornelia Huck <cohuck@redhat.com>
@@@ -7587,25 -7480,11 +7593,25 @@@ L:   linux-s390@vger.kernel.or
  W:    http://www.ibm.com/developerworks/linux/linux390/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
  S:    Supported
 -F:    Documentation/s390/kvm.txt
 +F:    arch/s390/include/uapi/asm/kvm*
 +F:    arch/s390/include/asm/gmap.h
  F:    arch/s390/include/asm/kvm*
  F:    arch/s390/kvm/
  F:    arch/s390/mm/gmap.c
  
 +KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
 +M:    Paolo Bonzini <pbonzini@redhat.com>
 +M:    Radim Krčmář <rkrcmar@redhat.com>
 +L:    kvm@vger.kernel.org
 +W:    http://www.linux-kvm.org
 +T:    git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
 +S:    Supported
 +F:    arch/x86/kvm/
 +F:    arch/x86/include/uapi/asm/kvm*
 +F:    arch/x86/include/asm/kvm*
 +F:    arch/x86/kernel/kvm.c
 +F:    arch/x86/kernel/kvmclock.c
 +
  KERNFS
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  M:    Tejun Heo <tj@kernel.org>
@@@ -7687,7 -7566,7 +7693,7 @@@ F:      include/linux/kmemleak.
  F:    mm/kmemleak.c
  F:    mm/kmemleak-test.c
  
 -KMOD MODULE USERMODE HELPER
 +KMOD KERNEL MODULE LOADER - USERMODE HELPER
  M:    "Luis R. Rodriguez" <mcgrof@kernel.org>
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
@@@ -7728,7 -7607,6 +7734,7 @@@ M:      John Crispin <john@phrozen.org
  L:    linux-mips@linux-mips.org
  S:    Maintained
  F:    arch/mips/lantiq
 +F:    drivers/soc/lantiq
  
  LAPB module
  L:    linux-x25@vger.kernel.org
@@@ -7788,6 -7666,17 +7794,6 @@@ T:     git git://linuxtv.org/mkrufky/tuners
  S:    Maintained
  F:    drivers/media/dvb-frontends/lgdt3305.*
  
 -LGUEST
 -M:    Rusty Russell <rusty@rustcorp.com.au>
 -L:    lguest@lists.ozlabs.org
 -W:    http://lguest.ozlabs.org/
 -S:    Odd Fixes
 -F:    arch/x86/include/asm/lguest*.h
 -F:    arch/x86/lguest/
 -F:    drivers/lguest/
 -F:    include/linux/lguest*.h
 -F:    tools/lguest/
 -
  LIBATA PATA ARASAN COMPACT FLASH CONTROLLER
  M:    Viresh Kumar <vireshk@kernel.org>
  L:    linux-ide@vger.kernel.org
@@@ -7923,7 -7812,6 +7929,7 @@@ F:      drivers/pci/hotplug/rpa
  F:    drivers/rtc/rtc-opal.c
  F:    drivers/scsi/ibmvscsi/
  F:    drivers/tty/hvc/hvc_opal.c
 +F:    drivers/watchdog/wdrtas.c
  F:    tools/testing/selftests/powerpc
  N:    /pmac
  N:    powermac
@@@ -8440,14 -8328,6 +8446,14 @@@ T:    git git://linuxtv.org/media_tree.gi
  S:    Supported
  F:    drivers/media/dvb-frontends/cxd2841er*
  
 +MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES
 +M:    Daniel Scheller <d.scheller.oss@gmail.com>
 +L:    linux-media@vger.kernel.org
 +W:    https://linuxtv.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Maintained
 +F:    drivers/media/pci/ddbridge/*
 +
  MEDIA DRIVERS FOR FREESCALE IMX
  M:    Steve Longerbeam <slongerbeam@gmail.com>
  M:    Philipp Zabel <p.zabel@pengutronix.de>
@@@ -8489,14 -8369,6 +8495,14 @@@ T:    git git://linuxtv.org/media_tree.gi
  S:    Supported
  F:    drivers/media/dvb-frontends/lnbh25*
  
 +MEDIA DRIVERS FOR MXL5XX TUNER DEMODULATORS
 +M:    Daniel Scheller <d.scheller.oss@gmail.com>
 +L:    linux-media@vger.kernel.org
 +W:    https://linuxtv.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Maintained
 +F:    drivers/media/dvb-frontends/mxl5xx*
 +
  MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
  M:    Sergey Kozlov <serjk@netup.ru>
  M:    Abylay Ospan <aospan@netup.ru>
@@@ -8553,22 -8425,6 +8559,22 @@@ S:    Supporte
  F:    Documentation/devicetree/bindings/media/renesas,vsp1.txt
  F:    drivers/media/platform/vsp1/
  
 +MEDIA DRIVERS FOR ST STV0910 DEMODULATOR ICs
 +M:    Daniel Scheller <d.scheller.oss@gmail.com>
 +L:    linux-media@vger.kernel.org
 +W:    https://linuxtv.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Maintained
 +F:    drivers/media/dvb-frontends/stv0910*
 +
 +MEDIA DRIVERS FOR ST STV6111 TUNER ICs
 +M:    Daniel Scheller <d.scheller.oss@gmail.com>
 +L:    linux-media@vger.kernel.org
 +W:    https://linuxtv.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Maintained
 +F:    drivers/media/dvb-frontends/stv6111*
 +
  MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
  M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
  M:    Mauro Carvalho Chehab <mchehab@kernel.org>
@@@ -8592,16 -8448,9 +8598,16 @@@ F:    include/uapi/linux/meye.
  F:    include/uapi/linux/ivtv*
  F:    include/uapi/linux/uvcvideo.h
  
 +MEDIATEK CIR DRIVER
 +M:    Sean Wang <sean.wang@mediatek.com>
 +S:    Maintained
 +F:    drivers/media/rc/mtk-cir.c
 +
  MEDIATEK ETHERNET DRIVER
  M:    Felix Fietkau <nbd@openwrt.org>
 -M:    John Crispin <blogic@openwrt.org>
 +M:    John Crispin <john@phrozen.org>
 +M:    Sean Wang <sean.wang@mediatek.com>
 +M:    Nelson Chang <nelson.chang@mediatek.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/ethernet/mediatek/
@@@ -8642,14 -8491,6 +8648,14 @@@ M:    Sean Wang <sean.wang@mediatek.com
  S:    Maintained
  F:    drivers/char/hw_random/mtk-rng.c
  
 +MEDIATEK USB3 DRD IP DRIVER
 +M:    Chunfeng Yun <chunfeng.yun@mediatek.com>
 +L:    linux-usb@vger.kernel.org (moderated for non-subscribers)
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +L:    linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    drivers/usb/mtu3/
 +
  MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
  M:    Peter Senna Tschudin <peter.senna@collabora.com>
  M:    Martin Donnelly <martin.donnelly@ge.com>
@@@ -8814,7 -8655,7 +8820,7 @@@ M:      Mathieu Desnoyers <mathieu.desnoyers
  M:    "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
  L:    linux-kernel@vger.kernel.org
  S:    Supported
 -F:    kernel/membarrier.c
 +F:    kernel/sched/membarrier.c
  F:    include/uapi/linux/membarrier.h
  
  MEMORY MANAGEMENT
@@@ -8868,16 -8709,6 +8874,16 @@@ F:    drivers/leds/leds-menf21bmc.
  F:    drivers/hwmon/menf21bmc_hwmon.c
  F:    Documentation/hwmon/menf21bmc
  
 +MESON AO CEC DRIVER FOR AMLOGIC SOCS
 +M:    Neil Armstrong <narmstrong@baylibre.com>
 +L:    linux-media@lists.freedesktop.org
 +L:    linux-amlogic@lists.infradead.org
 +W:    http://linux-meson.com/
 +S:    Supported
 +F:    drivers/media/platform/meson/ao-cec.c
 +F:    Documentation/devicetree/bindings/media/meson-ao-cec.txt
 +T:    git git://linuxtv.org/media_tree.git
 +
  METAG ARCHITECTURE
  M:    James Hogan <james.hogan@imgtec.com>
  L:    linux-metag@vger.kernel.org
@@@ -8914,12 -8745,6 +8920,12 @@@ F:    drivers/dma/at_hdmac.
  F:    drivers/dma/at_hdmac_regs.h
  F:    include/linux/platform_data/dma-atmel.h
  
 +MICROCHIP / ATMEL ECC DRIVER
 +M:    Tudor Ambarus <tudor.ambarus@microchip.com>
 +L:    linux-crypto@vger.kernel.org
 +S:    Maintained
 +F:    drivers/crypto/atmel-ecc.*
 +
  MICROCHIP / ATMEL ISC DRIVER
  M:    Songjun Wu <songjun.wu@microchip.com>
  L:    linux-media@vger.kernel.org
@@@ -8994,7 -8819,6 +9000,7 @@@ M:      Paul Burton <paul.burton@imgtec.com
  L:    linux-mips@linux-mips.org
  S:    Supported
  F:    arch/mips/generic/
 +F:    arch/mips/tools/generic-board-config.sh
  
  MIPS/LOONGSON1 ARCHITECTURE
  M:    Keguang Zhang <keguang.zhang@gmail.com>
@@@ -9005,13 -8829,6 +9011,13 @@@ F:    arch/mips/include/asm/mach-loongson3
  F:    drivers/*/*loongson1*
  F:    drivers/*/*/*loongson1*
  
 +MIPS RINT INSTRUCTION EMULATION
 +M:    Aleksandar Markovic <aleksandar.markovic@imgtec.com>
 +L:    linux-mips@linux-mips.org
 +S:    Supported
 +F:    arch/mips/math-emu/sp_rint.c
 +F:    arch/mips/math-emu/dp_rint.c
 +
  MIROSOUND PCM20 FM RADIO RECEIVER DRIVER
  M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
@@@ -9237,7 -9054,7 +9243,7 @@@ T:      git git://git.infradead.org/linux-mt
  T:    git git://git.infradead.org/l2-mtd.git nand/next
  S:    Maintained
  F:    drivers/mtd/nand/
 -F:    include/linux/mtd/nand*.h
 +F:    include/linux/mtd/*nand*.h
  
  NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
  M:    Daniel Mack <zonque@gmail.com>
@@@ -9329,6 -9146,15 +9335,6 @@@ F:     net/*/netfilter
  F:    net/netfilter/
  F:    net/bridge/br_netfilter*.c
  
 -NETLABEL
 -M:    Paul Moore <paul@paul-moore.com>
 -W:    http://netlabel.sf.net
 -L:    netdev@vger.kernel.org
 -S:    Maintained
 -F:    Documentation/netlabel/
 -F:    include/net/netlabel.h
 -F:    net/netlabel/
 -
  NETROM NETWORK LAYER
  M:    Ralf Baechle <ralf@linux-mips.org>
  L:    linux-hams@vger.kernel.org
@@@ -9456,23 -9282,10 +9462,23 @@@ F:   net/ipv6
  F:    include/net/ip*
  F:    arch/x86/net/*
  
 -NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
 +NETWORKING [LABELED] (NetLabel, Labeled IPsec, SECMARK)
  M:    Paul Moore <paul@paul-moore.com>
 +W:    https://github.com/netlabel
  L:    netdev@vger.kernel.org
 +L:    linux-security-module@vger.kernel.org
  S:    Maintained
 +F:    Documentation/netlabel/
 +F:    include/net/calipso.h
 +F:    include/net/cipso_ipv4.h
 +F:    include/net/netlabel.h
 +F:    include/uapi/linux/netfilter/xt_SECMARK.h
 +F:    include/uapi/linux/netfilter/xt_CONNSECMARK.h
 +F:    net/netlabel/
 +F:    net/ipv4/cipso_ipv4.c
 +F:    net/ipv6/calipso.c
 +F:    net/netfilter/xt_CONNSECMARK.c
 +F:    net/netfilter/xt_SECMARK.c
  
  NETWORKING [TLS]
  M:    Ilya Lesokhin <ilyal@mellanox.com>
@@@ -9679,7 -9492,6 +9685,7 @@@ M:      Srinivas Kandagatla <srinivas.kandag
  S:    Maintained
  F:    drivers/nvmem/
  F:    Documentation/devicetree/bindings/nvmem/
 +F:    Documentation/ABI/stable/sysfs-bus-nvmem
  F:    include/linux/nvmem-consumer.h
  F:    include/linux/nvmem-provider.h
  
@@@ -9889,12 -9701,6 +9895,12 @@@ F:    drivers/regulator/twl-regulator.
  F:    drivers/regulator/twl6030-regulator.c
  F:    include/linux/i2c-omap.h
  
 +ONION OMEGA2+ BOARD
 +M:    Harvey Hunt <harveyhuntnexus@gmail.com>
 +L:    linux-mips@linux-mips.org
 +S:    Maintained
 +F:    arch/mips/boot/dts/ralink/omega2p.dts
 +
  OMFS FILESYSTEM
  M:    Bob Copeland <me@bobcopeland.com>
  L:    linux-karma-devel@lists.sourceforge.net
@@@ -9929,7 -9735,7 +9935,7 @@@ S:      Maintaine
  F:    drivers/media/i2c/ov5640.c
  
  OMNIVISION OV5647 SENSOR DRIVER
 -M:    Ramiro Oliveira <roliveir@synopsys.com>
 +M:    Luis Oliveira <lolivei@synopsys.com>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
  S:    Maintained
@@@ -10166,7 -9972,7 +10172,7 @@@ F:    include/uapi/linux/ppdev.
  F:    Documentation/parport*.txt
  
  PARAVIRT_OPS INTERFACE
 -M:    Jeremy Fitzhardinge <jeremy@goop.org>
 +M:    Juergen Gross <jgross@suse.com>
  M:    Chris Wright <chrisw@sous-sol.org>
  M:    Alok Kataria <akataria@vmware.com>
  M:    Rusty Russell <rusty@rustcorp.com.au>
@@@ -10174,7 -9980,7 +10180,7 @@@ L:    virtualization@lists.linux-foundatio
  S:    Supported
  F:    Documentation/virtual/paravirt_ops.txt
  F:    arch/*/kernel/paravirt*
 -F:    arch/*/include/asm/paravirt.h
 +F:    arch/*/include/asm/paravirt*.h
  F:    include/linux/hypervisor.h
  
  PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
@@@ -10318,7 -10124,6 +10324,7 @@@ F:   drivers/pci/dwc/*imx6
  
  PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
  M:    Keith Busch <keith.busch@intel.com>
 +M:    Jonathan Derrick <jonathan.derrick@intel.com>
  L:    linux-pci@vger.kernel.org
  S:    Supported
  F:    drivers/pci/host/vmd.c
@@@ -10365,7 -10170,7 +10371,7 @@@ L:   linux-samsung-soc@vger.kernel.org (m
  S:    Maintained
  F:    drivers/pci/dwc/pci-exynos.c
  
 -PCI DRIVER FOR SYNOPSIS DESIGNWARE
 +PCI DRIVER FOR SYNOPSYS DESIGNWARE
  M:    Jingoo Han <jingoohan1@gmail.com>
  M:    Joao Pinto <Joao.Pinto@synopsys.com>
  L:    linux-pci@vger.kernel.org
@@@ -10801,11 -10606,8 +10807,11 @@@ W: http://wiki.enneenne.com/index.php/L
  L:    linuxpps@ml.enneenne.com (subscribers-only)
  S:    Maintained
  F:    Documentation/pps/
 +F:    Documentation/devicetree/bindings/pps/pps-gpio.txt
 +F:    Documentation/ABI/testing/sysfs-pps
  F:    drivers/pps/
  F:    include/linux/pps*.h
 +F:    include/uapi/linux/pps.h
  
  PPTP DRIVER
  M:    Dmitry Kozlov <xeb@mail.ru>
@@@ -10931,7 -10733,6 +10937,7 @@@ L:   linux-media@vger.kernel.or
  T:    git git://linuxtv.org/media_tree.git
  S:    Maintained
  F:    drivers/media/usb/pulse8-cec/*
 +F:    Documentation/media/cec-drivers/pulse8-cec.rst
  
  PVRUSB2 VIDEO4LINUX DRIVER
  M:    Mike Isely <isely@pobox.com>
@@@ -10959,12 -10760,6 +10965,12 @@@ F: Documentation/devicetree/bindings/hw
  F:    Documentation/hwmon/pwm-fan
  F:    drivers/hwmon/pwm-fan.c
  
 +PWM IR Transmitter
 +M:    Sean Young <sean@mess.org>
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    drivers/media/rc/pwm-ir-tx.c
 +
  PWM SUBSYSTEM
  M:    Thierry Reding <thierry.reding@gmail.com>
  L:    linux-pwm@vger.kernel.org
@@@ -11058,6 -10853,7 +11064,6 @@@ S:   Supporte
  F:    drivers/scsi/qedi/
  
  QLOGIC QL4xxx ETHERNET DRIVER
 -M:    Yuval Mintz <Yuval.Mintz@cavium.com>
  M:    Ariel Elior <Ariel.Elior@cavium.com>
  M:    everest-linux-l2@cavium.com
  L:    netdev@vger.kernel.org
@@@ -11158,14 -10954,6 +11164,14 @@@ W: http://wireless.kernel.org/en/users/
  S:    Supported
  F:    drivers/net/wireless/ath/ath9k/
  
 +QUALCOMM CAMERA SUBSYSTEM DRIVER
 +M:    Todor Tomov <todor.tomov@linaro.org>
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/media/qcom,camss.txt
 +F:    Documentation/media/v4l-drivers/qcom_camss.rst
 +F:    drivers/media/platform/qcom/camss-8x16/
 +
  QUALCOMM EMAC GIGABIT ETHERNET DRIVER
  M:    Timur Tabi <timur@codeaurora.org>
  L:    netdev@vger.kernel.org
@@@ -11179,13 -10967,6 +11185,13 @@@ T: git git://git.kernel.org/pub/scm/lin
  S:    Supported
  F:    arch/hexagon/
  
 +QUALCOMM IOMMU
 +M:    Rob Clark <robdclark@gmail.com>
 +L:    iommu@lists.linux-foundation.org
 +L:    linux-arm-msm@vger.kernel.org
 +S:    Maintained
 +F:    drivers/iommu/qcom_iommu.c
 +
  QUALCOMM VENUS VIDEO ACCELERATOR DRIVER
  M:    Stanimir Varbanov <stanimir.varbanov@linaro.org>
  L:    linux-media@vger.kernel.org
@@@ -11356,7 -11137,7 +11362,7 @@@ M:   Fenghua Yu <fenghua.yu@intel.com
  L:    linux-kernel@vger.kernel.org
  S:    Supported
  F:    arch/x86/kernel/cpu/intel_rdt*
 -F:    arch/x86/include/asm/intel_rdt*
 +F:    arch/x86/include/asm/intel_rdt_sched.h
  F:    Documentation/x86/intel_rdt*
  
  READ-COPY UPDATE (RCU)
@@@ -11445,8 -11226,6 +11451,8 @@@ RENESAS ETHERNET DRIVER
  R:    Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
  L:    netdev@vger.kernel.org
  L:    linux-renesas-soc@vger.kernel.org
 +F:    Documentation/devicetree/bindings/net/renesas,*.txt
 +F:    Documentation/devicetree/bindings/net/sh_eth.txt
  F:    drivers/net/ethernet/renesas/
  F:    include/linux/sh_eth.h
  
@@@ -11528,17 -11307,6 +11534,17 @@@ L: linux-serial@vger.kernel.or
  S:    Odd Fixes
  F:    drivers/tty/serial/rp2.*
  
 +ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
 +M:    Marek Vasut <marek.vasut+renesas@gmail.com>
 +L:    linux-kernel@vger.kernel.org
 +L:    linux-renesas-soc@vger.kernel.org
 +S:    Supported
 +F:    drivers/mfd/bd9571mwv.c
 +F:    drivers/regulator/bd9571mwv-regulator.c
 +F:    drivers/gpio/gpio-bd9571mwv.c
 +F:    include/linux/mfd/bd9571mwv.h
 +F:    Documentation/devicetree/bindings/mfd/bd9571mwv.txt
 +
  ROSE NETWORK LAYER
  M:    Ralf Baechle <ralf@linux-mips.org>
  L:    linux-hams@vger.kernel.org
@@@ -11700,7 -11468,6 +11706,7 @@@ F:   drivers/s390/crypto
  
  S390 ZFCP DRIVER
  M:    Steffen Maier <maier@linux.vnet.ibm.com>
 +M:    Benjamin Block <bblock@linux.vnet.ibm.com>
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
  S:    Supported
@@@ -12065,9 -11832,8 +12071,9 @@@ M:   Paul Moore <paul@paul-moore.com
  M:    Stephen Smalley <sds@tycho.nsa.gov>
  M:    Eric Paris <eparis@parisplace.org>
  L:    selinux@tycho.nsa.gov (moderated for non-subscribers)
 -W:    http://selinuxproject.org
 -T:    git git://git.infradead.org/users/pcmoore/selinux
 +W:    https://selinuxproject.org
 +W:    https://github.com/SELinuxProject
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
  S:    Supported
  F:    include/linux/selinux*
  F:    security/selinux/
@@@ -12554,7 -12320,6 +12560,7 @@@ F:   drivers/tty/serial/sunsab.
  F:    drivers/tty/serial/sunsu.c
  F:    drivers/tty/serial/sunzilog.c
  F:    drivers/tty/serial/sunzilog.h
 +F:    drivers/tty/vcc.c
  
  SPARSE CHECKER
  M:    "Christopher Li" <sparse@chrisli.org>
@@@ -12751,12 -12516,6 +12757,12 @@@ M: Ion Badulescu <ionut@badula.org
  S:    Odd Fixes
  F:    drivers/net/ethernet/adaptec/starfire*
  
 +STEC S1220 SKD DRIVER
 +M:    Bart Van Assche <bart.vanassche@wdc.com>
 +L:    linux-block@vger.kernel.org
 +S:    Maintained
 +F:    drivers/block/skd*[ch]
 +
  STI CEC DRIVER
  M:    Benjamin Gaignard <benjamin.gaignard@linaro.org>
  S:    Maintained
@@@ -12874,18 -12633,6 +12880,18 @@@ F: drivers/clocksource/arc_timer.
  F:    drivers/tty/serial/arc_uart.c
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
  
 +SYNOPSYS ARC HSDK SDP pll clock driver
 +M:    Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 +S:    Supported
 +F:    drivers/clk/clk-hsdk-pll.c
 +F:    Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt
 +
 +SYNOPSYS ARC SDP clock driver
 +M:    Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 +S:    Supported
 +F:    drivers/clk/axs10x/*
 +F:    Documentation/devicetree/bindings/clock/snps,pll-clock.txt
 +
  SYNOPSYS ARC SDP platform support
  M:    Alexey Brodkin <abrodkin@synopsys.com>
  S:    Supported
@@@ -12922,13 -12669,6 +12928,13 @@@ L: linux-mmc@vger.kernel.or
  S:    Maintained
  F:    drivers/mmc/host/dw_mmc*
  
 +SYNOPSYS HSDK RESET CONTROLLER DRIVER
 +M:    Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 +S:    Supported
 +F:    drivers/reset/reset-hsdk-v1.c
 +F:    include/dt-bindings/reset/snps,hsdk-v1-reset.h
 +F:    Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt
 +
  SYSTEM CONFIGURATION (SYSCON)
  M:    Lee Jones <lee.jones@linaro.org>
  M:    Arnd Bergmann <arnd@arndb.de>
@@@ -13279,11 -13019,6 +13285,11 @@@ M: Yehezkel Bernat <yehezkel.bernat@int
  S:    Maintained
  F:    drivers/thunderbolt/
  
 +THUNDERX GPIO DRIVER
 +M:    David Daney <david.daney@cavium.com>
 +S:    Maintained
 +F:    drivers/gpio/gpio-thunderx.c
 +
  TI AM437X VPFE DRIVER
  M:    "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
  L:    linux-media@vger.kernel.org
@@@ -13808,7 -13543,8 +13814,7 @@@ F:   Documentation/scsi/ufs.tx
  F:    drivers/scsi/ufs/
  
  UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS
 -M:    Manjunath M Bettegowda <manjumb@synopsys.com>
 -M:    Prabu Thangamuthu <prabut@synopsys.com>
 +M:    Joao Pinto <jpinto@synopsys.com>
  L:    linux-scsi@vger.kernel.org
  S:    Supported
  F:    drivers/scsi/ufs/*dwc*
@@@ -14417,12 -14153,6 +14423,12 @@@ L: netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/vmxnet3/
  
 +VOCORE VOCORE2 BOARD
 +M:    Harvey Hunt <harveyhuntnexus@gmail.com>
 +L:    linux-mips@linux-mips.org
 +S:    Maintained
 +F:    arch/mips/boot/dts/ralink/vocore2.dts
 +
  VOLTAGE AND CURRENT REGULATOR FRAMEWORK
  M:    Liam Girdwood <lgirdwood@gmail.com>
  M:    Mark Brown <broonie@kernel.org>
index 2fd383d7253a0db87a569458a017a4d155aef51b,9e787621b4f511e188fdc4c340488059e0cb8d09..366c56fe5f58409b5269875c1e9cf09d451c9c55
@@@ -163,13 -163,6 +163,6 @@@ void drm_atomic_state_default_clear(str
                crtc->funcs->atomic_destroy_state(crtc,
                                                  state->crtcs[i].state);
  
-               if (state->crtcs[i].commit) {
-                       kfree(state->crtcs[i].commit->event);
-                       state->crtcs[i].commit->event = NULL;
-                       drm_crtc_commit_put(state->crtcs[i].commit);
-               }
-               state->crtcs[i].commit = NULL;
                state->crtcs[i].ptr = NULL;
                state->crtcs[i].state = NULL;
        }
        }
        state->num_private_objs = 0;
  
+       if (state->fake_commit) {
+               drm_crtc_commit_put(state->fake_commit);
+               state->fake_commit = NULL;
+       }
  }
  EXPORT_SYMBOL(drm_atomic_state_default_clear);
  
@@@ -1631,9 -1628,6 +1628,9 @@@ int drm_atomic_check_only(struct drm_at
        if (config->funcs->atomic_check)
                ret = config->funcs->atomic_check(state->dev, state);
  
 +      if (ret)
 +              return ret;
 +
        if (!state->allow_modeset) {
                for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                        if (drm_atomic_crtc_needs_modeset(crtc_state)) {
                }
        }
  
 -      return ret;
 +      return 0;
  }
  EXPORT_SYMBOL(drm_atomic_check_only);
  
@@@ -2206,10 -2200,10 +2203,10 @@@ int drm_mode_atomic_ioctl(struct drm_de
        struct drm_atomic_state *state;
        struct drm_modeset_acquire_ctx ctx;
        struct drm_plane *plane;
 -      struct drm_out_fence_state *fence_state = NULL;
 +      struct drm_out_fence_state *fence_state;
        unsigned plane_mask;
        int ret = 0;
 -      unsigned int i, j, num_fences = 0;
 +      unsigned int i, j, num_fences;
  
        /* disallow for drivers not supporting atomic: */
        if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
                        (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
                return -EINVAL;
  
-       drm_modeset_acquire_init(&ctx, 0);
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
  
        state = drm_atomic_state_alloc(dev);
        if (!state)
@@@ -2250,8 -2244,6 +2247,8 @@@ retry
        plane_mask = 0;
        copied_objs = 0;
        copied_props = 0;
 +      fence_state = NULL;
 +      num_fences = 0;
  
        for (i = 0; i < arg->count_objs; i++) {
                uint32_t obj_id, count_props;
@@@ -2350,8 -2342,9 +2347,9 @@@ out
  
        if (ret == -EDEADLK) {
                drm_atomic_state_clear(state);
-               drm_modeset_backoff(&ctx);
-               goto retry;
+               ret = drm_modeset_backoff(&ctx);
+               if (!ret)
+                       goto retry;
        }
  
        drm_atomic_state_put(state);
index 4e53aae9a1fb19fc6710202188a53119c566aef7,b97c054f9786d606ff7afd8934bcb4bf3c4ea805..01c34bc5b5b0ce5c09d866cdfe600bdeedb5346e
@@@ -1262,12 -1262,12 +1262,12 @@@ EXPORT_SYMBOL(drm_atomic_helper_wait_fo
  void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
                                          struct drm_atomic_state *old_state)
  {
-       struct drm_crtc_state *unused;
+       struct drm_crtc_state *new_crtc_state;
        struct drm_crtc *crtc;
        int i;
  
-       for_each_new_crtc_in_state(old_state, crtc, unused, i) {
-               struct drm_crtc_commit *commit = old_state->crtcs[i].commit;
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
+               struct drm_crtc_commit *commit = new_crtc_state->commit;
                int ret;
  
                if (!commit)
@@@ -1388,35 -1388,31 +1388,31 @@@ int drm_atomic_helper_async_check(struc
  {
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
-       struct drm_crtc_commit *commit;
-       struct drm_plane *__plane, *plane = NULL;
-       struct drm_plane_state *__plane_state, *plane_state = NULL;
+       struct drm_plane *plane;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        const struct drm_plane_helper_funcs *funcs;
-       int i, j, n_planes = 0;
+       int i, n_planes = 0;
  
        for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                if (drm_atomic_crtc_needs_modeset(crtc_state))
                        return -EINVAL;
        }
  
-       for_each_new_plane_in_state(state, __plane, __plane_state, i) {
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i)
                n_planes++;
-               plane = __plane;
-               plane_state = __plane_state;
-       }
  
        /* FIXME: we support only single plane updates for now */
-       if (!plane || n_planes != 1)
+       if (n_planes != 1)
                return -EINVAL;
  
-       if (!plane_state->crtc)
+       if (!new_plane_state->crtc)
                return -EINVAL;
  
        funcs = plane->helper_private;
        if (!funcs->atomic_async_update)
                return -EINVAL;
  
-       if (plane_state->fence)
+       if (new_plane_state->fence)
                return -EINVAL;
  
        /*
         * the plane.  This prevents our async update's changes from getting
         * overridden by a previous synchronous update's state.
         */
-       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-               if (plane->crtc != crtc)
-                       continue;
+       if (old_plane_state->commit &&
+           !try_wait_for_completion(&old_plane_state->commit->hw_done))
+               return -EBUSY;
  
-               spin_lock(&crtc->commit_lock);
-               commit = list_first_entry_or_null(&crtc->commit_list,
-                                                 struct drm_crtc_commit,
-                                                 commit_entry);
-               if (!commit) {
-                       spin_unlock(&crtc->commit_lock);
-                       continue;
-               }
-               spin_unlock(&crtc->commit_lock);
-               if (!crtc->state->state)
-                       continue;
-               for_each_plane_in_state(crtc->state->state, __plane,
-                                       __plane_state, j) {
-                       if (__plane == plane)
-                               return -EINVAL;
-               }
-       }
-       return funcs->atomic_async_check(plane, plane_state);
+       return funcs->atomic_async_check(plane, new_plane_state);
  }
  EXPORT_SYMBOL(drm_atomic_helper_async_check);
  
@@@ -1633,8 -1609,7 +1609,7 @@@ static int stall_checks(struct drm_crt
                                return -EBUSY;
                        }
                } else if (i == 1) {
-                       stall_commit = commit;
-                       drm_crtc_commit_get(stall_commit);
+                       stall_commit = drm_crtc_commit_get(commit);
                        break;
                }
  
@@@ -1668,6 -1643,38 +1643,38 @@@ static void release_crtc_commit(struct 
        drm_crtc_commit_put(commit);
  }
  
+ static void init_commit(struct drm_crtc_commit *commit, struct drm_crtc *crtc)
+ {
+       init_completion(&commit->flip_done);
+       init_completion(&commit->hw_done);
+       init_completion(&commit->cleanup_done);
+       INIT_LIST_HEAD(&commit->commit_entry);
+       kref_init(&commit->ref);
+       commit->crtc = crtc;
+ }
+ static struct drm_crtc_commit *
+ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc)
+ {
+       if (crtc) {
+               struct drm_crtc_state *new_crtc_state;
+               new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+               return new_crtc_state->commit;
+       }
+       if (!state->fake_commit) {
+               state->fake_commit = kzalloc(sizeof(*state->fake_commit), GFP_KERNEL);
+               if (!state->fake_commit)
+                       return NULL;
+               init_commit(state->fake_commit, NULL);
+       }
+       return state->fake_commit;
+ }
  /**
   * drm_atomic_helper_setup_commit - setup possibly nonblocking commit
   * @state: new modeset state to be committed
@@@ -1716,6 -1723,10 +1723,10 @@@ int drm_atomic_helper_setup_commit(stru
  {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+       struct drm_connector *conn;
+       struct drm_connector_state *old_conn_state, *new_conn_state;
+       struct drm_plane *plane;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
        struct drm_crtc_commit *commit;
        int i, ret;
  
                if (!commit)
                        return -ENOMEM;
  
-               init_completion(&commit->flip_done);
-               init_completion(&commit->hw_done);
-               init_completion(&commit->cleanup_done);
-               INIT_LIST_HEAD(&commit->commit_entry);
-               kref_init(&commit->ref);
-               commit->crtc = crtc;
+               init_commit(commit, crtc);
  
-               state->crtcs[i].commit = commit;
+               new_crtc_state->commit = commit;
  
                ret = stall_checks(crtc, nonblock);
                if (ret)
                drm_crtc_commit_get(commit);
        }
  
-       return 0;
- }
- EXPORT_SYMBOL(drm_atomic_helper_setup_commit);
+       for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) {
+               /* commit tracked through new_crtc_state->commit, no need to do it explicitly */
+               if (new_conn_state->crtc)
+                       continue;
  
+               /* Userspace is not allowed to get ahead of the previous
+                * commit with nonblocking ones. */
+               if (nonblock && old_conn_state->commit &&
+                   !try_wait_for_completion(&old_conn_state->commit->flip_done))
+                       return -EBUSY;
  
- static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
- {
-       struct drm_crtc_commit *commit;
-       int i = 0;
+               commit = crtc_or_fake_commit(state, old_conn_state->crtc);
+               if (!commit)
+                       return -ENOMEM;
  
-       list_for_each_entry(commit, &crtc->commit_list, commit_entry) {
-               /* skip the first entry, that's the current commit */
-               if (i == 1)
-                       return commit;
-               i++;
+               new_conn_state->commit = drm_crtc_commit_get(commit);
+       }
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+               /*
+                * Unlike connectors, always track planes explicitly for
+                * async pageflip support.
+                */
+               /* Userspace is not allowed to get ahead of the previous
+                * commit with nonblocking ones. */
+               if (nonblock && old_plane_state->commit &&
+                   !try_wait_for_completion(&old_plane_state->commit->flip_done))
+                       return -EBUSY;
+               commit = crtc_or_fake_commit(state, old_plane_state->crtc);
+               if (!commit)
+                       return -ENOMEM;
+               new_plane_state->commit = drm_crtc_commit_get(commit);
        }
  
-       return NULL;
+       return 0;
  }
+ EXPORT_SYMBOL(drm_atomic_helper_setup_commit);
  
  /**
   * drm_atomic_helper_wait_for_dependencies - wait for required preceeding commits
  void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
  {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *new_crtc_state;
+       struct drm_crtc_state *old_crtc_state;
+       struct drm_plane *plane;
+       struct drm_plane_state *old_plane_state;
+       struct drm_connector *conn;
+       struct drm_connector_state *old_conn_state;
        struct drm_crtc_commit *commit;
        int i;
        long ret;
  
-       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-               spin_lock(&crtc->commit_lock);
-               commit = preceeding_commit(crtc);
-               if (commit)
-                       drm_crtc_commit_get(commit);
-               spin_unlock(&crtc->commit_lock);
+       for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+               commit = old_crtc_state->commit;
  
                if (!commit)
                        continue;
                if (ret == 0)
                        DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
                                  crtc->base.id, crtc->name);
+       }
+       for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
+               commit = old_conn_state->commit;
  
-               drm_crtc_commit_put(commit);
+               if (!commit)
+                       continue;
+               ret = wait_for_completion_timeout(&commit->hw_done,
+                                                 10*HZ);
+               if (ret == 0)
+                       DRM_ERROR("[CONNECTOR:%d:%s] hw_done timed out\n",
+                                 conn->base.id, conn->name);
+               /* Currently no support for overwriting flips, hence
+                * stall for previous one to execute completely. */
+               ret = wait_for_completion_timeout(&commit->flip_done,
+                                                 10*HZ);
+               if (ret == 0)
+                       DRM_ERROR("[CONNECTOR:%d:%s] flip_done timed out\n",
+                                 conn->base.id, conn->name);
+       }
+       for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
+               commit = old_plane_state->commit;
+               if (!commit)
+                       continue;
+               ret = wait_for_completion_timeout(&commit->hw_done,
+                                                 10*HZ);
+               if (ret == 0)
+                       DRM_ERROR("[PLANE:%d:%s] hw_done timed out\n",
+                                 plane->base.id, plane->name);
+               /* Currently no support for overwriting flips, hence
+                * stall for previous one to execute completely. */
+               ret = wait_for_completion_timeout(&commit->flip_done,
+                                                 10*HZ);
+               if (ret == 0)
+                       DRM_ERROR("[PLANE:%d:%s] flip_done timed out\n",
+                                 plane->base.id, plane->name);
        }
  }
  EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
  void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
  {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *new_crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_crtc_commit *commit;
        int i;
  
-       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-               commit = old_state->crtcs[i].commit;
+       for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
+               commit = new_crtc_state->commit;
                if (!commit)
                        continue;
  
+               /*
+                * copy new_crtc_state->commit to old_crtc_state->commit,
+                * it's unsafe to touch new_crtc_state after hw_done,
+                * but we still need to do so in cleanup_done().
+                */
+               if (old_crtc_state->commit)
+                       drm_crtc_commit_put(old_crtc_state->commit);
+               old_crtc_state->commit = drm_crtc_commit_get(commit);
                /* backend must have consumed any event by now */
                WARN_ON(new_crtc_state->event);
                complete_all(&commit->hw_done);
        }
+       if (old_state->fake_commit) {
+               complete_all(&old_state->fake_commit->hw_done);
+               complete_all(&old_state->fake_commit->flip_done);
+       }
  }
  EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
  
  void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
  {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *new_crtc_state;
+       struct drm_crtc_state *old_crtc_state;
        struct drm_crtc_commit *commit;
        int i;
-       long ret;
  
-       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-               commit = old_state->crtcs[i].commit;
+       for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+               commit = old_crtc_state->commit;
                if (WARN_ON(!commit))
                        continue;
  
                complete_all(&commit->cleanup_done);
                WARN_ON(!try_wait_for_completion(&commit->hw_done));
  
-               /* commit_list borrows our reference, need to remove before we
-                * clean up our drm_atomic_state. But only after it actually
-                * completed, otherwise subsequent commits won't stall properly. */
-               if (try_wait_for_completion(&commit->flip_done))
-                       goto del_commit;
-               /* We must wait for the vblank event to signal our completion
-                * before releasing our reference, since the vblank work does
-                * not hold a reference of its own. */
-               ret = wait_for_completion_timeout(&commit->flip_done,
-                                                 10*HZ);
-               if (ret == 0)
-                       DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
-                                 crtc->base.id, crtc->name);
- del_commit:
                spin_lock(&crtc->commit_lock);
                list_del(&commit->commit_entry);
                spin_unlock(&crtc->commit_lock);
        }
+       if (old_state->fake_commit)
+               complete_all(&old_state->fake_commit->cleanup_done);
  }
  EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done);
  
@@@ -2294,20 -2362,44 +2362,44 @@@ int drm_atomic_helper_swap_state(struc
        struct drm_private_state *old_obj_state, *new_obj_state;
  
        if (stall) {
-               for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-                       spin_lock(&crtc->commit_lock);
-                       commit = list_first_entry_or_null(&crtc->commit_list,
-                                       struct drm_crtc_commit, commit_entry);
-                       if (commit)
-                               drm_crtc_commit_get(commit);
-                       spin_unlock(&crtc->commit_lock);
+               /*
+                * We have to stall for hw_done here before
+                * drm_atomic_helper_wait_for_dependencies() because flip
+                * depth > 1 is not yet supported by all drivers. As long as
+                * obj->state is directly dereferenced anywhere in the drivers
+                * atomic_commit_tail function, then it's unsafe to swap state
+                * before drm_atomic_helper_commit_hw_done() is called.
+                */
+               for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
+                       commit = old_crtc_state->commit;
+                       if (!commit)
+                               continue;
+                       ret = wait_for_completion_interruptible(&commit->hw_done);
+                       if (ret)
+                               return ret;
+               }
+               for_each_old_connector_in_state(state, connector, old_conn_state, i) {
+                       commit = old_conn_state->commit;
  
                        if (!commit)
                                continue;
  
                        ret = wait_for_completion_interruptible(&commit->hw_done);
-                       drm_crtc_commit_put(commit);
+                       if (ret)
+                               return ret;
+               }
  
+               for_each_old_plane_in_state(state, plane, old_plane_state, i) {
+                       commit = old_plane_state->commit;
+                       if (!commit)
+                               continue;
+                       ret = wait_for_completion_interruptible(&commit->hw_done);
                        if (ret)
                                return ret;
                }
                state->crtcs[i].state = old_crtc_state;
                crtc->state = new_crtc_state;
  
-               if (state->crtcs[i].commit) {
+               if (new_crtc_state->commit) {
                        spin_lock(&crtc->commit_lock);
-                       list_add(&state->crtcs[i].commit->commit_entry,
+                       list_add(&new_crtc_state->commit->commit_entry,
                                 &crtc->commit_list);
                        spin_unlock(&crtc->commit_lock);
  
-                       state->crtcs[i].commit->event = NULL;
+                       new_crtc_state->commit->event = NULL;
                }
        }
  
@@@ -2716,7 -2808,6 +2808,7 @@@ int drm_atomic_helper_disable_all(struc
        struct drm_plane *plane;
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
 +      unsigned plane_mask = 0;
        int ret, i;
  
        state = drm_atomic_state_alloc(dev);
                        goto free;
  
                drm_atomic_set_fb_for_plane(plane_state, NULL);
 +              plane_mask |= BIT(drm_plane_index(plane));
 +              plane->old_fb = plane->fb;
        }
  
        ret = drm_atomic_commit(state);
  free:
 +      if (plane_mask)
 +              drm_atomic_clean_old_fb(dev, plane_mask, ret);
        drm_atomic_state_put(state);
        return ret;
  }
@@@ -2897,16 -2984,11 +2989,16 @@@ int drm_atomic_helper_commit_duplicated
        struct drm_connector_state *new_conn_state;
        struct drm_crtc *crtc;
        struct drm_crtc_state *new_crtc_state;
 +      unsigned plane_mask = 0;
 +      struct drm_device *dev = state->dev;
 +      int ret;
  
        state->acquire_ctx = ctx;
  
 -      for_each_new_plane_in_state(state, plane, new_plane_state, i)
 +      for_each_new_plane_in_state(state, plane, new_plane_state, i) {
 +              plane_mask |= BIT(drm_plane_index(plane));
                state->planes[i].old_state = plane->state;
 +      }
  
        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
                state->crtcs[i].old_state = crtc->state;
        for_each_new_connector_in_state(state, connector, new_conn_state, i)
                state->connectors[i].old_state = connector->state;
  
 -      return drm_atomic_commit(state);
 +      ret = drm_atomic_commit(state);
 +      if (plane_mask)
 +              drm_atomic_clean_old_fb(dev, plane_mask, ret);
 +
 +      return ret;
  }
  EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
  
@@@ -3186,6 -3264,7 +3278,7 @@@ void __drm_atomic_helper_crtc_duplicate
        state->connectors_changed = false;
        state->color_mgmt_changed = false;
        state->zpos_changed = false;
+       state->commit = NULL;
        state->event = NULL;
        state->pageflip_flags = 0;
  }
@@@ -3224,6 -3303,12 +3317,12 @@@ EXPORT_SYMBOL(drm_atomic_helper_crtc_du
   */
  void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
  {
+       if (state->commit) {
+               kfree(state->commit->event);
+               state->commit->event = NULL;
+               drm_crtc_commit_put(state->commit);
+       }
        drm_property_blob_put(state->mode_blob);
        drm_property_blob_put(state->degamma_lut);
        drm_property_blob_put(state->ctm);
@@@ -3286,6 -3371,7 +3385,7 @@@ void __drm_atomic_helper_plane_duplicat
                drm_framebuffer_get(state->fb);
  
        state->fence = NULL;
+       state->commit = NULL;
  }
  EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
  
@@@ -3327,6 -3413,9 +3427,9 @@@ void __drm_atomic_helper_plane_destroy_
  
        if (state->fence)
                dma_fence_put(state->fence);
+       if (state->commit)
+               drm_crtc_commit_put(state->commit);
  }
  EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
  
@@@ -3405,6 -3494,7 +3508,7 @@@ __drm_atomic_helper_connector_duplicate
        memcpy(state, connector->state, sizeof(*state));
        if (state->crtc)
                drm_connector_get(connector);
+       state->commit = NULL;
  }
  EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
  
@@@ -3531,6 -3621,9 +3635,9 @@@ __drm_atomic_helper_connector_destroy_s
  {
        if (state->crtc)
                drm_connector_put(state->connector);
+       if (state->commit)
+               drm_crtc_commit_put(state->commit);
  }
  EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
  
index c55f338e380b9d0d86da89012cd9109689ff6bd2,8bea0326e7a79a76ef4677ae23174cbebe693280..7199bba68c379385a2a3fb2b9fd47f853a1f9c76
@@@ -36,7 -36,6 +36,7 @@@
  #include <linux/pagemap.h>
  #include <linux/shmem_fs.h>
  #include <linux/dma-buf.h>
 +#include <linux/mem_encrypt.h>
  #include <drm/drmP.h>
  #include <drm/drm_vma_manager.h>
  #include <drm/drm_gem.h>
@@@ -334,6 -333,12 +334,12 @@@ int drm_gem_dumb_map_offset(struct drm_
        if (!obj)
                return -ENOENT;
  
+       /* Don't allow imported objects to be mapped */
+       if (obj->import_attach) {
+               ret = -EINVAL;
+               goto out;
+       }
        ret = drm_gem_create_mmap_offset(obj);
        if (ret)
                goto out;
@@@ -966,7 -971,6 +972,7 @@@ int drm_gem_mmap_obj(struct drm_gem_obj
        vma->vm_ops = dev->driver->gem_vm_ops;
        vma->vm_private_data = obj;
        vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
 +      vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
  
        /* Take a ref for this mapping of the object, so that the fault
         * handler can dereference the mmap offset's pointer to the object.
index 7a00351d5b5def435de5c55c40bb659da31ab8ca,5d1c4f452ca83a463884893a964d72e2b59fd044..72cba9805edcd939071a43952cfc49a546aed945
@@@ -667,7 -667,7 +667,7 @@@ static int setplane_internal(struct drm
        struct drm_modeset_acquire_ctx ctx;
        int ret;
  
-       drm_modeset_acquire_init(&ctx, 0);
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
  retry:
        ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
        if (ret)
  
  fail:
        if (ret == -EDEADLK) {
-               drm_modeset_backoff(&ctx);
-               goto retry;
+               ret = drm_modeset_backoff(&ctx);
+               if (!ret)
+                       goto retry;
        }
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
@@@ -719,7 -720,6 +720,7 @@@ int drm_mode_setplane(struct drm_devic
  
                crtc = drm_crtc_find(dev, plane_req->crtc_id);
                if (!crtc) {
 +                      drm_framebuffer_put(fb);
                        DRM_DEBUG_KMS("Unknown crtc ID %d\n",
                                      plane_req->crtc_id);
                        return -ENOENT;
@@@ -834,7 -834,7 +835,7 @@@ static int drm_mode_cursor_common(struc
                return -ENOENT;
        }
  
-       drm_modeset_acquire_init(&ctx, 0);
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
  retry:
        ret = drm_modeset_lock(&crtc->mutex, &ctx);
        if (ret)
        }
  out:
        if (ret == -EDEADLK) {
-               drm_modeset_backoff(&ctx);
-               goto retry;
+               ret = drm_modeset_backoff(&ctx);
+               if (!ret)
+                       goto retry;
        }
  
        drm_modeset_drop_locks(&ctx);
@@@ -985,7 -986,7 +987,7 @@@ int drm_mode_page_flip_ioctl(struct drm
                return -EINVAL;
        }
  
-       drm_modeset_acquire_init(&ctx, 0);
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
  retry:
        ret = drm_modeset_lock(&crtc->mutex, &ctx);
        if (ret)
@@@ -1074,8 -1075,9 +1076,9 @@@ out
        crtc->primary->old_fb = NULL;
  
        if (ret == -EDEADLK) {
-               drm_modeset_backoff(&ctx);
-               goto retry;
+               ret = drm_modeset_backoff(&ctx);
+               if (!ret)
+                       goto retry;
        }
  
        drm_modeset_drop_locks(&ctx);
index 935653eb3616c997064fb166cb0d1ce8e839e4b7,5b89a5c6114ff8cc204c7fb25a8203b45db9879c..657ea5ab6c3f896821672b3568e5808d39987f0b
@@@ -102,7 -102,7 +102,7 @@@ ssize_t drm_scdc_write(struct i2c_adapt
        void *data;
        int err;
  
 -      data = kmalloc(1 + size, GFP_TEMPORARY);
 +      data = kmalloc(1 + size, GFP_KERNEL);
        if (!data)
                return -ENOMEM;
  
@@@ -134,7 -134,6 +134,6 @@@ EXPORT_SYMBOL(drm_scdc_write)
   * Returns:
   * True if the scrambling is enabled, false otherwise.
   */
  bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter)
  {
        u8 status;
  
        ret = drm_scdc_readb(adapter, SCDC_SCRAMBLER_STATUS, &status);
        if (ret < 0) {
-               DRM_ERROR("Failed to read scrambling status, error %d\n", ret);
+               DRM_ERROR("Failed to read scrambling status: %d\n", ret);
                return false;
        }
  
@@@ -162,7 -161,6 +161,6 @@@ EXPORT_SYMBOL(drm_scdc_get_scrambling_s
   * Returns:
   * True if scrambling is set/reset successfully, false otherwise.
   */
  bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable)
  {
        u8 config;
  
        ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
        if (ret < 0) {
-               DRM_ERROR("Failed to read tmds config, err=%d\n", ret);
+               DRM_ERROR("Failed to read TMDS config: %d\n", ret);
                return false;
        }
  
  
        ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config);
        if (ret < 0) {
-               DRM_ERROR("Failed to enable scrambling, error %d\n", ret);
+               DRM_ERROR("Failed to enable scrambling: %d\n", ret);
                return false;
        }
  
@@@ -225,7 -223,7 +223,7 @@@ bool drm_scdc_set_high_tmds_clock_ratio
  
        ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
        if (ret < 0) {
-               DRM_ERROR("Failed to read tmds config, err=%d\n", ret);
+               DRM_ERROR("Failed to read TMDS config: %d\n", ret);
                return false;
        }
  
  
        ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config);
        if (ret < 0) {
-               DRM_ERROR("Failed to set TMDS clock ratio, error %d\n", ret);
+               DRM_ERROR("Failed to set TMDS clock ratio: %d\n", ret);
                return false;
        }
  
index 0422b8c2c2e7392c24107cd9d07b771b25722065,3db042501a3aa1029b79e6322dee3ba8729389cd..26d60615b4d422b56899dea572cfd811bb2394a1
@@@ -1,7 -1,5 +1,7 @@@
  /*
   * Copyright 2017 Red Hat
 + * Parts ported from amdgpu (fence wait code).
 + * Copyright 2016 Advanced Micro Devices, Inc.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
@@@ -33,9 -31,6 +33,9 @@@
   * that contain an optional fence. The fence can be updated with a new
   * fence, or be NULL.
   *
 + * syncobj's can be waited upon, where it will wait for the underlying
 + * fence.
 + *
   * syncobj's can be export to fd's and back, these fd's are opaque and
   * have no other use case, except passing the syncobj between processes.
   *
@@@ -51,7 -46,6 +51,7 @@@
  #include <linux/fs.h>
  #include <linux/anon_inodes.h>
  #include <linux/sync_file.h>
 +#include <linux/sched/signal.h>
  
  #include "drm_internal.h"
  #include <drm/drm_syncobj.h>
@@@ -81,75 -75,6 +81,75 @@@ struct drm_syncobj *drm_syncobj_find(st
  }
  EXPORT_SYMBOL(drm_syncobj_find);
  
 +static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj,
 +                                          struct drm_syncobj_cb *cb,
 +                                          drm_syncobj_func_t func)
 +{
 +      cb->func = func;
 +      list_add_tail(&cb->node, &syncobj->cb_list);
 +}
 +
 +static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
 +                                               struct dma_fence **fence,
 +                                               struct drm_syncobj_cb *cb,
 +                                               drm_syncobj_func_t func)
 +{
 +      int ret;
 +
 +      *fence = drm_syncobj_fence_get(syncobj);
 +      if (*fence)
 +              return 1;
 +
 +      spin_lock(&syncobj->lock);
 +      /* We've already tried once to get a fence and failed.  Now that we
 +       * have the lock, try one more time just to be sure we don't add a
 +       * callback when a fence has already been set.
 +       */
 +      if (syncobj->fence) {
 +              *fence = dma_fence_get(syncobj->fence);
 +              ret = 1;
 +      } else {
 +              *fence = NULL;
 +              drm_syncobj_add_callback_locked(syncobj, cb, func);
 +              ret = 0;
 +      }
 +      spin_unlock(&syncobj->lock);
 +
 +      return ret;
 +}
 +
 +/**
 + * drm_syncobj_add_callback - adds a callback to syncobj::cb_list
 + * @syncobj: Sync object to which to add the callback
 + * @cb: Callback to add
 + * @func: Func to use when initializing the drm_syncobj_cb struct
 + *
 + * This adds a callback to be called next time the fence is replaced
 + */
 +void drm_syncobj_add_callback(struct drm_syncobj *syncobj,
 +                            struct drm_syncobj_cb *cb,
 +                            drm_syncobj_func_t func)
 +{
 +      spin_lock(&syncobj->lock);
 +      drm_syncobj_add_callback_locked(syncobj, cb, func);
 +      spin_unlock(&syncobj->lock);
 +}
 +EXPORT_SYMBOL(drm_syncobj_add_callback);
 +
 +/**
 + * drm_syncobj_add_callback - removes a callback to syncobj::cb_list
 + * @syncobj: Sync object from which to remove the callback
 + * @cb: Callback to remove
 + */
 +void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
 +                               struct drm_syncobj_cb *cb)
 +{
 +      spin_lock(&syncobj->lock);
 +      list_del_init(&cb->node);
 +      spin_unlock(&syncobj->lock);
 +}
 +EXPORT_SYMBOL(drm_syncobj_remove_callback);
 +
  /**
   * drm_syncobj_replace_fence - replace fence in a sync object.
   * @syncobj: Sync object to replace fence in
@@@ -161,75 -86,18 +161,75 @@@ void drm_syncobj_replace_fence(struct d
                               struct dma_fence *fence)
  {
        struct dma_fence *old_fence;
 +      struct drm_syncobj_cb *cur, *tmp;
  
        if (fence)
                dma_fence_get(fence);
 -      old_fence = xchg(&syncobj->fence, fence);
 +
 +      spin_lock(&syncobj->lock);
 +
 +      old_fence = syncobj->fence;
 +      syncobj->fence = fence;
 +
 +      if (fence != old_fence) {
 +              list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
 +                      list_del_init(&cur->node);
 +                      cur->func(syncobj, cur);
 +              }
 +      }
 +
 +      spin_unlock(&syncobj->lock);
  
        dma_fence_put(old_fence);
  }
  EXPORT_SYMBOL(drm_syncobj_replace_fence);
  
 -int drm_syncobj_fence_get(struct drm_file *file_private,
 -                        u32 handle,
 -                        struct dma_fence **fence)
 +struct drm_syncobj_null_fence {
 +      struct dma_fence base;
 +      spinlock_t lock;
 +};
 +
 +static const char *drm_syncobj_null_fence_get_name(struct dma_fence *fence)
 +{
 +        return "syncobjnull";
 +}
 +
 +static bool drm_syncobj_null_fence_enable_signaling(struct dma_fence *fence)
 +{
 +    dma_fence_enable_sw_signaling(fence);
 +    return !dma_fence_is_signaled(fence);
 +}
 +
 +static const struct dma_fence_ops drm_syncobj_null_fence_ops = {
 +      .get_driver_name = drm_syncobj_null_fence_get_name,
 +      .get_timeline_name = drm_syncobj_null_fence_get_name,
 +      .enable_signaling = drm_syncobj_null_fence_enable_signaling,
 +      .wait = dma_fence_default_wait,
 +      .release = NULL,
 +};
 +
 +static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
 +{
 +      struct drm_syncobj_null_fence *fence;
 +      fence = kzalloc(sizeof(*fence), GFP_KERNEL);
 +      if (fence == NULL)
 +              return -ENOMEM;
 +
 +      spin_lock_init(&fence->lock);
 +      dma_fence_init(&fence->base, &drm_syncobj_null_fence_ops,
 +                     &fence->lock, 0, 0);
 +      dma_fence_signal(&fence->base);
 +
 +      drm_syncobj_replace_fence(syncobj, &fence->base);
 +
 +      dma_fence_put(&fence->base);
 +
 +      return 0;
 +}
 +
 +int drm_syncobj_find_fence(struct drm_file *file_private,
 +                         u32 handle,
 +                         struct dma_fence **fence)
  {
        struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
        int ret = 0;
        if (!syncobj)
                return -ENOENT;
  
 -      *fence = dma_fence_get(syncobj->fence);
 +      *fence = drm_syncobj_fence_get(syncobj);
        if (!*fence) {
                ret = -EINVAL;
        }
        drm_syncobj_put(syncobj);
        return ret;
  }
 -EXPORT_SYMBOL(drm_syncobj_fence_get);
 +EXPORT_SYMBOL(drm_syncobj_find_fence);
  
  /**
   * drm_syncobj_free - free a sync object.
@@@ -257,13 -125,13 +257,13 @@@ void drm_syncobj_free(struct kref *kref
        struct drm_syncobj *syncobj = container_of(kref,
                                                   struct drm_syncobj,
                                                   refcount);
 -      dma_fence_put(syncobj->fence);
 +      drm_syncobj_replace_fence(syncobj, NULL);
        kfree(syncobj);
  }
  EXPORT_SYMBOL(drm_syncobj_free);
  
  static int drm_syncobj_create(struct drm_file *file_private,
 -                            u32 *handle)
 +                            u32 *handle, uint32_t flags)
  {
        int ret;
        struct drm_syncobj *syncobj;
                return -ENOMEM;
  
        kref_init(&syncobj->refcount);
 +      INIT_LIST_HEAD(&syncobj->cb_list);
 +      spin_lock_init(&syncobj->lock);
 +
 +      if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) {
 +              ret = drm_syncobj_assign_null_handle(syncobj);
 +              if (ret < 0) {
 +                      drm_syncobj_put(syncobj);
 +                      return ret;
 +              }
 +      }
  
        idr_preload(GFP_KERNEL);
        spin_lock(&file_private->syncobj_table_lock);
@@@ -417,8 -275,8 +417,8 @@@ static int drm_syncobj_fd_to_handle(str
        return 0;
  }
  
- int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
-                                      int fd, int handle)
static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
+                                             int fd, int handle)
  {
        struct dma_fence *fence = sync_file_get_fence(fd);
        struct drm_syncobj *syncobj;
        return 0;
  }
  
- int drm_syncobj_export_sync_file(struct drm_file *file_private,
-                                int handle, int *p_fd)
static int drm_syncobj_export_sync_file(struct drm_file *file_private,
+                                       int handle, int *p_fd)
  {
        int ret;
        struct dma_fence *fence;
        if (fd < 0)
                return fd;
  
 -      ret = drm_syncobj_fence_get(file_private, handle, &fence);
 +      ret = drm_syncobj_find_fence(file_private, handle, &fence);
        if (ret)
                goto err_put_fd;
  
@@@ -519,11 -377,11 +519,11 @@@ drm_syncobj_create_ioctl(struct drm_dev
                return -ENODEV;
  
        /* no valid flags yet */
 -      if (args->flags)
 +      if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED)
                return -EINVAL;
  
        return drm_syncobj_create(file_private,
 -                                &args->handle);
 +                                &args->handle, args->flags);
  }
  
  int
@@@ -589,368 -447,3 +589,368 @@@ drm_syncobj_fd_to_handle_ioctl(struct d
        return drm_syncobj_fd_to_handle(file_private, args->fd,
                                        &args->handle);
  }
 +
 +struct syncobj_wait_entry {
 +      struct task_struct *task;
 +      struct dma_fence *fence;
 +      struct dma_fence_cb fence_cb;
 +      struct drm_syncobj_cb syncobj_cb;
 +};
 +
 +static void syncobj_wait_fence_func(struct dma_fence *fence,
 +                                  struct dma_fence_cb *cb)
 +{
 +      struct syncobj_wait_entry *wait =
 +              container_of(cb, struct syncobj_wait_entry, fence_cb);
 +
 +      wake_up_process(wait->task);
 +}
 +
 +static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
 +                                    struct drm_syncobj_cb *cb)
 +{
 +      struct syncobj_wait_entry *wait =
 +              container_of(cb, struct syncobj_wait_entry, syncobj_cb);
 +
 +      /* This happens inside the syncobj lock */
 +      wait->fence = dma_fence_get(syncobj->fence);
 +      wake_up_process(wait->task);
 +}
 +
 +static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 +                                                uint32_t count,
 +                                                uint32_t flags,
 +                                                signed long timeout,
 +                                                uint32_t *idx)
 +{
 +      struct syncobj_wait_entry *entries;
 +      struct dma_fence *fence;
 +      signed long ret;
 +      uint32_t signaled_count, i;
 +
 +      entries = kcalloc(count, sizeof(*entries), GFP_KERNEL);
 +      if (!entries)
 +              return -ENOMEM;
 +
 +      /* Walk the list of sync objects and initialize entries.  We do
 +       * this up-front so that we can properly return -EINVAL if there is
 +       * a syncobj with a missing fence and then never have the chance of
 +       * returning -EINVAL again.
 +       */
 +      signaled_count = 0;
 +      for (i = 0; i < count; ++i) {
 +              entries[i].task = current;
 +              entries[i].fence = drm_syncobj_fence_get(syncobjs[i]);
 +              if (!entries[i].fence) {
 +                      if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
 +                              continue;
 +                      } else {
 +                              ret = -EINVAL;
 +                              goto cleanup_entries;
 +                      }
 +              }
 +
 +              if (dma_fence_is_signaled(entries[i].fence)) {
 +                      if (signaled_count == 0 && idx)
 +                              *idx = i;
 +                      signaled_count++;
 +              }
 +      }
 +
 +      /* Initialize ret to the max of timeout and 1.  That way, the
 +       * default return value indicates a successful wait and not a
 +       * timeout.
 +       */
 +      ret = max_t(signed long, timeout, 1);
 +
 +      if (signaled_count == count ||
 +          (signaled_count > 0 &&
 +           !(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL)))
 +              goto cleanup_entries;
 +
 +      /* There's a very annoying laxness in the dma_fence API here, in
 +       * that backends are not required to automatically report when a
 +       * fence is signaled prior to fence->ops->enable_signaling() being
 +       * called.  So here if we fail to match signaled_count, we need to
 +       * fallthough and try a 0 timeout wait!
 +       */
 +
 +      if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
 +              for (i = 0; i < count; ++i) {
 +                      drm_syncobj_fence_get_or_add_callback(syncobjs[i],
 +                                                            &entries[i].fence,
 +                                                            &entries[i].syncobj_cb,
 +                                                            syncobj_wait_syncobj_func);
 +              }
 +      }
 +
 +      do {
 +              set_current_state(TASK_INTERRUPTIBLE);
 +
 +              signaled_count = 0;
 +              for (i = 0; i < count; ++i) {
 +                      fence = entries[i].fence;
 +                      if (!fence)
 +                              continue;
 +
 +                      if (dma_fence_is_signaled(fence) ||
 +                          (!entries[i].fence_cb.func &&
 +                           dma_fence_add_callback(fence,
 +                                                  &entries[i].fence_cb,
 +                                                  syncobj_wait_fence_func))) {
 +                              /* The fence has been signaled */
 +                              if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) {
 +                                      signaled_count++;
 +                              } else {
 +                                      if (idx)
 +                                              *idx = i;
 +                                      goto done_waiting;
 +                              }
 +                      }
 +              }
 +
 +              if (signaled_count == count)
 +                      goto done_waiting;
 +
 +              if (timeout == 0) {
 +                      /* If we are doing a 0 timeout wait and we got
 +                       * here, then we just timed out.
 +                       */
 +                      ret = 0;
 +                      goto done_waiting;
 +              }
 +
 +              ret = schedule_timeout(ret);
 +
 +              if (ret > 0 && signal_pending(current))
 +                      ret = -ERESTARTSYS;
 +      } while (ret > 0);
 +
 +done_waiting:
 +      __set_current_state(TASK_RUNNING);
 +
 +cleanup_entries:
 +      for (i = 0; i < count; ++i) {
 +              if (entries[i].syncobj_cb.func)
 +                      drm_syncobj_remove_callback(syncobjs[i],
 +                                                  &entries[i].syncobj_cb);
 +              if (entries[i].fence_cb.func)
 +                      dma_fence_remove_callback(entries[i].fence,
 +                                                &entries[i].fence_cb);
 +              dma_fence_put(entries[i].fence);
 +      }
 +      kfree(entries);
 +
 +      return ret;
 +}
 +
 +/**
 + * drm_timeout_abs_to_jiffies - calculate jiffies timeout from absolute value
 + *
 + * @timeout_nsec: timeout nsec component in ns, 0 for poll
 + *
 + * Calculate the timeout in jiffies from an absolute time in sec/nsec.
 + */
 +static signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec)
 +{
 +      ktime_t abs_timeout, now;
 +      u64 timeout_ns, timeout_jiffies64;
 +
 +      /* make 0 timeout means poll - absolute 0 doesn't seem valid */
 +      if (timeout_nsec == 0)
 +              return 0;
 +
 +      abs_timeout = ns_to_ktime(timeout_nsec);
 +      now = ktime_get();
 +
 +      if (!ktime_after(abs_timeout, now))
 +              return 0;
 +
 +      timeout_ns = ktime_to_ns(ktime_sub(abs_timeout, now));
 +
 +      timeout_jiffies64 = nsecs_to_jiffies64(timeout_ns);
 +      /*  clamp timeout to avoid infinite timeout */
 +      if (timeout_jiffies64 >= MAX_SCHEDULE_TIMEOUT - 1)
 +              return MAX_SCHEDULE_TIMEOUT - 1;
 +
 +      return timeout_jiffies64 + 1;
 +}
 +
 +static int drm_syncobj_array_wait(struct drm_device *dev,
 +                                struct drm_file *file_private,
 +                                struct drm_syncobj_wait *wait,
 +                                struct drm_syncobj **syncobjs)
 +{
 +      signed long timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec);
 +      signed long ret = 0;
 +      uint32_t first = ~0;
 +
 +      ret = drm_syncobj_array_wait_timeout(syncobjs,
 +                                           wait->count_handles,
 +                                           wait->flags,
 +                                           timeout, &first);
 +      if (ret < 0)
 +              return ret;
 +
 +      wait->first_signaled = first;
 +      if (ret == 0)
 +              return -ETIME;
 +      return 0;
 +}
 +
 +static int drm_syncobj_array_find(struct drm_file *file_private,
 +                                void *user_handles, uint32_t count_handles,
 +                                struct drm_syncobj ***syncobjs_out)
 +{
 +      uint32_t i, *handles;
 +      struct drm_syncobj **syncobjs;
 +      int ret;
 +
 +      handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
 +      if (handles == NULL)
 +              return -ENOMEM;
 +
 +      if (copy_from_user(handles, user_handles,
 +                         sizeof(uint32_t) * count_handles)) {
 +              ret = -EFAULT;
 +              goto err_free_handles;
 +      }
 +
 +      syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs), GFP_KERNEL);
 +      if (syncobjs == NULL) {
 +              ret = -ENOMEM;
 +              goto err_free_handles;
 +      }
 +
 +      for (i = 0; i < count_handles; i++) {
 +              syncobjs[i] = drm_syncobj_find(file_private, handles[i]);
 +              if (!syncobjs[i]) {
 +                      ret = -ENOENT;
 +                      goto err_put_syncobjs;
 +              }
 +      }
 +
 +      kfree(handles);
 +      *syncobjs_out = syncobjs;
 +      return 0;
 +
 +err_put_syncobjs:
 +      while (i-- > 0)
 +              drm_syncobj_put(syncobjs[i]);
 +      kfree(syncobjs);
 +err_free_handles:
 +      kfree(handles);
 +
 +      return ret;
 +}
 +
 +static void drm_syncobj_array_free(struct drm_syncobj **syncobjs,
 +                                 uint32_t count)
 +{
 +      uint32_t i;
 +      for (i = 0; i < count; i++)
 +              drm_syncobj_put(syncobjs[i]);
 +      kfree(syncobjs);
 +}
 +
 +int
 +drm_syncobj_wait_ioctl(struct drm_device *dev, void *data,
 +                     struct drm_file *file_private)
 +{
 +      struct drm_syncobj_wait *args = data;
 +      struct drm_syncobj **syncobjs;
 +      int ret = 0;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
 +              return -ENODEV;
 +
 +      if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
 +                          DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
 +              return -EINVAL;
 +
 +      if (args->count_handles == 0)
 +              return -EINVAL;
 +
 +      ret = drm_syncobj_array_find(file_private,
 +                                   u64_to_user_ptr(args->handles),
 +                                   args->count_handles,
 +                                   &syncobjs);
 +      if (ret < 0)
 +              return ret;
 +
 +      ret = drm_syncobj_array_wait(dev, file_private,
 +                                   args, syncobjs);
 +
 +      drm_syncobj_array_free(syncobjs, args->count_handles);
 +
 +      return ret;
 +}
 +
 +int
 +drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
 +                      struct drm_file *file_private)
 +{
 +      struct drm_syncobj_array *args = data;
 +      struct drm_syncobj **syncobjs;
 +      uint32_t i;
 +      int ret;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
 +              return -ENODEV;
 +
 +      if (args->pad != 0)
 +              return -EINVAL;
 +
 +      if (args->count_handles == 0)
 +              return -EINVAL;
 +
 +      ret = drm_syncobj_array_find(file_private,
 +                                   u64_to_user_ptr(args->handles),
 +                                   args->count_handles,
 +                                   &syncobjs);
 +      if (ret < 0)
 +              return ret;
 +
 +      for (i = 0; i < args->count_handles; i++)
 +              drm_syncobj_replace_fence(syncobjs[i], NULL);
 +
 +      drm_syncobj_array_free(syncobjs, args->count_handles);
 +
 +      return 0;
 +}
 +
 +int
 +drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
 +                       struct drm_file *file_private)
 +{
 +      struct drm_syncobj_array *args = data;
 +      struct drm_syncobj **syncobjs;
 +      uint32_t i;
 +      int ret;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
 +              return -ENODEV;
 +
 +      if (args->pad != 0)
 +              return -EINVAL;
 +
 +      if (args->count_handles == 0)
 +              return -EINVAL;
 +
 +      ret = drm_syncobj_array_find(file_private,
 +                                   u64_to_user_ptr(args->handles),
 +                                   args->count_handles,
 +                                   &syncobjs);
 +      if (ret < 0)
 +              return ret;
 +
 +      for (i = 0; i < args->count_handles; i++) {
 +              ret = drm_syncobj_assign_null_handle(syncobjs[i]);
 +              if (ret < 0)
 +                      break;
 +      }
 +
 +      drm_syncobj_array_free(syncobjs, args->count_handles);
 +
 +      return ret;
 +}
index ba4a32b132baada502df485477d85281600b872f,ab333d5b27275cf24dad7bd8e3328a63292153de..2174814273e2071934c817e180848498627f6e14
  #include <linux/component.h>
  #include <linux/pm_runtime.h>
  #include <drm/drmP.h>
 +#include <drm/drm_encoder.h>
  #include <linux/mfd/syscon.h>
  #include <linux/regmap.h>
  
 +#include "exynos_drm_drv.h"
 +
  /* Sysreg registers for MIC */
  #define DSD_CFG_MUX   0x1004
  #define MIC0_RGB_MUX  (1 << 0)
  
  #define MIC_BS_SIZE_2D(x)     ((x) & 0x3fff)
  
 -enum {
 -      ENDPOINT_DECON_NODE,
 -      ENDPOINT_DSI_NODE,
 -      NUM_ENDPOINTS
 -};
 -
  static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" };
  #define NUM_CLKS              ARRAY_SIZE(clk_names)
  static DEFINE_MUTEX(mic_mutex);
@@@ -226,6 -229,36 +226,6 @@@ static void mic_set_reg_on(struct exyno
        writel(reg, mic->reg + MIC_OP);
  }
  
 -static int parse_dt(struct exynos_mic *mic)
 -{
 -      int ret = 0, i, j;
 -      struct device_node *remote_node;
 -      struct device_node *nodes[3];
 -
 -      /*
 -       * The order of endpoints does matter.
 -       * The first node must be for decon and the second one must be for dsi.
 -       */
 -      for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) {
 -              remote_node = of_graph_get_remote_node(mic->dev->of_node, i, 0);
 -              if (!remote_node) {
 -                      ret = -EPIPE;
 -                      goto exit;
 -              }
 -              nodes[j++] = remote_node;
 -
 -              if (i == ENDPOINT_DECON_NODE &&
 -                      of_get_child_by_name(remote_node, "i80-if-timings"))
 -                      mic->i80_mode = 1;
 -      }
 -
 -exit:
 -      while (--j > -1)
 -              of_node_put(nodes[j]);
 -
 -      return ret;
 -}
 -
  static void mic_disable(struct drm_bridge *bridge) { }
  
  static void mic_post_disable(struct drm_bridge *bridge)
@@@ -253,7 -286,6 +253,7 @@@ static void mic_mode_set(struct drm_bri
  
        mutex_lock(&mic_mutex);
        drm_display_mode_to_videomode(mode, &mic->vm);
 +      mic->i80_mode = to_exynos_crtc(bridge->encoder->crtc)->i80_mode;
        mutex_unlock(&mic_mutex);
  }
  
@@@ -385,6 -417,10 +385,6 @@@ static int exynos_mic_probe(struct plat
  
        mic->dev = dev;
  
 -      ret = parse_dt(mic);
 -      if (ret)
 -              goto err;
 -
        ret = of_address_to_resource(dev->of_node, 0, &res);
        if (ret) {
                DRM_ERROR("mic: Failed to get mem region for MIC\n");
        mic->bridge.funcs = &mic_bridge_funcs;
        mic->bridge.of_node = dev->of_node;
  
-       ret = drm_bridge_add(&mic->bridge);
-       if (ret) {
-               DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
-               return ret;
-       }
+       drm_bridge_add(&mic->bridge);
  
        pm_runtime_enable(dev);
  
index 18d9da53282b6701c922ebfe46b40e8832d149e1,6b4771adb8ba01ee8e32bccbb40f9bd2bf35561b..b6b175aa5d255db9b536ef68ca323655a8c739e0
@@@ -80,8 -80,8 +80,8 @@@
  
  #define DRIVER_NAME           "i915"
  #define DRIVER_DESC           "Intel Graphics"
 -#define DRIVER_DATE           "20170717"
 -#define DRIVER_TIMESTAMP      1500275179
 +#define DRIVER_DATE           "20170818"
 +#define DRIVER_TIMESTAMP      1503088845
  
  /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
   * WARN_ON()) for hw state sanity checks to check for unexpected conditions
@@@ -602,7 -602,7 +602,7 @@@ struct drm_i915_file_private 
   * to limit the badly behaving clients access to gpu.
   */
  #define I915_MAX_CLIENT_CONTEXT_BANS 3
 -      int context_bans;
 +      atomic_t context_bans;
  };
  
  /* Used by dp and fdi links */
@@@ -646,7 -646,6 +646,7 @@@ struct intel_opregion 
        u32 swsci_sbcb_sub_functions;
        struct opregion_asle *asle;
        void *rvda;
 +      void *vbt_firmware;
        const void *vbt;
        u32 vbt_size;
        u32 *lid_state;
@@@ -707,8 -706,7 +707,7 @@@ struct drm_i915_display_funcs 
                            struct drm_atomic_state *old_state);
        void (*crtc_disable)(struct intel_crtc_state *old_crtc_state,
                             struct drm_atomic_state *old_state);
-       void (*update_crtcs)(struct drm_atomic_state *state,
-                            unsigned int *crtc_vblank_mask);
+       void (*update_crtcs)(struct drm_atomic_state *state);
        void (*audio_codec_enable)(struct drm_connector *connector,
                                   struct intel_encoder *encoder,
                                   const struct drm_display_mode *adjusted_mode);
        void (*fdi_link_train)(struct intel_crtc *crtc,
                               const struct intel_crtc_state *crtc_state);
        void (*init_clock_gating)(struct drm_i915_private *dev_priv);
 -      int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
 -                        struct drm_framebuffer *fb,
 -                        struct drm_i915_gem_object *obj,
 -                        struct drm_i915_gem_request *req,
 -                        uint32_t flags);
        void (*hpd_irq_setup)(struct drm_i915_private *dev_priv);
        /* clock updates for mode set */
        /* cursor updates */
@@@ -1059,11 -1062,6 +1058,11 @@@ struct intel_fbc 
        bool underrun_detected;
        struct work_struct underrun_work;
  
 +      /*
 +       * Due to the atomic rules we can't access some structures without the
 +       * appropriate locking, so we cache information here in order to avoid
 +       * these problems.
 +       */
        struct intel_fbc_state_cache {
                struct i915_vma *vma;
  
                } fb;
        } state_cache;
  
 +      /*
 +       * This structure contains everything that's relevant to program the
 +       * hardware registers. When we want to figure out if we need to disable
 +       * and re-enable FBC for a new configuration we just check if there's
 +       * something different in the struct. The genx_fbc_activate functions
 +       * are supposed to read from it in order to program the registers.
 +       */
        struct intel_fbc_reg_params {
                struct i915_vma *vma;
  
@@@ -1167,8 -1158,8 +1166,8 @@@ enum intel_pch 
        PCH_CPT,        /* Cougarpoint/Pantherpoint PCH */
        PCH_LPT,        /* Lynxpoint/Wildcatpoint PCH */
        PCH_SPT,        /* Sunrisepoint PCH */
 -      PCH_KBP,        /* Kabypoint PCH */
 -      PCH_CNP,        /* Cannonpoint PCH */
 +      PCH_KBP,        /* Kaby Lake PCH */
 +      PCH_CNP,        /* Cannon Lake PCH */
        PCH_NOP,
  };
  
@@@ -1396,23 -1387,12 +1395,23 @@@ struct i915_power_well 
        bool hw_enabled;
        u64 domains;
        /* unique identifier for this power well */
 -      unsigned long id;
 +      enum i915_power_well_id id;
        /*
         * Arbitraty data associated with this power well. Platform and power
         * well specific.
         */
 -      unsigned long data;
 +      union {
 +              struct {
 +                      enum dpio_phy phy;
 +              } bxt;
 +              struct {
 +                      /* Mask of pipes whose IRQ logic is backed by the pw */
 +                      u8 irq_pipe_mask;
 +                      /* The pw is backing the VGA functionality */
 +                      bool has_vga:1;
 +                      bool has_fuses:1;
 +              } hsw;
 +      };
        const struct i915_power_well_ops *ops;
  };
  
@@@ -1529,8 -1509,6 +1528,8 @@@ struct i915_gpu_error 
        /* Protected by the above dev->gpu_error.lock. */
        struct i915_gpu_state *first_error;
  
 +      atomic_t pending_fb_pin;
 +
        unsigned long missed_irq_rings;
  
        /**
        unsigned long flags;
  #define I915_RESET_BACKOFF    0
  #define I915_RESET_HANDOFF    1
 +#define I915_RESET_MODESET    2
  #define I915_WEDGED           (BITS_PER_LONG - 1)
  #define I915_RESET_ENGINE     (I915_WEDGED - I915_NUM_ENGINES)
  
@@@ -1906,7 -1883,6 +1905,7 @@@ struct i915_workarounds 
  
  struct i915_virtual_gpu {
        bool active;
 +      u32 caps;
  };
  
  /* used in computing the new watermarks state */
@@@ -1926,24 -1902,6 +1925,24 @@@ struct i915_oa_reg 
        u32 value;
  };
  
 +struct i915_oa_config {
 +      char uuid[UUID_STRING_LEN + 1];
 +      int id;
 +
 +      const struct i915_oa_reg *mux_regs;
 +      u32 mux_regs_len;
 +      const struct i915_oa_reg *b_counter_regs;
 +      u32 b_counter_regs_len;
 +      const struct i915_oa_reg *flex_regs;
 +      u32 flex_regs_len;
 +
 +      struct attribute_group sysfs_metric;
 +      struct attribute *attrs[2];
 +      struct device_attribute sysfs_metric_id;
 +
 +      atomic_t ref_count;
 +};
 +
  struct i915_perf_stream;
  
  /**
@@@ -2056,36 -2014,12 +2055,36 @@@ struct i915_perf_stream 
         * type of configured stream.
         */
        const struct i915_perf_stream_ops *ops;
 +
 +      /**
 +       * @oa_config: The OA configuration used by the stream.
 +       */
 +      struct i915_oa_config *oa_config;
  };
  
  /**
   * struct i915_oa_ops - Gen specific implementation of an OA unit stream
   */
  struct i915_oa_ops {
 +      /**
 +       * @is_valid_b_counter_reg: Validates register's address for
 +       * programming boolean counters for a particular platform.
 +       */
 +      bool (*is_valid_b_counter_reg)(struct drm_i915_private *dev_priv,
 +                                     u32 addr);
 +
 +      /**
 +       * @is_valid_mux_reg: Validates register's address for programming mux
 +       * for a particular platform.
 +       */
 +      bool (*is_valid_mux_reg)(struct drm_i915_private *dev_priv, u32 addr);
 +
 +      /**
 +       * @is_valid_flex_reg: Validates register's address for programming
 +       * flex EU filtering for a particular platform.
 +       */
 +      bool (*is_valid_flex_reg)(struct drm_i915_private *dev_priv, u32 addr);
 +
        /**
         * @init_oa_buffer: Resets the head and tail pointers of the
         * circular buffer for periodic OA reports.
         */
        void (*init_oa_buffer)(struct drm_i915_private *dev_priv);
  
 -      /**
 -       * @select_metric_set: The auto generated code that checks whether a
 -       * requested OA config is applicable to the system and if so sets up
 -       * the mux, oa and flex eu register config pointers according to the
 -       * current dev_priv->perf.oa.metrics_set.
 -       */
 -      int (*select_metric_set)(struct drm_i915_private *dev_priv);
 -
        /**
         * @enable_metric_set: Selects and applies any MUX configuration to set
         * up the Boolean and Custom (B/C) counters that are part of the
         * counter reports being sampled. May apply system constraints such as
         * disabling EU clock gating as required.
         */
 -      int (*enable_metric_set)(struct drm_i915_private *dev_priv);
 +      int (*enable_metric_set)(struct drm_i915_private *dev_priv,
 +                               const struct i915_oa_config *oa_config);
  
        /**
         * @disable_metric_set: Remove system constraints associated with using
@@@ -2156,7 -2097,6 +2155,7 @@@ struct drm_i915_private 
  
        struct kmem_cache *objects;
        struct kmem_cache *vmas;
 +      struct kmem_cache *luts;
        struct kmem_cache *requests;
        struct kmem_cache *dependencies;
        struct kmem_cache *priorities;
        /* protects the irq masks */
        spinlock_t irq_lock;
  
 -      /* protects the mmio flip data */
 -      spinlock_t mmio_flip_lock;
 -
        bool display_irqs_enabled;
  
        /* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
  
        struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
        struct intel_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
 -      wait_queue_head_t pending_flip_queue;
  
  #ifdef CONFIG_DEBUG_FS
        struct intel_pipe_crc pipe_crc[I915_MAX_PIPES];
                struct kobject *metrics_kobj;
                struct ctl_table_header *sysctl_header;
  
 +              /*
 +               * Lock associated with adding/modifying/removing OA configs
 +               * in dev_priv->perf.metrics_idr.
 +               */
 +              struct mutex metrics_lock;
 +
 +              /*
 +               * List of dynamic configurations, you need to hold
 +               * dev_priv->perf.metrics_lock to access it.
 +               */
 +              struct idr metrics_idr;
 +
 +              /*
 +               * Lock associated with anything below within this structure
 +               * except exclusive_stream.
 +               */
                struct mutex lock;
                struct list_head streams;
  
                struct {
 +                      /*
 +                       * The stream currently using the OA unit. If accessed
 +                       * outside a syscall associated to its file
 +                       * descriptor, you need to hold
 +                       * dev_priv->drm.struct_mutex.
 +                       */
                        struct i915_perf_stream *exclusive_stream;
  
                        u32 specific_ctx_id;
                        int period_exponent;
                        int timestamp_frequency;
  
 -                      int metrics_set;
 -
 -                      const struct i915_oa_reg *mux_regs[6];
 -                      int mux_regs_lens[6];
 -                      int n_mux_configs;
 -
 -                      const struct i915_oa_reg *b_counter_regs;
 -                      int b_counter_regs_len;
 -                      const struct i915_oa_reg *flex_regs;
 -                      int flex_regs_len;
 +                      struct i915_oa_config test_config;
  
                        struct {
                                struct i915_vma *vma;
  
                        struct i915_oa_ops ops;
                        const struct i915_oa_format *oa_formats;
 -                      int n_builtin_sets;
                } oa;
        } perf;
  
@@@ -3175,12 -3107,8 +3174,12 @@@ extern int i915_driver_load(struct pci_
  extern void i915_driver_unload(struct drm_device *dev);
  extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
  extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
 -extern void i915_reset(struct drm_i915_private *dev_priv);
 -extern int i915_reset_engine(struct intel_engine_cs *engine);
 +
 +#define I915_RESET_QUIET BIT(0)
 +extern void i915_reset(struct drm_i915_private *i915, unsigned int flags);
 +extern int i915_reset_engine(struct intel_engine_cs *engine,
 +                           unsigned int flags);
 +
  extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv);
  extern int intel_guc_reset(struct drm_i915_private *dev_priv);
  extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
@@@ -3200,8 -3128,7 +3199,8 @@@ void intel_hpd_irq_handler(struct drm_i
  void intel_hpd_init(struct drm_i915_private *dev_priv);
  void intel_hpd_init_work(struct drm_i915_private *dev_priv);
  void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
 -bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port);
 +enum port intel_hpd_pin_to_port(enum hpd_pin pin);
 +enum hpd_pin intel_hpd_pin(enum port port);
  bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
  void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
  
@@@ -3370,26 -3297,6 +3369,26 @@@ static inline void i915_gem_drain_freed
        } while (flush_work(&i915->mm.free_work));
  }
  
 +static inline void i915_gem_drain_workqueue(struct drm_i915_private *i915)
 +{
 +      /*
 +       * Similar to objects above (see i915_gem_drain_freed-objects), in
 +       * general we have workers that are armed by RCU and then rearm
 +       * themselves in their callbacks. To be paranoid, we need to
 +       * drain the workqueue a second time after waiting for the RCU
 +       * grace period so that we catch work queued via RCU from the first
 +       * pass. As neither drain_workqueue() nor flush_workqueue() report
 +       * a result, we make an assumption that we only don't require more
 +       * than 2 passes to catch all recursive RCU delayed work.
 +       *
 +       */
 +      int pass = 2;
 +      do {
 +              rcu_barrier();
 +              drain_workqueue(i915->wq);
 +      } while (--pass);
 +}
 +
  struct i915_vma * __must_check
  i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
                         const struct i915_ggtt_view *view,
@@@ -3479,9 -3386,6 +3478,9 @@@ void __i915_gem_object_invalidate(struc
  enum i915_map_type {
        I915_MAP_WB = 0,
        I915_MAP_WC,
 +#define I915_MAP_OVERRIDE BIT(31)
 +      I915_MAP_FORCE_WB = I915_MAP_WB | I915_MAP_OVERRIDE,
 +      I915_MAP_FORCE_WC = I915_MAP_WC | I915_MAP_OVERRIDE,
  };
  
  /**
@@@ -3690,10 -3594,6 +3689,10 @@@ i915_gem_context_lookup_timeline(struc
  
  int i915_perf_open_ioctl(struct drm_device *dev, void *data,
                         struct drm_file *file);
 +int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
 +                             struct drm_file *file);
 +int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
 +                                struct drm_file *file);
  void i915_oa_init_reg_state(struct intel_engine_cs *engine,
                            struct i915_gem_context *ctx,
                            uint32_t *reg_state);
@@@ -3745,7 -3645,6 +3744,7 @@@ i915_gem_object_create_internal(struct 
  /* i915_gem_shrinker.c */
  unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
                              unsigned long target,
 +                            unsigned long *nr_scanned,
                              unsigned flags);
  #define I915_SHRINK_PURGEABLE 0x1
  #define I915_SHRINK_UNBOUND 0x2
@@@ -4182,11 -4081,6 +4181,11 @@@ static inline unsigned long msecs_to_ji
  
  static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
  {
 +      /* nsecs_to_jiffies64() does not guard against overflow */
 +      if (NSEC_PER_SEC % HZ &&
 +          div_u64(n, NSEC_PER_SEC) >= MAX_JIFFY_OFFSET / HZ)
 +              return MAX_JIFFY_OFFSET;
 +
          return min_t(u64, MAX_JIFFY_OFFSET, nsecs_to_jiffies64(n) + 1);
  }
  
@@@ -4333,11 -4227,10 +4332,11 @@@ int remap_io_mapping(struct vm_area_str
                     unsigned long addr, unsigned long pfn, unsigned long size,
                     struct io_mapping *iomap);
  
 -static inline bool i915_gem_object_is_coherent(struct drm_i915_gem_object *obj)
 +static inline bool
 +intel_engine_can_store_dword(struct intel_engine_cs *engine)
  {
 -      return (obj->cache_level != I915_CACHE_NONE ||
 -              HAS_LLC(to_i915(obj->base.dev)));
 +      return __intel_engine_can_store_dword(INTEL_GEN(engine->i915),
 +                                            engine->class);
  }
  
  #endif
index 00cd17c76fdcc3bc5427f53bf45e416d66400655,3f505682963fc15083ea724c25f9efab4b0c9e4a..4b34fa6954f9997b01aa5953171dbd7d0a49dde2
  #include <linux/dma_remapping.h>
  #include <linux/reservation.h>
  
 -static bool is_mmio_work(struct intel_flip_work *work)
 -{
 -      return work->mmio_work.func;
 -}
 -
  /* Primary plane formats for gen <= 3 */
  static const uint32_t i8xx_primary_formats[] = {
        DRM_FORMAT_C8,
@@@ -67,12 -72,6 +67,12 @@@ static const uint32_t i965_primary_form
        DRM_FORMAT_XBGR2101010,
  };
  
 +static const uint64_t i9xx_format_modifiers[] = {
 +      I915_FORMAT_MOD_X_TILED,
 +      DRM_FORMAT_MOD_LINEAR,
 +      DRM_FORMAT_MOD_INVALID
 +};
 +
  static const uint32_t skl_primary_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_VYUY,
  };
  
 +static const uint64_t skl_format_modifiers_noccs[] = {
 +      I915_FORMAT_MOD_Yf_TILED,
 +      I915_FORMAT_MOD_Y_TILED,
 +      I915_FORMAT_MOD_X_TILED,
 +      DRM_FORMAT_MOD_LINEAR,
 +      DRM_FORMAT_MOD_INVALID
 +};
 +
 +static const uint64_t skl_format_modifiers_ccs[] = {
 +      I915_FORMAT_MOD_Yf_TILED_CCS,
 +      I915_FORMAT_MOD_Y_TILED_CCS,
 +      I915_FORMAT_MOD_Yf_TILED,
 +      I915_FORMAT_MOD_Y_TILED,
 +      I915_FORMAT_MOD_X_TILED,
 +      DRM_FORMAT_MOD_LINEAR,
 +      DRM_FORMAT_MOD_INVALID
 +};
 +
  /* Cursor formats */
  static const uint32_t intel_cursor_formats[] = {
        DRM_FORMAT_ARGB8888,
  };
  
 +static const uint64_t cursor_format_modifiers[] = {
 +      DRM_FORMAT_MOD_LINEAR,
 +      DRM_FORMAT_MOD_INVALID
 +};
 +
  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                                struct intel_crtc_state *pipe_config);
  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
@@@ -1801,7 -1777,7 +1801,7 @@@ static void lpt_enable_pch_transcoder(s
  
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
 -      assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
 +      assert_fdi_rx_enabled(dev_priv, PIPE_A);
  
        /* Workaround: set timing override bit. */
        val = I915_READ(TRANS_CHICKEN2(PIPE_A));
@@@ -1877,16 -1853,16 +1877,16 @@@ void lpt_disable_pch_transcoder(struct 
        I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
  }
  
 -enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 +enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
  {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
  
        WARN_ON(!crtc->config->has_pch_encoder);
  
        if (HAS_PCH_LPT(dev_priv))
 -              return TRANSCODER_A;
 +              return PIPE_A;
        else
 -              return (enum transcoder) crtc->pipe;
 +              return crtc->pipe;
  }
  
  /**
@@@ -1925,7 -1901,7 +1925,7 @@@ static void intel_enable_pipe(struct in
                if (crtc->config->has_pch_encoder) {
                        /* if driving the PCH, we need FDI enabled */
                        assert_fdi_rx_pll_enabled(dev_priv,
 -                                                (enum pipe) intel_crtc_pch_transcoder(crtc));
 +                                                intel_crtc_pch_transcoder(crtc));
                        assert_fdi_tx_pll_enabled(dev_priv,
                                                  (enum pipe) cpu_transcoder);
                }
@@@ -2023,19 -1999,11 +2023,19 @@@ intel_tile_width_bytes(const struct drm
                        return 128;
                else
                        return 512;
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +              if (plane == 1)
 +                      return 128;
 +              /* fall through */
        case I915_FORMAT_MOD_Y_TILED:
                if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
                        return 128;
                else
                        return 512;
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
 +              if (plane == 1)
 +                      return 128;
 +              /* fall through */
        case I915_FORMAT_MOD_Yf_TILED:
                switch (cpp) {
                case 1:
@@@ -2142,7 -2110,7 +2142,7 @@@ static unsigned int intel_surf_alignmen
        struct drm_i915_private *dev_priv = to_i915(fb->dev);
  
        /* AUX_DIST needs only 4K alignment */
 -      if (fb->format->format == DRM_FORMAT_NV12 && plane == 1)
 +      if (plane == 1)
                return 4096;
  
        switch (fb->modifier) {
                if (INTEL_GEN(dev_priv) >= 9)
                        return 256 * 1024;
                return 0;
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
        case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
                return 1 * 1024 * 1024;
@@@ -2196,8 -2162,6 +2196,8 @@@ intel_pin_and_fence_fb_obj(struct drm_f
         */
        intel_runtime_pm_get(dev_priv);
  
 +      atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
 +
        vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
        if (IS_ERR(vma))
                goto err;
  
        i915_vma_get(vma);
  err:
 +      atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
 +
        intel_runtime_pm_put(dev_priv);
        return vma;
  }
@@@ -2288,13 -2250,17 +2288,13 @@@ void intel_add_fb_offsets(int *x, int *
        }
  }
  
 -/*
 - * Input tile dimensions and pitch must already be
 - * rotated to match x and y, and in pixel units.
 - */
 -static u32 _intel_adjust_tile_offset(int *x, int *y,
 -                                   unsigned int tile_width,
 -                                   unsigned int tile_height,
 -                                   unsigned int tile_size,
 -                                   unsigned int pitch_tiles,
 -                                   u32 old_offset,
 -                                   u32 new_offset)
 +static u32 __intel_adjust_tile_offset(int *x, int *y,
 +                                    unsigned int tile_width,
 +                                    unsigned int tile_height,
 +                                    unsigned int tile_size,
 +                                    unsigned int pitch_tiles,
 +                                    u32 old_offset,
 +                                    u32 new_offset)
  {
        unsigned int pitch_pixels = pitch_tiles * tile_width;
        unsigned int tiles;
        return new_offset;
  }
  
 -/*
 - * Adjust the tile offset by moving the difference into
 - * the x/y offsets.
 - */
 -static u32 intel_adjust_tile_offset(int *x, int *y,
 -                                  const struct intel_plane_state *state, int plane,
 -                                  u32 old_offset, u32 new_offset)
 +static u32 _intel_adjust_tile_offset(int *x, int *y,
 +                                   const struct drm_framebuffer *fb, int plane,
 +                                   unsigned int rotation,
 +                                   u32 old_offset, u32 new_offset)
  {
 -      const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
 -      const struct drm_framebuffer *fb = state->base.fb;
 +      const struct drm_i915_private *dev_priv = to_i915(fb->dev);
        unsigned int cpp = fb->format->cpp[plane];
 -      unsigned int rotation = state->base.rotation;
        unsigned int pitch = intel_fb_pitch(fb, plane, rotation);
  
        WARN_ON(new_offset > old_offset);
                        pitch_tiles = pitch / (tile_width * cpp);
                }
  
 -              _intel_adjust_tile_offset(x, y, tile_width, tile_height,
 -                                        tile_size, pitch_tiles,
 -                                        old_offset, new_offset);
 +              __intel_adjust_tile_offset(x, y, tile_width, tile_height,
 +                                         tile_size, pitch_tiles,
 +                                         old_offset, new_offset);
        } else {
                old_offset += *y * pitch + *x * cpp;
  
        return new_offset;
  }
  
 +/*
 + * Adjust the tile offset by moving the difference into
 + * the x/y offsets.
 + */
 +static u32 intel_adjust_tile_offset(int *x, int *y,
 +                                  const struct intel_plane_state *state, int plane,
 +                                  u32 old_offset, u32 new_offset)
 +{
 +      return _intel_adjust_tile_offset(x, y, state->base.fb, plane,
 +                                       state->base.rotation,
 +                                       old_offset, new_offset);
 +}
 +
  /*
   * Computes the linear offset to the base tile and adjusts
   * x, y. bytes per pixel is assumed to be a power-of-two.
@@@ -2417,9 -2375,9 +2417,9 @@@ static u32 _intel_compute_tile_offset(c
                offset = (tile_rows * pitch_tiles + tiles) * tile_size;
                offset_aligned = offset & ~alignment;
  
 -              _intel_adjust_tile_offset(x, y, tile_width, tile_height,
 -                                        tile_size, pitch_tiles,
 -                                        offset, offset_aligned);
 +              __intel_adjust_tile_offset(x, y, tile_width, tile_height,
 +                                         tile_size, pitch_tiles,
 +                                         offset, offset_aligned);
        } else {
                offset = *y * pitch + *x * cpp;
                offset_aligned = offset & ~alignment;
@@@ -2451,24 -2409,16 +2451,24 @@@ u32 intel_compute_tile_offset(int *x, i
                                          rotation, alignment);
  }
  
 -/* Convert the fb->offset[] linear offset into x/y offsets */
 -static void intel_fb_offset_to_xy(int *x, int *y,
 -                                const struct drm_framebuffer *fb, int plane)
 +/* Convert the fb->offset[] into x/y offsets */
 +static int intel_fb_offset_to_xy(int *x, int *y,
 +                               const struct drm_framebuffer *fb, int plane)
  {
 -      unsigned int cpp = fb->format->cpp[plane];
 -      unsigned int pitch = fb->pitches[plane];
 -      u32 linear_offset = fb->offsets[plane];
 +      struct drm_i915_private *dev_priv = to_i915(fb->dev);
 +
 +      if (fb->modifier != DRM_FORMAT_MOD_LINEAR &&
 +          fb->offsets[plane] % intel_tile_size(dev_priv))
 +              return -EINVAL;
 +
 +      *x = 0;
 +      *y = 0;
  
 -      *y = linear_offset / pitch;
 -      *x = linear_offset % pitch / cpp;
 +      _intel_adjust_tile_offset(x, y,
 +                                fb, plane, DRM_MODE_ROTATE_0,
 +                                fb->offsets[plane], 0);
 +
 +      return 0;
  }
  
  static unsigned int intel_fb_modifier_to_tiling(uint64_t fb_modifier)
        case I915_FORMAT_MOD_X_TILED:
                return I915_TILING_X;
        case I915_FORMAT_MOD_Y_TILED:
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
                return I915_TILING_Y;
        default:
                return I915_TILING_NONE;
        }
  }
  
 +static const struct drm_format_info ccs_formats[] = {
 +      { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
 +      { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
 +      { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
 +      { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
 +};
 +
 +static const struct drm_format_info *
 +lookup_format_info(const struct drm_format_info formats[],
 +                 int num_formats, u32 format)
 +{
 +      int i;
 +
 +      for (i = 0; i < num_formats; i++) {
 +              if (formats[i].format == format)
 +                      return &formats[i];
 +      }
 +
 +      return NULL;
 +}
 +
 +static const struct drm_format_info *
 +intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
 +{
 +      switch (cmd->modifier[0]) {
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
 +              return lookup_format_info(ccs_formats,
 +                                        ARRAY_SIZE(ccs_formats),
 +                                        cmd->pixel_format);
 +      default:
 +              return NULL;
 +      }
 +}
 +
  static int
  intel_fill_fb_info(struct drm_i915_private *dev_priv,
                   struct drm_framebuffer *fb)
                unsigned int cpp, size;
                u32 offset;
                int x, y;
 +              int ret;
  
                cpp = fb->format->cpp[i];
                width = drm_framebuffer_plane_width(fb->width, fb, i);
                height = drm_framebuffer_plane_height(fb->height, fb, i);
  
 -              intel_fb_offset_to_xy(&x, &y, fb, i);
 +              ret = intel_fb_offset_to_xy(&x, &y, fb, i);
 +              if (ret) {
 +                      DRM_DEBUG_KMS("bad fb plane %d offset: 0x%x\n",
 +                                    i, fb->offsets[i]);
 +                      return ret;
 +              }
 +
 +              if ((fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
 +                   fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) && i == 1) {
 +                      int hsub = fb->format->hsub;
 +                      int vsub = fb->format->vsub;
 +                      int tile_width, tile_height;
 +                      int main_x, main_y;
 +                      int ccs_x, ccs_y;
 +
 +                      intel_tile_dims(fb, i, &tile_width, &tile_height);
 +                      tile_width *= hsub;
 +                      tile_height *= vsub;
 +
 +                      ccs_x = (x * hsub) % tile_width;
 +                      ccs_y = (y * vsub) % tile_height;
 +                      main_x = intel_fb->normal[0].x % tile_width;
 +                      main_y = intel_fb->normal[0].y % tile_height;
 +
 +                      /*
 +                       * CCS doesn't have its own x/y offset register, so the intra CCS tile
 +                       * x/y offsets must match between CCS and the main surface.
 +                       */
 +                      if (main_x != ccs_x || main_y != ccs_y) {
 +                              DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n",
 +                                            main_x, main_y,
 +                                            ccs_x, ccs_y,
 +                                            intel_fb->normal[0].x,
 +                                            intel_fb->normal[0].y,
 +                                            x, y);
 +                              return -EINVAL;
 +                      }
 +              }
  
                /*
                 * The fence (if used) is aligned to the start of the object
                 * fb layout agrees with the fence layout. We already check that the
                 * fb stride matches the fence stride elsewhere.
                 */
 -              if (i915_gem_object_is_tiled(intel_fb->obj) &&
 +              if (i == 0 && i915_gem_object_is_tiled(intel_fb->obj) &&
                    (x + width) * cpp > fb->pitches[i]) {
                        DRM_DEBUG_KMS("bad fb plane %d offset: 0x%x\n",
                                      i, fb->offsets[i]);
                         * We only keep the x/y offsets, so push all of the
                         * gtt offset into the x/y offsets.
                         */
 -                      _intel_adjust_tile_offset(&x, &y,
 -                                                tile_width, tile_height,
 -                                                tile_size, pitch_tiles,
 -                                                gtt_offset_rotated * tile_size, 0);
 +                      __intel_adjust_tile_offset(&x, &y,
 +                                                 tile_width, tile_height,
 +                                                 tile_size, pitch_tiles,
 +                                                 gtt_offset_rotated * tile_size, 0);
  
                        gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
  
@@@ -2788,6 -2664,20 +2788,6 @@@ out_unref_obj
        return false;
  }
  
 -/* Update plane->state->fb to match plane->fb after driver-internal updates */
 -static void
 -update_state_fb(struct drm_plane *plane)
 -{
 -      if (plane->fb == plane->state->fb)
 -              return;
 -
 -      if (plane->state->fb)
 -              drm_framebuffer_unreference(plane->state->fb);
 -      plane->state->fb = plane->fb;
 -      if (plane->state->fb)
 -              drm_framebuffer_reference(plane->state->fb);
 -}
 -
  static void
  intel_set_plane_visible(struct intel_crtc_state *crtc_state,
                        struct intel_plane_state *plane_state,
@@@ -2940,9 -2830,6 +2940,9 @@@ static int skl_max_plane_width(const st
                        break;
                }
                break;
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
 +              /* FIXME AUX plane? */
        case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
                switch (cpp) {
        return 2048;
  }
  
 +static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
 +                                         int main_x, int main_y, u32 main_offset)
 +{
 +      const struct drm_framebuffer *fb = plane_state->base.fb;
 +      int hsub = fb->format->hsub;
 +      int vsub = fb->format->vsub;
 +      int aux_x = plane_state->aux.x;
 +      int aux_y = plane_state->aux.y;
 +      u32 aux_offset = plane_state->aux.offset;
 +      u32 alignment = intel_surf_alignment(fb, 1);
 +
 +      while (aux_offset >= main_offset && aux_y <= main_y) {
 +              int x, y;
 +
 +              if (aux_x == main_x && aux_y == main_y)
 +                      break;
 +
 +              if (aux_offset == 0)
 +                      break;
 +
 +              x = aux_x / hsub;
 +              y = aux_y / vsub;
 +              aux_offset = intel_adjust_tile_offset(&x, &y, plane_state, 1,
 +                                                    aux_offset, aux_offset - alignment);
 +              aux_x = x * hsub + aux_x % hsub;
 +              aux_y = y * vsub + aux_y % vsub;
 +      }
 +
 +      if (aux_x != main_x || aux_y != main_y)
 +              return false;
 +
 +      plane_state->aux.offset = aux_offset;
 +      plane_state->aux.x = aux_x;
 +      plane_state->aux.y = aux_y;
 +
 +      return true;
 +}
 +
  static int skl_check_main_surface(struct intel_plane_state *plane_state)
  {
        const struct drm_framebuffer *fb = plane_state->base.fb;
  
                while ((x + w) * cpp > fb->pitches[0]) {
                        if (offset == 0) {
 -                              DRM_DEBUG_KMS("Unable to find suitable display surface offset\n");
 +                              DRM_DEBUG_KMS("Unable to find suitable display surface offset due to X-tiling\n");
                                return -EINVAL;
                        }
  
                }
        }
  
 +      /*
 +       * CCS AUX surface doesn't have its own x/y offsets, we must make sure
 +       * they match with the main surface x/y offsets.
 +       */
 +      if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
 +          fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) {
 +              while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset)) {
 +                      if (offset == 0)
 +                              break;
 +
 +                      offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
 +                                                        offset, offset - alignment);
 +              }
 +
 +              if (x != plane_state->aux.x || y != plane_state->aux.y) {
 +                      DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n");
 +                      return -EINVAL;
 +              }
 +      }
 +
        plane_state->main.offset = offset;
        plane_state->main.x = x;
        plane_state->main.y = y;
@@@ -3110,49 -2939,6 +3110,49 @@@ static int skl_check_nv12_aux_surface(s
        return 0;
  }
  
 +static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
 +{
 +      struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 +      struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc);
 +      const struct drm_framebuffer *fb = plane_state->base.fb;
 +      int src_x = plane_state->base.src.x1 >> 16;
 +      int src_y = plane_state->base.src.y1 >> 16;
 +      int hsub = fb->format->hsub;
 +      int vsub = fb->format->vsub;
 +      int x = src_x / hsub;
 +      int y = src_y / vsub;
 +      u32 offset;
 +
 +      switch (plane->id) {
 +      case PLANE_PRIMARY:
 +      case PLANE_SPRITE0:
 +              break;
 +      default:
 +              DRM_DEBUG_KMS("RC support only on plane 1 and 2\n");
 +              return -EINVAL;
 +      }
 +
 +      if (crtc->pipe == PIPE_C) {
 +              DRM_DEBUG_KMS("No RC support on pipe C\n");
 +              return -EINVAL;
 +      }
 +
 +      if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) {
 +              DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n",
 +                            plane_state->base.rotation);
 +              return -EINVAL;
 +      }
 +
 +      intel_add_fb_offsets(&x, &y, plane_state, 1);
 +      offset = intel_compute_tile_offset(&x, &y, plane_state, 1);
 +
 +      plane_state->aux.offset = offset;
 +      plane_state->aux.x = x * hsub + src_x % hsub;
 +      plane_state->aux.y = y * vsub + src_y % vsub;
 +
 +      return 0;
 +}
 +
  int skl_check_plane_surface(struct intel_plane_state *plane_state)
  {
        const struct drm_framebuffer *fb = plane_state->base.fb;
                ret = skl_check_nv12_aux_surface(plane_state);
                if (ret)
                        return ret;
 +      } else if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
 +                 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) {
 +              ret = skl_check_ccs_aux_surface(plane_state);
 +              if (ret)
 +                      return ret;
        } else {
                plane_state->aux.offset = ~0xfff;
                plane_state->aux.x = 0;
@@@ -3487,12 -3268,8 +3487,12 @@@ static u32 skl_plane_ctl_tiling(uint64_
                return PLANE_CTL_TILED_X;
        case I915_FORMAT_MOD_Y_TILED:
                return PLANE_CTL_TILED_Y;
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +              return PLANE_CTL_TILED_Y | PLANE_CTL_DECOMPRESSION_ENABLE;
        case I915_FORMAT_MOD_Yf_TILED:
                return PLANE_CTL_TILED_YF;
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
 +              return PLANE_CTL_TILED_YF | PLANE_CTL_DECOMPRESSION_ENABLE;
        default:
                MISSING_CASE(fb_modifier);
        }
@@@ -3565,7 -3342,6 +3565,7 @@@ static void skylake_update_primary_plan
        u32 plane_ctl = plane_state->ctl;
        unsigned int rotation = plane_state->base.rotation;
        u32 stride = skl_plane_stride(fb, 0, rotation);
 +      u32 aux_stride = skl_plane_stride(fb, 1, rotation);
        u32 surf_addr = plane_state->main.offset;
        int scaler_id = plane_state->scaler_id;
        int src_x = plane_state->main.x;
        I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (src_y << 16) | src_x);
        I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
        I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
 +      I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
 +                    (plane_state->aux.offset - surf_addr) | aux_stride);
 +      I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
 +                    (plane_state->aux.y << 16) | plane_state->aux.x);
  
        if (scaler_id >= 0) {
                uint32_t ps_ctrl = 0;
@@@ -3647,6 -3419,14 +3647,6 @@@ static void skylake_disable_primary_pla
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
  }
  
 -static void intel_complete_page_flips(struct drm_i915_private *dev_priv)
 -{
 -      struct intel_crtc *crtc;
 -
 -      for_each_intel_crtc(&dev_priv->drm, crtc)
 -              intel_finish_page_flip_cs(dev_priv, crtc->pipe);
 -}
 -
  static int
  __intel_display_resume(struct drm_device *dev,
                       struct drm_atomic_state *state,
@@@ -3705,15 -3485,6 +3705,15 @@@ void intel_prepare_reset(struct drm_i91
            !gpu_reset_clobbers_display(dev_priv))
                return;
  
 +      /* We have a modeset vs reset deadlock, defensively unbreak it. */
 +      set_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
 +      wake_up_all(&dev_priv->gpu_error.wait_queue);
 +
 +      if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
 +              DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
 +              i915_gem_set_wedged(dev_priv);
 +      }
 +
        /*
         * Need mode_config.mutex so that we don't
         * trample ongoing ->detect() and whatnot.
@@@ -3764,6 -3535,13 +3764,6 @@@ void intel_finish_reset(struct drm_i915
        if (!state)
                goto unlock;
  
 -      /*
 -       * Flips in the rings will be nuked by the reset,
 -       * so complete all pending flips so that user space
 -       * will get its events and not get stuck.
 -       */
 -      intel_complete_page_flips(dev_priv);
 -
        dev_priv->modeset_restore_state = NULL;
  
        /* reset doesn't touch the display */
@@@ -3800,8 -3578,35 +3800,8 @@@ unlock
        drm_modeset_drop_locks(ctx);
        drm_modeset_acquire_fini(ctx);
        mutex_unlock(&dev->mode_config.mutex);
 -}
 -
 -static bool abort_flip_on_reset(struct intel_crtc *crtc)
 -{
 -      struct i915_gpu_error *error = &to_i915(crtc->base.dev)->gpu_error;
 -
 -      if (i915_reset_backoff(error))
 -              return true;
 -
 -      if (crtc->reset_count != i915_reset_count(error))
 -              return true;
  
 -      return false;
 -}
 -
 -static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      bool pending;
 -
 -      if (abort_flip_on_reset(intel_crtc))
 -              return false;
 -
 -      spin_lock_irq(&dev->event_lock);
 -      pending = to_intel_crtc(crtc)->flip_work != NULL;
 -      spin_unlock_irq(&dev->event_lock);
 -
 -      return pending;
 +      clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
  }
  
  static void intel_update_pipe_config(struct intel_crtc *crtc,
@@@ -4358,22 -4163,21 +4358,22 @@@ static void ironlake_fdi_disable(struc
  
  bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv)
  {
 -      struct intel_crtc *crtc;
 -
 -      /* Note that we don't need to be called with mode_config.lock here
 -       * as our list of CRTC objects is static for the lifetime of the
 -       * device and so cannot disappear as we iterate. Similarly, we can
 -       * happily treat the predicates as racy, atomic checks as userspace
 -       * cannot claim and pin a new fb without at least acquring the
 -       * struct_mutex and so serialising with us.
 -       */
 -      for_each_intel_crtc(&dev_priv->drm, crtc) {
 -              if (atomic_read(&crtc->unpin_work_count) == 0)
 +      struct drm_crtc *crtc;
 +      bool cleanup_done;
 +
 +      drm_for_each_crtc(crtc, &dev_priv->drm) {
 +              struct drm_crtc_commit *commit;
 +              spin_lock(&crtc->commit_lock);
 +              commit = list_first_entry_or_null(&crtc->commit_list,
 +                                                struct drm_crtc_commit, commit_entry);
 +              cleanup_done = commit ?
 +                      try_wait_for_completion(&commit->cleanup_done) : true;
 +              spin_unlock(&crtc->commit_lock);
 +
 +              if (cleanup_done)
                        continue;
  
 -              if (crtc->flip_work)
 -                      intel_wait_for_vblank(dev_priv, crtc->pipe);
 +              drm_crtc_wait_one_vblank(crtc);
  
                return true;
        }
        return false;
  }
  
 -static void page_flip_completed(struct intel_crtc *intel_crtc)
 -{
 -      struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 -      struct intel_flip_work *work = intel_crtc->flip_work;
 -
 -      intel_crtc->flip_work = NULL;
 -
 -      if (work->event)
 -              drm_crtc_send_vblank_event(&intel_crtc->base, work->event);
 -
 -      drm_crtc_vblank_put(&intel_crtc->base);
 -
 -      wake_up_all(&dev_priv->pending_flip_queue);
 -      trace_i915_flip_complete(intel_crtc->plane,
 -                               work->pending_flip_obj);
 -
 -      queue_work(dev_priv->wq, &work->unpin_work);
 -}
 -
 -static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      long ret;
 -
 -      WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
 -
 -      ret = wait_event_interruptible_timeout(
 -                                      dev_priv->pending_flip_queue,
 -                                      !intel_crtc_has_pending_flip(crtc),
 -                                      60*HZ);
 -
 -      if (ret < 0)
 -              return ret;
 -
 -      if (ret == 0) {
 -              struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -              struct intel_flip_work *work;
 -
 -              spin_lock_irq(&dev->event_lock);
 -              work = intel_crtc->flip_work;
 -              if (work && !is_mmio_work(work)) {
 -                      WARN_ONCE(1, "Removing stuck page flip\n");
 -                      page_flip_completed(intel_crtc);
 -              }
 -              spin_unlock_irq(&dev->event_lock);
 -      }
 -
 -      return 0;
 -}
 -
  void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
  {
        u32 temp;
@@@ -4700,7 -4555,7 +4700,7 @@@ static void lpt_pch_enable(const struc
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
  
 -      assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
 +      assert_pch_transcoder_disabled(dev_priv, PIPE_A);
  
        lpt_program_iclkip(crtc);
  
@@@ -4745,9 -4600,6 +4745,9 @@@ skl_update_scaler(struct intel_crtc_sta
         */
        need_scaling = src_w != dst_w || src_h != dst_h;
  
 +      if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX)
 +              need_scaling = true;
 +
        /*
         * Scaling/fitting not supported in IF-ID mode in GEN9+
         * TODO: Interlace fetch mode doesn't support YUV420 planar formats.
@@@ -5471,7 -5323,8 +5471,7 @@@ static void haswell_crtc_enable(struct 
                return;
  
        if (intel_crtc->config->has_pch_encoder)
 -              intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 -                                                    false);
 +              intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
  
        intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
  
                intel_wait_for_vblank(dev_priv, pipe);
                intel_wait_for_vblank(dev_priv, pipe);
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 -              intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 -                                                    true);
 +              intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
        }
  
        /* If we change the relative order between pipe/planes enabling, we need
@@@ -5653,7 -5507,8 +5653,7 @@@ static void haswell_crtc_disable(struc
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
  
        if (intel_crtc->config->has_pch_encoder)
 -              intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 -                                                    false);
 +              intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
  
        intel_encoders_disable(crtc, old_crtc_state, old_state);
  
        intel_encoders_post_disable(crtc, old_crtc_state, old_state);
  
        if (old_crtc_state->has_pch_encoder)
 -              intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 -                                                    true);
 +              intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
  }
  
  static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@@ -5990,6 -5846,8 +5990,6 @@@ static void intel_crtc_disable_noatomic
                return;
  
        if (crtc->primary->state->visible) {
 -              WARN_ON(intel_crtc->flip_work);
 -
                intel_pre_disable_primary_noatomic(crtc);
  
                intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
@@@ -6398,16 -6256,6 +6398,16 @@@ static int intel_crtc_compute_config(st
                return -EINVAL;
        }
  
 +      if (pipe_config->ycbcr420 && pipe_config->base.ctm) {
 +              /*
 +               * There is only one pipe CSC unit per pipe, and we need that
 +               * for output conversion from RGB->YCBCR. So if CTM is already
 +               * applied we can't support YCBCR420 output.
 +               */
 +              DRM_DEBUG_KMS("YCBCR420 and CTM together are not possible\n");
 +              return -EINVAL;
 +      }
 +
        /*
         * Pipe horizontal size must be even in:
         * - DVO ganged mode
@@@ -8201,7 -8049,6 +8201,7 @@@ static void haswell_set_pipemisc(struc
  {
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      struct intel_crtc_state *config = intel_crtc->config;
  
        if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
                u32 val = 0;
                if (intel_crtc->config->dither)
                        val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
  
 +              if (config->ycbcr420) {
 +                      val |= PIPEMISC_OUTPUT_COLORSPACE_YUV |
 +                              PIPEMISC_YUV420_ENABLE |
 +                              PIPEMISC_YUV420_MODE_FULL_BLEND;
 +              }
 +
                I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
        }
  }
@@@ -8560,16 -8401,10 +8560,16 @@@ skylake_get_initial_plane_config(struc
                fb->modifier = I915_FORMAT_MOD_X_TILED;
                break;
        case PLANE_CTL_TILED_Y:
 -              fb->modifier = I915_FORMAT_MOD_Y_TILED;
 +              if (val & PLANE_CTL_DECOMPRESSION_ENABLE)
 +                      fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
 +              else
 +                      fb->modifier = I915_FORMAT_MOD_Y_TILED;
                break;
        case PLANE_CTL_TILED_YF:
 -              fb->modifier = I915_FORMAT_MOD_Yf_TILED;
 +              if (val & PLANE_CTL_DECOMPRESSION_ENABLE)
 +                      fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
 +              else
 +                      fb->modifier = I915_FORMAT_MOD_Yf_TILED;
                break;
        default:
                MISSING_CASE(tiling);
@@@ -8803,8 -8638,7 +8803,8 @@@ static void assert_can_disable_lcpll(st
                I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
  
 -      I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
 +      I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL)),
 +                      "Display power well on\n");
        I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
        I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
        I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
@@@ -9274,7 -9108,12 +9274,7 @@@ static bool haswell_get_pipe_config(str
        u64 power_domain_mask;
        bool active;
  
 -      if (INTEL_GEN(dev_priv) >= 9) {
 -              intel_crtc_init_scalers(crtc, pipe_config);
 -
 -              pipe_config->scaler_state.scaler_id = -1;
 -              pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
 -      }
 +      intel_crtc_init_scalers(crtc, pipe_config);
  
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
        pipe_config->gamma_mode =
                I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
  
 +      if (IS_BROADWELL(dev_priv) || dev_priv->info.gen >= 9) {
 +              u32 tmp = I915_READ(PIPEMISC(crtc->pipe));
 +              bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV;
 +
 +              if (IS_GEMINILAKE(dev_priv) || dev_priv->info.gen >= 10) {
 +                      bool blend_mode_420 = tmp &
 +                                            PIPEMISC_YUV420_MODE_FULL_BLEND;
 +
 +                      pipe_config->ycbcr420 = tmp & PIPEMISC_YUV420_ENABLE;
 +                      if (pipe_config->ycbcr420 != clrspace_yuv ||
 +                          pipe_config->ycbcr420 != blend_mode_420)
 +                              DRM_DEBUG_KMS("Bad 4:2:0 mode (%08x)\n", tmp);
 +              } else if (clrspace_yuv) {
 +                      DRM_DEBUG_KMS("YCbCr 4:2:0 Unsupported\n");
 +              }
 +      }
 +
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
        if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                power_domain_mask |= BIT_ULL(power_domain);
@@@ -10298,44 -10120,882 +10298,44 @@@ struct drm_display_mode *intel_crtc_mod
  static void intel_crtc_destroy(struct drm_crtc *crtc)
  {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_device *dev = crtc->dev;
 -      struct intel_flip_work *work;
 -
 -      spin_lock_irq(&dev->event_lock);
 -      work = intel_crtc->flip_work;
 -      intel_crtc->flip_work = NULL;
 -      spin_unlock_irq(&dev->event_lock);
 -
 -      if (work) {
 -              cancel_work_sync(&work->mmio_work);
 -              cancel_work_sync(&work->unpin_work);
 -              kfree(work);
 -      }
  
        drm_crtc_cleanup(crtc);
 -
        kfree(intel_crtc);
  }
  
 -static void intel_unpin_work_fn(struct work_struct *__work)
 +/**
 + * intel_wm_need_update - Check whether watermarks need updating
 + * @plane: drm plane
 + * @state: new plane state
 + *
 + * Check current plane state versus the new one to determine whether
 + * watermarks need to be recalculated.
 + *
 + * Returns true or false.
 + */
 +static bool intel_wm_need_update(struct drm_plane *plane,
 +                               struct drm_plane_state *state)
  {
 -      struct intel_flip_work *work =
 -              container_of(__work, struct intel_flip_work, unpin_work);
 -      struct intel_crtc *crtc = to_intel_crtc(work->crtc);
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_plane *primary = crtc->base.primary;
 +      struct intel_plane_state *new = to_intel_plane_state(state);
 +      struct intel_plane_state *cur = to_intel_plane_state(plane->state);
  
 -      if (is_mmio_work(work))
 -              flush_work(&work->mmio_work);
 +      /* Update watermarks on tiling or size changes. */
 +      if (new->base.visible != cur->base.visible)
 +              return true;
  
 -      mutex_lock(&dev->struct_mutex);
 -      intel_unpin_fb_vma(work->old_vma);
 -      i915_gem_object_put(work->pending_flip_obj);
 -      mutex_unlock(&dev->struct_mutex);
 +      if (!cur->base.fb || !new->base.fb)
 +              return false;
  
 -      i915_gem_request_put(work->flip_queued_req);
 +      if (cur->base.fb->modifier != new->base.fb->modifier ||
 +          cur->base.rotation != new->base.rotation ||
 +          drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
 +          drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
 +          drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) ||
 +          drm_rect_height(&new->base.dst) != drm_rect_height(&cur->base.dst))
 +              return true;
  
 -      intel_frontbuffer_flip_complete(to_i915(dev),
 -                                      to_intel_plane(primary)->frontbuffer_bit);
 -      intel_fbc_post_update(crtc);
 -      drm_framebuffer_unreference(work->old_fb);
 -
 -      BUG_ON(atomic_read(&crtc->unpin_work_count) == 0);
 -      atomic_dec(&crtc->unpin_work_count);
 -
 -      kfree(work);
 -}
 -
 -/* Is 'a' after or equal to 'b'? */
 -static bool g4x_flip_count_after_eq(u32 a, u32 b)
 -{
 -      return !((a - b) & 0x80000000);
 -}
 -
 -static bool __pageflip_finished_cs(struct intel_crtc *crtc,
 -                                 struct intel_flip_work *work)
 -{
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -
 -      if (abort_flip_on_reset(crtc))
 -              return true;
 -
 -      /*
 -       * The relevant registers doen't exist on pre-ctg.
 -       * As the flip done interrupt doesn't trigger for mmio
 -       * flips on gmch platforms, a flip count check isn't
 -       * really needed there. But since ctg has the registers,
 -       * include it in the check anyway.
 -       */
 -      if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
 -              return true;
 -
 -      /*
 -       * BDW signals flip done immediately if the plane
 -       * is disabled, even if the plane enable is already
 -       * armed to occur at the next vblank :(
 -       */
 -
 -      /*
 -       * A DSPSURFLIVE check isn't enough in case the mmio and CS flips
 -       * used the same base address. In that case the mmio flip might
 -       * have completed, but the CS hasn't even executed the flip yet.
 -       *
 -       * A flip count check isn't enough as the CS might have updated
 -       * the base address just after start of vblank, but before we
 -       * managed to process the interrupt. This means we'd complete the
 -       * CS flip too soon.
 -       *
 -       * Combining both checks should get us a good enough result. It may
 -       * still happen that the CS flip has been executed, but has not
 -       * yet actually completed. But in case the base address is the same
 -       * anyway, we don't really care.
 -       */
 -      return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
 -              crtc->flip_work->gtt_offset &&
 -              g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)),
 -                                  crtc->flip_work->flip_count);
 -}
 -
 -static bool
 -__pageflip_finished_mmio(struct intel_crtc *crtc,
 -                             struct intel_flip_work *work)
 -{
 -      /*
 -       * MMIO work completes when vblank is different from
 -       * flip_queued_vblank.
 -       *
 -       * Reset counter value doesn't matter, this is handled by
 -       * i915_wait_request finishing early, so no need to handle
 -       * reset here.
 -       */
 -      return intel_crtc_get_vblank_counter(crtc) != work->flip_queued_vblank;
 -}
 -
 -
 -static bool pageflip_finished(struct intel_crtc *crtc,
 -                            struct intel_flip_work *work)
 -{
 -      if (!atomic_read(&work->pending))
 -              return false;
 -
 -      smp_rmb();
 -
 -      if (is_mmio_work(work))
 -              return __pageflip_finished_mmio(crtc, work);
 -      else
 -              return __pageflip_finished_cs(crtc, work);
 -}
 -
 -void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
 -{
 -      struct drm_device *dev = &dev_priv->drm;
 -      struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 -      struct intel_flip_work *work;
 -      unsigned long flags;
 -
 -      /* Ignore early vblank irqs */
 -      if (!crtc)
 -              return;
 -
 -      /*
 -       * This is called both by irq handlers and the reset code (to complete
 -       * lost pageflips) so needs the full irqsave spinlocks.
 -       */
 -      spin_lock_irqsave(&dev->event_lock, flags);
 -      work = crtc->flip_work;
 -
 -      if (work != NULL &&
 -          !is_mmio_work(work) &&
 -          pageflip_finished(crtc, work))
 -              page_flip_completed(crtc);
 -
 -      spin_unlock_irqrestore(&dev->event_lock, flags);
 -}
 -
 -void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
 -{
 -      struct drm_device *dev = &dev_priv->drm;
 -      struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 -      struct intel_flip_work *work;
 -      unsigned long flags;
 -
 -      /* Ignore early vblank irqs */
 -      if (!crtc)
 -              return;
 -
 -      /*
 -       * This is called both by irq handlers and the reset code (to complete
 -       * lost pageflips) so needs the full irqsave spinlocks.
 -       */
 -      spin_lock_irqsave(&dev->event_lock, flags);
 -      work = crtc->flip_work;
 -
 -      if (work != NULL &&
 -          is_mmio_work(work) &&
 -          pageflip_finished(crtc, work))
 -              page_flip_completed(crtc);
 -
 -      spin_unlock_irqrestore(&dev->event_lock, flags);
 -}
 -
 -static inline void intel_mark_page_flip_active(struct intel_crtc *crtc,
 -                                             struct intel_flip_work *work)
 -{
 -      work->flip_queued_vblank = intel_crtc_get_vblank_counter(crtc);
 -
 -      /* Ensure that the work item is consistent when activating it ... */
 -      smp_mb__before_atomic();
 -      atomic_set(&work->pending, 1);
 -}
 -
 -static int intel_gen2_queue_flip(struct drm_device *dev,
 -                               struct drm_crtc *crtc,
 -                               struct drm_framebuffer *fb,
 -                               struct drm_i915_gem_object *obj,
 -                               struct drm_i915_gem_request *req,
 -                               uint32_t flags)
 -{
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      u32 flip_mask, *cs;
 -
 -      cs = intel_ring_begin(req, 6);
 -      if (IS_ERR(cs))
 -              return PTR_ERR(cs);
 -
 -      /* Can't queue multiple flips, so wait for the previous
 -       * one to finish before executing the next.
 -       */
 -      if (intel_crtc->plane)
 -              flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
 -      else
 -              flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
 -      *cs++ = MI_WAIT_FOR_EVENT | flip_mask;
 -      *cs++ = MI_NOOP;
 -      *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
 -      *cs++ = fb->pitches[0];
 -      *cs++ = intel_crtc->flip_work->gtt_offset;
 -      *cs++ = 0; /* aux display base address, unused */
 -
 -      return 0;
 -}
 -
 -static int intel_gen3_queue_flip(struct drm_device *dev,
 -                               struct drm_crtc *crtc,
 -                               struct drm_framebuffer *fb,
 -                               struct drm_i915_gem_object *obj,
 -                               struct drm_i915_gem_request *req,
 -                               uint32_t flags)
 -{
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      u32 flip_mask, *cs;
 -
 -      cs = intel_ring_begin(req, 6);
 -      if (IS_ERR(cs))
 -              return PTR_ERR(cs);
 -
 -      if (intel_crtc->plane)
 -              flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
 -      else
 -              flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
 -      *cs++ = MI_WAIT_FOR_EVENT | flip_mask;
 -      *cs++ = MI_NOOP;
 -      *cs++ = MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
 -      *cs++ = fb->pitches[0];
 -      *cs++ = intel_crtc->flip_work->gtt_offset;
 -      *cs++ = MI_NOOP;
 -
 -      return 0;
 -}
 -
 -static int intel_gen4_queue_flip(struct drm_device *dev,
 -                               struct drm_crtc *crtc,
 -                               struct drm_framebuffer *fb,
 -                               struct drm_i915_gem_object *obj,
 -                               struct drm_i915_gem_request *req,
 -                               uint32_t flags)
 -{
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      u32 pf, pipesrc, *cs;
 -
 -      cs = intel_ring_begin(req, 4);
 -      if (IS_ERR(cs))
 -              return PTR_ERR(cs);
 -
 -      /* i965+ uses the linear or tiled offsets from the
 -       * Display Registers (which do not change across a page-flip)
 -       * so we need only reprogram the base address.
 -       */
 -      *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
 -      *cs++ = fb->pitches[0];
 -      *cs++ = intel_crtc->flip_work->gtt_offset |
 -              intel_fb_modifier_to_tiling(fb->modifier);
 -
 -      /* XXX Enabling the panel-fitter across page-flip is so far
 -       * untested on non-native modes, so ignore it for now.
 -       * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
 -       */
 -      pf = 0;
 -      pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
 -      *cs++ = pf | pipesrc;
 -
 -      return 0;
 -}
 -
 -static int intel_gen6_queue_flip(struct drm_device *dev,
 -                               struct drm_crtc *crtc,
 -                               struct drm_framebuffer *fb,
 -                               struct drm_i915_gem_object *obj,
 -                               struct drm_i915_gem_request *req,
 -                               uint32_t flags)
 -{
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      u32 pf, pipesrc, *cs;
 -
 -      cs = intel_ring_begin(req, 4);
 -      if (IS_ERR(cs))
 -              return PTR_ERR(cs);
 -
 -      *cs++ = MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane);
 -      *cs++ = fb->pitches[0] | intel_fb_modifier_to_tiling(fb->modifier);
 -      *cs++ = intel_crtc->flip_work->gtt_offset;
 -
 -      /* Contrary to the suggestions in the documentation,
 -       * "Enable Panel Fitter" does not seem to be required when page
 -       * flipping with a non-native mode, and worse causes a normal
 -       * modeset to fail.
 -       * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
 -       */
 -      pf = 0;
 -      pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
 -      *cs++ = pf | pipesrc;
 -
 -      return 0;
 -}
 -
 -static int intel_gen7_queue_flip(struct drm_device *dev,
 -                               struct drm_crtc *crtc,
 -                               struct drm_framebuffer *fb,
 -                               struct drm_i915_gem_object *obj,
 -                               struct drm_i915_gem_request *req,
 -                               uint32_t flags)
 -{
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      u32 *cs, plane_bit = 0;
 -      int len, ret;
 -
 -      switch (intel_crtc->plane) {
 -      case PLANE_A:
 -              plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
 -              break;
 -      case PLANE_B:
 -              plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B;
 -              break;
 -      case PLANE_C:
 -              plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C;
 -              break;
 -      default:
 -              WARN_ONCE(1, "unknown plane in flip command\n");
 -              return -ENODEV;
 -      }
 -
 -      len = 4;
 -      if (req->engine->id == RCS) {
 -              len += 6;
 -              /*
 -               * On Gen 8, SRM is now taking an extra dword to accommodate
 -               * 48bits addresses, and we need a NOOP for the batch size to
 -               * stay even.
 -               */
 -              if (IS_GEN8(dev_priv))
 -                      len += 2;
 -      }
 -
 -      /*
 -       * BSpec MI_DISPLAY_FLIP for IVB:
 -       * "The full packet must be contained within the same cache line."
 -       *
 -       * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
 -       * cacheline, if we ever start emitting more commands before
 -       * the MI_DISPLAY_FLIP we may need to first emit everything else,
 -       * then do the cacheline alignment, and finally emit the
 -       * MI_DISPLAY_FLIP.
 -       */
 -      ret = intel_ring_cacheline_align(req);
 -      if (ret)
 -              return ret;
 -
 -      cs = intel_ring_begin(req, len);
 -      if (IS_ERR(cs))
 -              return PTR_ERR(cs);
 -
 -      /* Unmask the flip-done completion message. Note that the bspec says that
 -       * we should do this for both the BCS and RCS, and that we must not unmask
 -       * more than one flip event at any time (or ensure that one flip message
 -       * can be sent by waiting for flip-done prior to queueing new flips).
 -       * Experimentation says that BCS works despite DERRMR masking all
 -       * flip-done completion events and that unmasking all planes at once
 -       * for the RCS also doesn't appear to drop events. Setting the DERRMR
 -       * to zero does lead to lockups within MI_DISPLAY_FLIP.
 -       */
 -      if (req->engine->id == RCS) {
 -              *cs++ = MI_LOAD_REGISTER_IMM(1);
 -              *cs++ = i915_mmio_reg_offset(DERRMR);
 -              *cs++ = ~(DERRMR_PIPEA_PRI_FLIP_DONE |
 -                        DERRMR_PIPEB_PRI_FLIP_DONE |
 -                        DERRMR_PIPEC_PRI_FLIP_DONE);
 -              if (IS_GEN8(dev_priv))
 -                      *cs++ = MI_STORE_REGISTER_MEM_GEN8 |
 -                              MI_SRM_LRM_GLOBAL_GTT;
 -              else
 -                      *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
 -              *cs++ = i915_mmio_reg_offset(DERRMR);
 -              *cs++ = i915_ggtt_offset(req->engine->scratch) + 256;
 -              if (IS_GEN8(dev_priv)) {
 -                      *cs++ = 0;
 -                      *cs++ = MI_NOOP;
 -              }
 -      }
 -
 -      *cs++ = MI_DISPLAY_FLIP_I915 | plane_bit;
 -      *cs++ = fb->pitches[0] | intel_fb_modifier_to_tiling(fb->modifier);
 -      *cs++ = intel_crtc->flip_work->gtt_offset;
 -      *cs++ = MI_NOOP;
 -
 -      return 0;
 -}
 -
 -static bool use_mmio_flip(struct intel_engine_cs *engine,
 -                        struct drm_i915_gem_object *obj)
 -{
 -      /*
 -       * This is not being used for older platforms, because
 -       * non-availability of flip done interrupt forces us to use
 -       * CS flips. Older platforms derive flip done using some clever
 -       * tricks involving the flip_pending status bits and vblank irqs.
 -       * So using MMIO flips there would disrupt this mechanism.
 -       */
 -
 -      if (engine == NULL)
 -              return true;
 -
 -      if (INTEL_GEN(engine->i915) < 5)
 -              return false;
 -
 -      if (i915.use_mmio_flip < 0)
 -              return false;
 -      else if (i915.use_mmio_flip > 0)
 -              return true;
 -      else if (i915.enable_execlists)
 -              return true;
 -
 -      return engine != i915_gem_object_last_write_engine(obj);
 -}
 -
 -static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
 -                           unsigned int rotation,
 -                           struct intel_flip_work *work)
 -{
 -      struct drm_device *dev = intel_crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
 -      const enum pipe pipe = intel_crtc->pipe;
 -      u32 ctl, stride = skl_plane_stride(fb, 0, rotation);
 -
 -      ctl = I915_READ(PLANE_CTL(pipe, 0));
 -      ctl &= ~PLANE_CTL_TILED_MASK;
 -      switch (fb->modifier) {
 -      case DRM_FORMAT_MOD_LINEAR:
 -              break;
 -      case I915_FORMAT_MOD_X_TILED:
 -              ctl |= PLANE_CTL_TILED_X;
 -              break;
 -      case I915_FORMAT_MOD_Y_TILED:
 -              ctl |= PLANE_CTL_TILED_Y;
 -              break;
 -      case I915_FORMAT_MOD_Yf_TILED:
 -              ctl |= PLANE_CTL_TILED_YF;
 -              break;
 -      default:
 -              MISSING_CASE(fb->modifier);
 -      }
 -
 -      /*
 -       * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
 -       * PLANE_SURF updates, the update is then guaranteed to be atomic.
 -       */
 -      I915_WRITE(PLANE_CTL(pipe, 0), ctl);
 -      I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
 -
 -      I915_WRITE(PLANE_SURF(pipe, 0), work->gtt_offset);
 -      POSTING_READ(PLANE_SURF(pipe, 0));
 -}
 -
 -static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
 -                           struct intel_flip_work *work)
 -{
 -      struct drm_device *dev = intel_crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
 -      i915_reg_t reg = DSPCNTR(intel_crtc->plane);
 -      u32 dspcntr;
 -
 -      dspcntr = I915_READ(reg);
 -
 -      if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 -              dspcntr |= DISPPLANE_TILED;
 -      else
 -              dspcntr &= ~DISPPLANE_TILED;
 -
 -      I915_WRITE(reg, dspcntr);
 -
 -      I915_WRITE(DSPSURF(intel_crtc->plane), work->gtt_offset);
 -      POSTING_READ(DSPSURF(intel_crtc->plane));
 -}
 -
 -static void intel_mmio_flip_work_func(struct work_struct *w)
 -{
 -      struct intel_flip_work *work =
 -              container_of(w, struct intel_flip_work, mmio_work);
 -      struct intel_crtc *crtc = to_intel_crtc(work->crtc);
 -      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 -      struct intel_framebuffer *intel_fb =
 -              to_intel_framebuffer(crtc->base.primary->fb);
 -      struct drm_i915_gem_object *obj = intel_fb->obj;
 -
 -      WARN_ON(i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT, NULL) < 0);
 -
 -      intel_pipe_update_start(crtc);
 -
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              skl_do_mmio_flip(crtc, work->rotation, work);
 -      else
 -              /* use_mmio_flip() retricts MMIO flips to ilk+ */
 -              ilk_do_mmio_flip(crtc, work);
 -
 -      intel_pipe_update_end(crtc, work);
 -}
 -
 -static int intel_default_queue_flip(struct drm_device *dev,
 -                                  struct drm_crtc *crtc,
 -                                  struct drm_framebuffer *fb,
 -                                  struct drm_i915_gem_object *obj,
 -                                  struct drm_i915_gem_request *req,
 -                                  uint32_t flags)
 -{
 -      return -ENODEV;
 -}
 -
 -static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv,
 -                                    struct intel_crtc *intel_crtc,
 -                                    struct intel_flip_work *work)
 -{
 -      u32 addr, vblank;
 -
 -      if (!atomic_read(&work->pending))
 -              return false;
 -
 -      smp_rmb();
 -
 -      vblank = intel_crtc_get_vblank_counter(intel_crtc);
 -      if (work->flip_ready_vblank == 0) {
 -              if (work->flip_queued_req &&
 -                  !i915_gem_request_completed(work->flip_queued_req))
 -                      return false;
 -
 -              work->flip_ready_vblank = vblank;
 -      }
 -
 -      if (vblank - work->flip_ready_vblank < 3)
 -              return false;
 -
 -      /* Potential stall - if we see that the flip has happened,
 -       * assume a missed interrupt. */
 -      if (INTEL_GEN(dev_priv) >= 4)
 -              addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane)));
 -      else
 -              addr = I915_READ(DSPADDR(intel_crtc->plane));
 -
 -      /* There is a potential issue here with a false positive after a flip
 -       * to the same address. We could address this by checking for a
 -       * non-incrementing frame counter.
 -       */
 -      return addr == work->gtt_offset;
 -}
 -
 -void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
 -{
 -      struct drm_device *dev = &dev_priv->drm;
 -      struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 -      struct intel_flip_work *work;
 -
 -      WARN_ON(!in_interrupt());
 -
 -      if (crtc == NULL)
 -              return;
 -
 -      spin_lock(&dev->event_lock);
 -      work = crtc->flip_work;
 -
 -      if (work != NULL && !is_mmio_work(work) &&
 -          __pageflip_stall_check_cs(dev_priv, crtc, work)) {
 -              WARN_ONCE(1,
 -                        "Kicking stuck page flip: queued at %d, now %d\n",
 -                      work->flip_queued_vblank, intel_crtc_get_vblank_counter(crtc));
 -              page_flip_completed(crtc);
 -              work = NULL;
 -      }
 -
 -      if (work != NULL && !is_mmio_work(work) &&
 -          intel_crtc_get_vblank_counter(crtc) - work->flip_queued_vblank > 1)
 -              intel_queue_rps_boost_for_request(work->flip_queued_req);
 -      spin_unlock(&dev->event_lock);
 -}
 -
 -__maybe_unused
 -static int intel_crtc_page_flip(struct drm_crtc *crtc,
 -                              struct drm_framebuffer *fb,
 -                              struct drm_pending_vblank_event *event,
 -                              uint32_t page_flip_flags)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct drm_framebuffer *old_fb = crtc->primary->fb;
 -      struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_plane *primary = crtc->primary;
 -      enum pipe pipe = intel_crtc->pipe;
 -      struct intel_flip_work *work;
 -      struct intel_engine_cs *engine;
 -      bool mmio_flip;
 -      struct drm_i915_gem_request *request;
 -      struct i915_vma *vma;
 -      int ret;
 -
 -      /*
 -       * drm_mode_page_flip_ioctl() should already catch this, but double
 -       * check to be safe.  In the future we may enable pageflipping from
 -       * a disabled primary plane.
 -       */
 -      if (WARN_ON(intel_fb_obj(old_fb) == NULL))
 -              return -EBUSY;
 -
 -      /* Can't change pixel format via MI display flips. */
 -      if (fb->format != crtc->primary->fb->format)
 -              return -EINVAL;
 -
 -      /*
 -       * TILEOFF/LINOFF registers can't be changed via MI display flips.
 -       * Note that pitch changes could also affect these register.
 -       */
 -      if (INTEL_GEN(dev_priv) > 3 &&
 -          (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
 -           fb->pitches[0] != crtc->primary->fb->pitches[0]))
 -              return -EINVAL;
 -
 -      if (i915_terminally_wedged(&dev_priv->gpu_error))
 -              goto out_hang;
 -
 -      work = kzalloc(sizeof(*work), GFP_KERNEL);
 -      if (work == NULL)
 -              return -ENOMEM;
 -
 -      work->event = event;
 -      work->crtc = crtc;
 -      work->old_fb = old_fb;
 -      INIT_WORK(&work->unpin_work, intel_unpin_work_fn);
 -
 -      ret = drm_crtc_vblank_get(crtc);
 -      if (ret)
 -              goto free_work;
 -
 -      /* We borrow the event spin lock for protecting flip_work */
 -      spin_lock_irq(&dev->event_lock);
 -      if (intel_crtc->flip_work) {
 -              /* Before declaring the flip queue wedged, check if
 -               * the hardware completed the operation behind our backs.
 -               */
 -              if (pageflip_finished(intel_crtc, intel_crtc->flip_work)) {
 -                      DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n");
 -                      page_flip_completed(intel_crtc);
 -              } else {
 -                      DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 -                      spin_unlock_irq(&dev->event_lock);
 -
 -                      drm_crtc_vblank_put(crtc);
 -                      kfree(work);
 -                      return -EBUSY;
 -              }
 -      }
 -      intel_crtc->flip_work = work;
 -      spin_unlock_irq(&dev->event_lock);
 -
 -      if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
 -              flush_workqueue(dev_priv->wq);
 -
 -      /* Reference the objects for the scheduled work. */
 -      drm_framebuffer_reference(work->old_fb);
 -
 -      crtc->primary->fb = fb;
 -      update_state_fb(crtc->primary);
 -
 -      work->pending_flip_obj = i915_gem_object_get(obj);
 -
 -      ret = i915_mutex_lock_interruptible(dev);
 -      if (ret)
 -              goto cleanup;
 -
 -      intel_crtc->reset_count = i915_reset_count(&dev_priv->gpu_error);
 -      if (i915_reset_backoff_or_wedged(&dev_priv->gpu_error)) {
 -              ret = -EIO;
 -              goto unlock;
 -      }
 -
 -      atomic_inc(&intel_crtc->unpin_work_count);
 -
 -      if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 -              work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 -
 -      if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 -              engine = dev_priv->engine[BCS];
 -              if (fb->modifier != old_fb->modifier)
 -                      /* vlv: DISPLAY_FLIP fails to change tiling */
 -                      engine = NULL;
 -      } else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
 -              engine = dev_priv->engine[BCS];
 -      } else if (INTEL_GEN(dev_priv) >= 7) {
 -              engine = i915_gem_object_last_write_engine(obj);
 -              if (engine == NULL || engine->id != RCS)
 -                      engine = dev_priv->engine[BCS];
 -      } else {
 -              engine = dev_priv->engine[RCS];
 -      }
 -
 -      mmio_flip = use_mmio_flip(engine, obj);
 -
 -      vma = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
 -      if (IS_ERR(vma)) {
 -              ret = PTR_ERR(vma);
 -              goto cleanup_pending;
 -      }
 -
 -      work->old_vma = to_intel_plane_state(primary->state)->vma;
 -      to_intel_plane_state(primary->state)->vma = vma;
 -
 -      work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
 -      work->rotation = crtc->primary->state->rotation;
 -
 -      /*
 -       * There's the potential that the next frame will not be compatible with
 -       * FBC, so we want to call pre_update() before the actual page flip.
 -       * The problem is that pre_update() caches some information about the fb
 -       * object, so we want to do this only after the object is pinned. Let's
 -       * be on the safe side and do this immediately before scheduling the
 -       * flip.
 -       */
 -      intel_fbc_pre_update(intel_crtc, intel_crtc->config,
 -                           to_intel_plane_state(primary->state));
 -
 -      if (mmio_flip) {
 -              INIT_WORK(&work->mmio_work, intel_mmio_flip_work_func);
 -              queue_work(system_unbound_wq, &work->mmio_work);
 -      } else {
 -              request = i915_gem_request_alloc(engine,
 -                                               dev_priv->kernel_context);
 -              if (IS_ERR(request)) {
 -                      ret = PTR_ERR(request);
 -                      goto cleanup_unpin;
 -              }
 -
 -              ret = i915_gem_request_await_object(request, obj, false);
 -              if (ret)
 -                      goto cleanup_request;
 -
 -              ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request,
 -                                                 page_flip_flags);
 -              if (ret)
 -                      goto cleanup_request;
 -
 -              intel_mark_page_flip_active(intel_crtc, work);
 -
 -              work->flip_queued_req = i915_gem_request_get(request);
 -              i915_add_request(request);
 -      }
 -
 -      i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
 -      i915_gem_track_fb(intel_fb_obj(old_fb), obj,
 -                        to_intel_plane(primary)->frontbuffer_bit);
 -      mutex_unlock(&dev->struct_mutex);
 -
 -      intel_frontbuffer_flip_prepare(to_i915(dev),
 -                                     to_intel_plane(primary)->frontbuffer_bit);
 -
 -      trace_i915_flip_request(intel_crtc->plane, obj);
 -
 -      return 0;
 -
 -cleanup_request:
 -      i915_add_request(request);
 -cleanup_unpin:
 -      to_intel_plane_state(primary->state)->vma = work->old_vma;
 -      intel_unpin_fb_vma(vma);
 -cleanup_pending:
 -      atomic_dec(&intel_crtc->unpin_work_count);
 -unlock:
 -      mutex_unlock(&dev->struct_mutex);
 -cleanup:
 -      crtc->primary->fb = old_fb;
 -      update_state_fb(crtc->primary);
 -
 -      i915_gem_object_put(obj);
 -      drm_framebuffer_unreference(work->old_fb);
 -
 -      spin_lock_irq(&dev->event_lock);
 -      intel_crtc->flip_work = NULL;
 -      spin_unlock_irq(&dev->event_lock);
 -
 -      drm_crtc_vblank_put(crtc);
 -free_work:
 -      kfree(work);
 -
 -      if (ret == -EIO) {
 -              struct drm_atomic_state *state;
 -              struct drm_plane_state *plane_state;
 -
 -out_hang:
 -              state = drm_atomic_state_alloc(dev);
 -              if (!state)
 -                      return -ENOMEM;
 -              state->acquire_ctx = dev->mode_config.acquire_ctx;
 -
 -retry:
 -              plane_state = drm_atomic_get_plane_state(state, primary);
 -              ret = PTR_ERR_OR_ZERO(plane_state);
 -              if (!ret) {
 -                      drm_atomic_set_fb_for_plane(plane_state, fb);
 -
 -                      ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
 -                      if (!ret)
 -                              ret = drm_atomic_commit(state);
 -              }
 -
 -              if (ret == -EDEADLK) {
 -                      drm_modeset_backoff(state->acquire_ctx);
 -                      drm_atomic_state_clear(state);
 -                      goto retry;
 -              }
 -
 -              drm_atomic_state_put(state);
 -
 -              if (ret == 0 && event) {
 -                      spin_lock_irq(&dev->event_lock);
 -                      drm_crtc_send_vblank_event(crtc, event);
 -                      spin_unlock_irq(&dev->event_lock);
 -              }
 -      }
 -      return ret;
 -}
 -
 -
 -/**
 - * intel_wm_need_update - Check whether watermarks need updating
 - * @plane: drm plane
 - * @state: new plane state
 - *
 - * Check current plane state versus the new one to determine whether
 - * watermarks need to be recalculated.
 - *
 - * Returns true or false.
 - */
 -static bool intel_wm_need_update(struct drm_plane *plane,
 -                               struct drm_plane_state *state)
 -{
 -      struct intel_plane_state *new = to_intel_plane_state(state);
 -      struct intel_plane_state *cur = to_intel_plane_state(plane->state);
 -
 -      /* Update watermarks on tiling or size changes. */
 -      if (new->base.visible != cur->base.visible)
 -              return true;
 -
 -      if (!cur->base.fb || !new->base.fb)
 -              return false;
 -
 -      if (cur->base.fb->modifier != new->base.fb->modifier ||
 -          cur->base.rotation != new->base.rotation ||
 -          drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
 -          drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
 -          drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) ||
 -          drm_rect_height(&new->base.dst) != drm_rect_height(&cur->base.dst))
 -              return true;
 -
 -      return false;
 -}
 +      return false;
 +}
  
  static bool needs_scaling(struct intel_plane_state *state)
  {
@@@ -10700,9 -11360,6 +10700,9 @@@ static void intel_dump_pipe_config(stru
                                      pipe_config->fdi_lanes,
                                      &pipe_config->fdi_m_n);
  
 +      if (pipe_config->ycbcr420)
 +              DRM_DEBUG_KMS("YCbCr 4:2:0 output enabled\n");
 +
        if (intel_crtc_has_dp_encoder(pipe_config)) {
                intel_dump_m_n_config(pipe_config, "dp m_n",
                                pipe_config->lane_count, &pipe_config->dp_m_n);
@@@ -11274,7 -11931,6 +11274,7 @@@ intel_pipe_config_compare(struct drm_i9
        PIPE_CONF_CHECK_I(hdmi_scrambling);
        PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio);
        PIPE_CONF_CHECK_I(has_infoframe);
 +      PIPE_CONF_CHECK_I(ycbcr420);
  
        PIPE_CONF_CHECK_I(has_audio);
  
@@@ -12116,7 -12772,31 +12116,7 @@@ static int intel_atomic_check(struct dr
  static int intel_atomic_prepare_commit(struct drm_device *dev,
                                       struct drm_atomic_state *state)
  {
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 -      struct drm_crtc_state *crtc_state;
 -      struct drm_crtc *crtc;
 -      int i, ret;
 -
 -      for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 -              if (state->legacy_cursor_update)
 -                      continue;
 -
 -              ret = intel_crtc_wait_for_pending_flips(crtc);
 -              if (ret)
 -                      return ret;
 -
 -              if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
 -                      flush_workqueue(dev_priv->wq);
 -      }
 -
 -      ret = mutex_lock_interruptible(&dev->struct_mutex);
 -      if (ret)
 -              return ret;
 -
 -      ret = drm_atomic_helper_prepare_planes(dev, state);
 -      mutex_unlock(&dev->struct_mutex);
 -
 -      return ret;
 +      return drm_atomic_helper_prepare_planes(dev, state);
  }
  
  u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
        return dev->driver->get_vblank_counter(dev, crtc->pipe);
  }
  
- static void intel_atomic_wait_for_vblanks(struct drm_device *dev,
-                                         struct drm_i915_private *dev_priv,
-                                         unsigned crtc_mask)
- {
-       unsigned last_vblank_count[I915_MAX_PIPES];
-       enum pipe pipe;
-       int ret;
-       if (!crtc_mask)
-               return;
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
-                                                                 pipe);
-               if (!((1 << pipe) & crtc_mask))
-                       continue;
-               ret = drm_crtc_vblank_get(&crtc->base);
-               if (WARN_ON(ret != 0)) {
-                       crtc_mask &= ~(1 << pipe);
-                       continue;
-               }
-               last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base);
-       }
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
-                                                                 pipe);
-               long lret;
-               if (!((1 << pipe) & crtc_mask))
-                       continue;
-               lret = wait_event_timeout(dev->vblank[pipe].queue,
-                               last_vblank_count[pipe] !=
-                                       drm_crtc_vblank_count(&crtc->base),
-                               msecs_to_jiffies(50));
-               WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe));
-               drm_crtc_vblank_put(&crtc->base);
-       }
- }
- static bool needs_vblank_wait(struct intel_crtc_state *crtc_state)
- {
-       /* fb updated, need to unpin old fb */
-       if (crtc_state->fb_changed)
-               return true;
-       /* wm changes, need vblank before final wm's */
-       if (crtc_state->update_wm_post)
-               return true;
-       if (crtc_state->wm.need_postvbl_update)
-               return true;
-       return false;
- }
  static void intel_update_crtc(struct drm_crtc *crtc,
                              struct drm_atomic_state *state,
                              struct drm_crtc_state *old_crtc_state,
-                             struct drm_crtc_state *new_crtc_state,
-                             unsigned int *crtc_vblank_mask)
+                             struct drm_crtc_state *new_crtc_state)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        }
  
        drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
-       if (needs_vblank_wait(pipe_config))
-               *crtc_vblank_mask |= drm_crtc_mask(crtc);
  }
  
- static void intel_update_crtcs(struct drm_atomic_state *state,
-                              unsigned int *crtc_vblank_mask)
+ static void intel_update_crtcs(struct drm_atomic_state *state)
  {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
                        continue;
  
                intel_update_crtc(crtc, state, old_crtc_state,
-                                 new_crtc_state, crtc_vblank_mask);
+                                 new_crtc_state);
        }
  }
  
- static void skl_update_crtcs(struct drm_atomic_state *state,
-                            unsigned int *crtc_vblank_mask)
+ static void skl_update_crtcs(struct drm_atomic_state *state)
  {
        struct drm_i915_private *dev_priv = to_i915(state->dev);
        struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
                                vbl_wait = true;
  
                        intel_update_crtc(crtc, state, old_crtc_state,
-                                         new_crtc_state, crtc_vblank_mask);
+                                         new_crtc_state);
  
                        if (vbl_wait)
                                intel_wait_for_vblank(dev_priv, pipe);
@@@ -12327,30 -12939,6 +12259,30 @@@ static void intel_atomic_helper_free_st
        intel_atomic_helper_free_state(dev_priv);
  }
  
 +static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
 +{
 +      struct wait_queue_entry wait_fence, wait_reset;
 +      struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
 +
 +      init_wait_entry(&wait_fence, 0);
 +      init_wait_entry(&wait_reset, 0);
 +      for (;;) {
 +              prepare_to_wait(&intel_state->commit_ready.wait,
 +                              &wait_fence, TASK_UNINTERRUPTIBLE);
 +              prepare_to_wait(&dev_priv->gpu_error.wait_queue,
 +                              &wait_reset, TASK_UNINTERRUPTIBLE);
 +
 +
 +              if (i915_sw_fence_done(&intel_state->commit_ready)
 +                  || test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags))
 +                      break;
 +
 +              schedule();
 +      }
 +      finish_wait(&intel_state->commit_ready.wait, &wait_fence);
 +      finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
 +}
 +
  static void intel_atomic_commit_tail(struct drm_atomic_state *state)
  {
        struct drm_device *dev = state->dev;
        struct intel_crtc_state *intel_cstate;
        bool hw_check = intel_state->modeset;
        u64 put_domains[I915_MAX_PIPES] = {};
-       unsigned crtc_vblank_mask = 0;
        int i;
  
 +      intel_atomic_commit_fence_wait(intel_state);
 +
        drm_atomic_helper_wait_for_dependencies(state);
  
        if (intel_state->modeset)
        }
  
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
-       dev_priv->display.update_crtcs(state, &crtc_vblank_mask);
+       dev_priv->display.update_crtcs(state);
  
        /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
         * already, but still need the state for the delayed optimization. To
         * - switch over to the vblank wait helper in the core after that since
         *   we don't need out special handling any more.
         */
-       if (!state->legacy_cursor_update)
-               intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask);
+       drm_atomic_helper_wait_for_flip_done(dev, state);
  
        /*
         * Now that the vblank has passed, we can go ahead and program the
                intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
        }
  
 -      mutex_lock(&dev->struct_mutex);
        drm_atomic_helper_cleanup_planes(dev, state);
 -      mutex_unlock(&dev->struct_mutex);
  
        drm_atomic_helper_commit_cleanup_done(state);
  
@@@ -12531,8 -13117,10 +12461,8 @@@ intel_atomic_commit_ready(struct i915_s
  
        switch (notify) {
        case FENCE_COMPLETE:
 -              if (state->base.commit_work.func)
 -                      queue_work(system_unbound_wq, &state->base.commit_work);
 +              /* we do blocking waits in the worker, nothing to do here */
                break;
 -
        case FENCE_FREE:
                {
                        struct intel_atomic_helper *helper =
@@@ -12618,7 -13206,9 +12548,7 @@@ static int intel_atomic_commit(struct d
        if (ret) {
                i915_sw_fence_commit(&intel_state->commit_ready);
  
 -              mutex_lock(&dev->struct_mutex);
                drm_atomic_helper_cleanup_planes(dev, state);
 -              mutex_unlock(&dev->struct_mutex);
                return ret;
        }
        dev_priv->wm.distrust_bios_wm = false;
        }
  
        drm_atomic_state_get(state);
 -      INIT_WORK(&state->commit_work,
 -                nonblock ? intel_atomic_commit_work : NULL);
 +      INIT_WORK(&state->commit_work, intel_atomic_commit_work);
  
        i915_sw_fence_commit(&intel_state->commit_ready);
 -      if (!nonblock) {
 -              i915_sw_fence_wait(&intel_state->commit_ready);
 +      if (nonblock)
 +              queue_work(system_unbound_wq, &state->commit_work);
 +      else
                intel_atomic_commit_tail(state);
 -      }
 +
  
        return 0;
  }
@@@ -12682,6 -13272,32 +12612,6 @@@ intel_prepare_plane_fb(struct drm_plan
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
        int ret;
  
 -      if (obj) {
 -              if (plane->type == DRM_PLANE_TYPE_CURSOR &&
 -                  INTEL_INFO(dev_priv)->cursor_needs_physical) {
 -                      const int align = intel_cursor_alignment(dev_priv);
 -
 -                      ret = i915_gem_object_attach_phys(obj, align);
 -                      if (ret) {
 -                              DRM_DEBUG_KMS("failed to attach phys object\n");
 -                              return ret;
 -                      }
 -              } else {
 -                      struct i915_vma *vma;
 -
 -                      vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
 -                      if (IS_ERR(vma)) {
 -                              DRM_DEBUG_KMS("failed to pin object\n");
 -                              return PTR_ERR(vma);
 -                      }
 -
 -                      to_intel_plane_state(new_state)->vma = vma;
 -              }
 -      }
 -
 -      if (!obj && !old_obj)
 -              return 0;
 -
        if (old_obj) {
                struct drm_crtc_state *crtc_state =
                        drm_atomic_get_existing_crtc_state(new_state->state,
        if (!obj)
                return 0;
  
 +      ret = i915_gem_object_pin_pages(obj);
 +      if (ret)
 +              return ret;
 +
 +      ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
 +      if (ret) {
 +              i915_gem_object_unpin_pages(obj);
 +              return ret;
 +      }
 +
 +      if (plane->type == DRM_PLANE_TYPE_CURSOR &&
 +          INTEL_INFO(dev_priv)->cursor_needs_physical) {
 +              const int align = intel_cursor_alignment(dev_priv);
 +
 +              ret = i915_gem_object_attach_phys(obj, align);
 +      } else {
 +              struct i915_vma *vma;
 +
 +              vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
 +              if (!IS_ERR(vma))
 +                      to_intel_plane_state(new_state)->vma = vma;
 +              else
 +                      ret =  PTR_ERR(vma);
 +      }
 +
 +      i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
 +
 +      mutex_unlock(&dev_priv->drm.struct_mutex);
 +      i915_gem_object_unpin_pages(obj);
 +      if (ret)
 +              return ret;
 +
        if (!new_state->fence) { /* implicit fencing */
                ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
                                                      obj->resv, NULL,
                                                      GFP_KERNEL);
                if (ret < 0)
                        return ret;
 -
 -              i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
        }
  
        return 0;
@@@ -12781,11 -13367,8 +12711,11 @@@ intel_cleanup_plane_fb(struct drm_plan
  
        /* Should only be called after a successful intel_prepare_plane_fb()! */
        vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
 -      if (vma)
 +      if (vma) {
 +              mutex_lock(&plane->dev->struct_mutex);
                intel_unpin_fb_vma(vma);
 +              mutex_unlock(&plane->dev->struct_mutex);
 +      }
  }
  
  int
@@@ -12912,7 -13495,7 +12842,7 @@@ static void intel_finish_crtc_commit(st
  {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  
 -      intel_pipe_update_end(intel_crtc, NULL);
 +      intel_pipe_update_end(intel_crtc);
  }
  
  /**
@@@ -12928,102 -13511,7 +12858,102 @@@ void intel_plane_destroy(struct drm_pla
        kfree(to_intel_plane(plane));
  }
  
 -const struct drm_plane_funcs intel_plane_funcs = {
 +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
 +{
 +      switch (format) {
 +      case DRM_FORMAT_C8:
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_XRGB1555:
 +      case DRM_FORMAT_XRGB8888:
 +              return modifier == DRM_FORMAT_MOD_LINEAR ||
 +                      modifier == I915_FORMAT_MOD_X_TILED;
 +      default:
 +              return false;
 +      }
 +}
 +
 +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
 +{
 +      switch (format) {
 +      case DRM_FORMAT_C8:
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_XBGR8888:
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_XBGR2101010:
 +              return modifier == DRM_FORMAT_MOD_LINEAR ||
 +                      modifier == I915_FORMAT_MOD_X_TILED;
 +      default:
 +              return false;
 +      }
 +}
 +
 +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
 +{
 +      switch (format) {
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_XBGR8888:
 +      case DRM_FORMAT_ARGB8888:
 +      case DRM_FORMAT_ABGR8888:
 +              if (modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
 +                  modifier == I915_FORMAT_MOD_Y_TILED_CCS)
 +                      return true;
 +              /* fall through */
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_XBGR2101010:
 +      case DRM_FORMAT_YUYV:
 +      case DRM_FORMAT_YVYU:
 +      case DRM_FORMAT_UYVY:
 +      case DRM_FORMAT_VYUY:
 +              if (modifier == I915_FORMAT_MOD_Yf_TILED)
 +                      return true;
 +              /* fall through */
 +      case DRM_FORMAT_C8:
 +              if (modifier == DRM_FORMAT_MOD_LINEAR ||
 +                  modifier == I915_FORMAT_MOD_X_TILED ||
 +                  modifier == I915_FORMAT_MOD_Y_TILED)
 +                      return true;
 +              /* fall through */
 +      default:
 +              return false;
 +      }
 +}
 +
 +static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
 +                                                   uint32_t format,
 +                                                   uint64_t modifier)
 +{
 +      struct drm_i915_private *dev_priv = to_i915(plane->dev);
 +
 +      if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
 +              return false;
 +
 +      if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
 +          modifier != DRM_FORMAT_MOD_LINEAR)
 +              return false;
 +
 +      if (INTEL_GEN(dev_priv) >= 9)
 +              return skl_mod_supported(format, modifier);
 +      else if (INTEL_GEN(dev_priv) >= 4)
 +              return i965_mod_supported(format, modifier);
 +      else
 +              return i8xx_mod_supported(format, modifier);
 +
 +      unreachable();
 +}
 +
 +static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane,
 +                                                  uint32_t format,
 +                                                  uint64_t modifier)
 +{
 +      if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
 +              return false;
 +
 +      return modifier == DRM_FORMAT_MOD_LINEAR && format == DRM_FORMAT_ARGB8888;
 +}
 +
 +static struct drm_plane_funcs intel_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
 +      .format_mod_supported = intel_primary_plane_format_mod_supported,
  };
  
  static int
@@@ -13050,7 -13537,7 +12980,7 @@@ intel_legacy_cursor_update(struct drm_p
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_framebuffer *old_fb;
        struct drm_crtc_state *crtc_state = crtc->state;
 -      struct i915_vma *old_vma;
 +      struct i915_vma *old_vma, *vma;
  
        /*
         * When crtc is inactive or there is a modeset pending,
                goto slow;
  
        old_plane_state = plane->state;
+       /*
+        * Don't do an async update if there is an outstanding commit modifying
+        * the plane.  This prevents our async update's changes from getting
+        * overridden by a previous synchronous update's state.
+        */
+       if (old_plane_state->commit &&
+           !try_wait_for_completion(&old_plane_state->commit->hw_done))
+               goto slow;
  
        /*
         * If any parameters change that may affect watermarks,
                        goto out_unlock;
                }
        } else {
 -              struct i915_vma *vma;
 -
                vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation);
                if (IS_ERR(vma)) {
                        DRM_DEBUG_KMS("failed to pin object\n");
        }
  
        old_fb = old_plane_state->fb;
-       old_vma = to_intel_plane_state(old_plane_state)->vma;
  
        i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb),
                          intel_plane->frontbuffer_bit);
  
        /* Swap plane state */
-       new_plane_state->fence = old_plane_state->fence;
-       *to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state);
-       new_plane_state->fence = NULL;
-       new_plane_state->fb = old_fb;
-       to_intel_plane_state(new_plane_state)->vma = NULL;
+       plane->state = new_plane_state;
  
        if (plane->state->visible) {
                trace_intel_update_plane(plane, to_intel_crtc(crtc));
                intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
        }
  
+       old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma);
        if (old_vma)
                intel_unpin_fb_vma(old_vma);
  
  out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
  out_free:
-       intel_plane_destroy_state(plane, new_plane_state);
+       if (ret)
+               intel_plane_destroy_state(plane, new_plane_state);
+       else
+               intel_plane_destroy_state(plane, old_plane_state);
        return ret;
  
  slow:
@@@ -13165,7 -13661,6 +13102,7 @@@ static const struct drm_plane_funcs int
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
 +      .format_mod_supported = intel_cursor_plane_format_mod_supported,
  };
  
  static struct intel_plane *
@@@ -13176,7 -13671,6 +13113,7 @@@ intel_primary_plane_create(struct drm_i
        const uint32_t *intel_primary_formats;
        unsigned int supported_rotations;
        unsigned int num_formats;
 +      const uint64_t *modifiers;
        int ret;
  
        primary = kzalloc(sizeof(*primary), GFP_KERNEL);
        primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
        primary->check_plane = intel_check_primary_plane;
  
 -      if (INTEL_GEN(dev_priv) >= 9) {
 +      if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
 +              intel_primary_formats = skl_primary_formats;
 +              num_formats = ARRAY_SIZE(skl_primary_formats);
 +              modifiers = skl_format_modifiers_ccs;
 +
 +              primary->update_plane = skylake_update_primary_plane;
 +              primary->disable_plane = skylake_disable_primary_plane;
 +      } else if (INTEL_GEN(dev_priv) >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
 +              if (pipe < PIPE_C)
 +                      modifiers = skl_format_modifiers_ccs;
 +              else
 +                      modifiers = skl_format_modifiers_noccs;
  
                primary->update_plane = skylake_update_primary_plane;
                primary->disable_plane = skylake_disable_primary_plane;
        } else if (INTEL_GEN(dev_priv) >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
 +              modifiers = i9xx_format_modifiers;
  
                primary->update_plane = i9xx_update_primary_plane;
                primary->disable_plane = i9xx_disable_primary_plane;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
 +              modifiers = i9xx_format_modifiers;
  
                primary->update_plane = i9xx_update_primary_plane;
                primary->disable_plane = i9xx_disable_primary_plane;
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
                                               0, &intel_plane_funcs,
                                               intel_primary_formats, num_formats,
 -                                             NULL,
 +                                             modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane 1%c", pipe_name(pipe));
        else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
                                               0, &intel_plane_funcs,
                                               intel_primary_formats, num_formats,
 -                                             NULL,
 +                                             modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "primary %c", pipe_name(pipe));
        else
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
                                               0, &intel_plane_funcs,
                                               intel_primary_formats, num_formats,
 -                                             NULL,
 +                                             modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane %c", plane_name(primary->plane));
        if (ret)
@@@ -13349,8 -13830,7 +13286,8 @@@ intel_cursor_plane_create(struct drm_i9
                                       0, &intel_cursor_plane_funcs,
                                       intel_cursor_formats,
                                       ARRAY_SIZE(intel_cursor_formats),
 -                                     NULL, DRM_PLANE_TYPE_CURSOR,
 +                                     cursor_format_modifiers,
 +                                     DRM_PLANE_TYPE_CURSOR,
                                       "cursor %c", pipe_name(pipe));
        if (ret)
                goto fail;
@@@ -13872,12 -14352,10 +13809,12 @@@ static int intel_framebuffer_init(struc
                                  struct drm_mode_fb_cmd2 *mode_cmd)
  {
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 +      struct drm_framebuffer *fb = &intel_fb->base;
        struct drm_format_name_buf format_name;
 -      u32 pitch_limit, stride_alignment;
 +      u32 pitch_limit;
        unsigned int tiling, stride;
        int ret = -EINVAL;
 +      int i;
  
        i915_gem_object_lock(obj);
        obj->framebuffer_references++;
  
        /* Passed in modifier sanity checking. */
        switch (mode_cmd->modifier[0]) {
 +      case I915_FORMAT_MOD_Y_TILED_CCS:
 +      case I915_FORMAT_MOD_Yf_TILED_CCS:
 +              switch (mode_cmd->pixel_format) {
 +              case DRM_FORMAT_XBGR8888:
 +              case DRM_FORMAT_ABGR8888:
 +              case DRM_FORMAT_XRGB8888:
 +              case DRM_FORMAT_ARGB8888:
 +                      break;
 +              default:
 +                      DRM_DEBUG_KMS("RC supported only with RGB8888 formats\n");
 +                      goto err;
 +              }
 +              /* fall through */
        case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
                if (INTEL_GEN(dev_priv) < 9) {
        if (mode_cmd->offsets[0] != 0)
                goto err;
  
 -      drm_helper_mode_fill_fb_struct(&dev_priv->drm,
 -                                     &intel_fb->base, mode_cmd);
 +      drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd);
  
 -      stride_alignment = intel_fb_stride_alignment(&intel_fb->base, 0);
 -      if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
 -              DRM_DEBUG_KMS("pitch (%d) must be at least %u byte aligned\n",
 -                            mode_cmd->pitches[0], stride_alignment);
 -              goto err;
 +      for (i = 0; i < fb->format->num_planes; i++) {
 +              u32 stride_alignment;
 +
 +              if (mode_cmd->handles[i] != mode_cmd->handles[0]) {
 +                      DRM_DEBUG_KMS("bad plane %d handle\n", i);
 +                      goto err;
 +              }
 +
 +              stride_alignment = intel_fb_stride_alignment(fb, i);
 +
 +              /*
 +               * Display WA #0531: skl,bxt,kbl,glk
 +               *
 +               * Render decompression and plane width > 3840
 +               * combined with horizontal panning requires the
 +               * plane stride to be a multiple of 4. We'll just
 +               * require the entire fb to accommodate that to avoid
 +               * potential runtime errors at plane configuration time.
 +               */
 +              if (IS_GEN9(dev_priv) && i == 0 && fb->width > 3840 &&
 +                  (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
 +                   fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS))
 +                      stride_alignment *= 4;
 +
 +              if (fb->pitches[i] & (stride_alignment - 1)) {
 +                      DRM_DEBUG_KMS("plane %d pitch (%d) must be at least %u byte aligned\n",
 +                                    i, fb->pitches[i], stride_alignment);
 +                      goto err;
 +              }
        }
  
        intel_fb->obj = obj;
  
 -      ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
 +      ret = intel_fill_fb_info(dev_priv, fb);
        if (ret)
                goto err;
  
 -      ret = drm_framebuffer_init(obj->base.dev,
 -                                 &intel_fb->base,
 -                                 &intel_fb_funcs);
 +      ret = drm_framebuffer_init(&dev_priv->drm, fb, &intel_fb_funcs);
        if (ret) {
                DRM_ERROR("framebuffer init failed %d\n", ret);
                goto err;
@@@ -14110,7 -14554,6 +14047,7 @@@ static void intel_atomic_state_free(str
  
  static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_create = intel_user_framebuffer_create,
 +      .get_format_info = intel_get_format_info,
        .output_poll_changed = intel_fbdev_output_poll_changed,
        .atomic_check = intel_atomic_check,
        .atomic_commit = intel_atomic_commit,
@@@ -14210,6 -14653,34 +14147,6 @@@ void intel_init_display_hooks(struct dr
                dev_priv->display.update_crtcs = skl_update_crtcs;
        else
                dev_priv->display.update_crtcs = intel_update_crtcs;
 -
 -      switch (INTEL_INFO(dev_priv)->gen) {
 -      case 2:
 -              dev_priv->display.queue_flip = intel_gen2_queue_flip;
 -              break;
 -
 -      case 3:
 -              dev_priv->display.queue_flip = intel_gen3_queue_flip;
 -              break;
 -
 -      case 4:
 -      case 5:
 -              dev_priv->display.queue_flip = intel_gen4_queue_flip;
 -              break;
 -
 -      case 6:
 -              dev_priv->display.queue_flip = intel_gen6_queue_flip;
 -              break;
 -      case 7:
 -      case 8: /* FIXME(BDW): Check that the gen8 RCS flip works. */
 -              dev_priv->display.queue_flip = intel_gen7_queue_flip;
 -              break;
 -      case 9:
 -              /* Drop through - unsupported since execlist only. */
 -      default:
 -              /* Default just returns -ENODEV to indicate unsupported */
 -              dev_priv->display.queue_flip = intel_default_queue_flip;
 -      }
  }
  
  /*
@@@ -15140,7 -15611,7 +15077,7 @@@ intel_modeset_setup_hw_state(struct drm
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                vlv_wm_get_hw_state(dev);
                vlv_wm_sanitize(dev_priv);
 -      } else if (IS_GEN9(dev_priv)) {
 +      } else if (INTEL_GEN(dev_priv) >= 9) {
                skl_wm_get_hw_state(dev);
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                ilk_wm_get_hw_state(dev);
@@@ -15247,9 -15718,6 +15184,9 @@@ void intel_modeset_cleanup(struct drm_d
         */
        drm_kms_helper_poll_fini(dev);
  
 +      /* poll work can call into fbdev, hence clean that up afterwards */
 +      intel_fbdev_fini(dev_priv);
 +
        intel_unregister_dsm_handler();
  
        intel_fbc_global_disable(dev_priv);
@@@ -15369,8 -15837,7 +15306,8 @@@ intel_display_capture_error_state(struc
                return NULL;
  
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 -              error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 +              error->power_well_driver =
 +                      I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL));
  
        for_each_pipe(dev_priv, i) {
                error->pipe[i].power_domain_on =
index cf98596c7ce1e7598de76ad1cf1bcaa3407c8d65,82e1c500ec204616b1a08ad569808cbd15f37617..247c60e6bed27a208599b12d018c3141a3995dee
@@@ -18,6 -18,7 +18,7 @@@
  #include <drm/drm_atomic_helper.h>
  #include <drm/drm_fb_cma_helper.h>
  #include <drm/drm_gem_cma_helper.h>
+ #include <drm/drm_gem_framebuffer_helper.h>
  #include <drm/drm_plane_helper.h>
  
  #include "video/imx-ipu-v3.h"
@@@ -496,27 -497,6 +497,27 @@@ static int ipu_chan_assign_axi_id(int i
        }
  }
  
 +static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride,
 +                               u8 *burstsize, u8 *num_bursts)
 +{
 +      const unsigned int width_bytes = width * cpp;
 +      unsigned int npb, bursts;
 +
 +      /* Maximum number of pixels per burst without overshooting stride */
 +      for (npb = 64 / cpp; npb > 0; --npb) {
 +              if (round_up(width_bytes, npb * cpp) <= stride)
 +                      break;
 +      }
 +      *burstsize = npb;
 +
 +      /* Maximum number of consecutive bursts without overshooting stride */
 +      for (bursts = 8; bursts > 1; bursts /= 2) {
 +              if (round_up(width_bytes, npb * cpp * bursts) <= stride)
 +                      break;
 +      }
 +      *num_bursts = bursts;
 +}
 +
  static void ipu_plane_atomic_update(struct drm_plane *plane,
                                    struct drm_plane_state *old_state)
  {
        unsigned long alpha_eba = 0;
        enum ipu_color_space ics;
        unsigned int axi_id = 0;
 +      const struct drm_format_info *info;
 +      u8 burstsize, num_bursts;
 +      u32 width, height;
        int active;
  
        if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
                ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
                                          drm_rect_width(&state->src) >> 16,
                                          drm_rect_height(&state->src) >> 16,
 -                                        state->fb->pitches[0],
 -                                        state->fb->format->format, &eba);
 +                                        fb->pitches[0],
 +                                        fb->format->format, &eba);
        }
  
        if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
                return;
        }
  
 +      ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
        switch (ipu_plane->dp_flow) {
        case IPU_DP_FLOW_SYNC_BG:
 -              ipu_dp_setup_channel(ipu_plane->dp,
 -                                      IPUV3_COLORSPACE_RGB,
 -                                      IPUV3_COLORSPACE_RGB);
 +              ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
                ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
                break;
        case IPU_DP_FLOW_SYNC_FG:
 -              ics = ipu_drm_fourcc_to_colorspace(state->fb->format->format);
                ipu_dp_setup_channel(ipu_plane->dp, ics,
                                        IPUV3_COLORSPACE_UNKNOWN);
                /* Enable local alpha on partial plane */
 -              switch (state->fb->format->format) {
 +              switch (fb->format->format) {
                case DRM_FORMAT_ARGB1555:
                case DRM_FORMAT_ABGR1555:
                case DRM_FORMAT_RGBA5551:
  
        ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
  
 +      width = drm_rect_width(&state->src) >> 16;
 +      height = drm_rect_height(&state->src) >> 16;
 +      info = drm_format_info(fb->format->format);
 +      ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
 +                           &burstsize, &num_bursts);
 +
        ipu_cpmem_zero(ipu_plane->ipu_ch);
 -      ipu_cpmem_set_resolution(ipu_plane->ipu_ch,
 -                               drm_rect_width(&state->src) >> 16,
 -                               drm_rect_height(&state->src) >> 16);
 -      ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->format->format);
 +      ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height);
 +      ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format);
 +      ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize);
        ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
        ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
 -      ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
 +      ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
        ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
 +
        switch (fb->format->format) {
        case DRM_FORMAT_YUV420:
        case DRM_FORMAT_YVU420:
        case DRM_FORMAT_RGBX8888_A8:
        case DRM_FORMAT_BGRX8888_A8:
                alpha_eba = drm_plane_state_to_eba(state, 1);
 +              num_bursts = 0;
  
                dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d",
                        eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16);
                ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
                ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
                ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1);
 -              ipu_cpmem_set_stride(ipu_plane->alpha_ch,
 -                                   state->fb->pitches[1]);
 +              ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]);
                ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16);
                ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba);
                ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba);
        }
        ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
        ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
 +      ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
        ipu_plane_enable(ipu_plane);
  }
  
  static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
-       .prepare_fb = drm_fb_cma_prepare_fb,
+       .prepare_fb = drm_gem_fb_prepare_fb,
        .atomic_check = ipu_plane_atomic_check,
        .atomic_disable = ipu_plane_atomic_disable,
        .atomic_update = ipu_plane_atomic_update,
index ff3d0f5efbb144465e802c3ab54df0e8b05b75f7,83cfcfefedcec356df5b86b46ba2ddc8b626dbcc..76d63de5921d1c0931eabae91ed0fd1b6ff9fcc4
@@@ -58,7 -58,7 +58,7 @@@ int rockchip_drm_dma_attach_device(stru
  
        ret = iommu_attach_device(private->domain, dev);
        if (ret) {
-               dev_err(dev, "Failed to attach iommu device\n");
+               DRM_DEV_ERROR(dev, "Failed to attach iommu device\n");
                return ret;
        }
  
@@@ -270,15 -270,11 +270,15 @@@ static void rockchip_drm_fb_resume(stru
  static int rockchip_drm_sys_suspend(struct device *dev)
  {
        struct drm_device *drm = dev_get_drvdata(dev);
 -      struct rockchip_drm_private *priv = drm->dev_private;
 +      struct rockchip_drm_private *priv;
 +
 +      if (!drm)
 +              return 0;
  
        drm_kms_helper_poll_disable(drm);
        rockchip_drm_fb_suspend(drm);
  
 +      priv = drm->dev_private;
        priv->state = drm_atomic_helper_suspend(drm);
        if (IS_ERR(priv->state)) {
                rockchip_drm_fb_resume(drm);
  static int rockchip_drm_sys_resume(struct device *dev)
  {
        struct drm_device *drm = dev_get_drvdata(dev);
 -      struct rockchip_drm_private *priv = drm->dev_private;
 +      struct rockchip_drm_private *priv;
 +
 +      if (!drm)
 +              return 0;
  
 +      priv = drm->dev_private;
        drm_atomic_helper_resume(drm, priv->state);
        rockchip_drm_fb_resume(drm);
        drm_kms_helper_poll_enable(drm);
@@@ -373,8 -365,9 +373,9 @@@ static int rockchip_drm_platform_of_pro
  
                iommu = of_parse_phandle(port->parent, "iommus", 0);
                if (!iommu || !of_device_is_available(iommu->parent)) {
-                       dev_dbg(dev, "no iommu attached for %pOF, using non-iommu buffers\n",
-                               port->parent);
+                       DRM_DEV_DEBUG(dev,
+                                     "no iommu attached for %pOF, using non-iommu buffers\n",
+                                     port->parent);
                        /*
                         * if there is a crtc not support iommu, force set all
                         * crtc use non-iommu buffer.
        }
  
        if (i == 0) {
-               dev_err(dev, "missing 'ports' property\n");
+               DRM_DEV_ERROR(dev, "missing 'ports' property\n");
                return -ENODEV;
        }
  
        if (!found) {
-               dev_err(dev, "No available vop found for display-subsystem.\n");
+               DRM_DEV_ERROR(dev,
+                             "No available vop found for display-subsystem.\n");
                return -ENODEV;
        }
  
@@@ -453,6 -447,8 +455,8 @@@ static int __init rockchip_drm_init(voi
  
        num_rockchip_sub_drivers = 0;
        ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+       ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
+                               CONFIG_ROCKCHIP_LVDS);
        ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
                                CONFIG_ROCKCHIP_ANALOGIX_DP);
        ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
index ace59651892fb636400088e2ac9136a0917d45dd,6eddb80860753453210ba306c319bd4f001e29a5..a2012638d5f77a8d7c23cf32db2d8c3370904e99
  #include "sun4i_framebuffer.h"
  #include "sun4i_tcon.h"
  
 +static void sun4i_drv_lastclose(struct drm_device *dev)
 +{
 +      struct sun4i_drv *drv = dev->dev_private;
 +
 +      drm_fbdev_cma_restore_mode(drv->fbdev);
 +}
 +
  DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
  
  static struct drm_driver sun4i_drv_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
  
        /* Generic Operations */
 +      .lastclose              = sun4i_drv_lastclose,
        .fops                   = &sun4i_drv_fops,
        .name                   = "sun4i-drm",
        .desc                   = "Allwinner sun4i Display Engine",
@@@ -106,11 -98,6 +106,6 @@@ static int sun4i_drv_bind(struct devic
                goto free_drm;
        }
  
-       /* drm_vblank_init calls kcalloc, which can fail */
-       ret = drm_vblank_init(drm, 1);
-       if (ret)
-               goto free_mem_region;
        drm_mode_config_init(drm);
  
        ret = component_bind_all(drm->dev, drm);
                goto cleanup_mode_config;
        }
  
+       /* drm_vblank_init calls kcalloc, which can fail */
+       ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+       if (ret)
+               goto free_mem_region;
        drm->irq_enabled = true;
  
        /* Remove early framebuffers (ie. simplefb) */
@@@ -200,11 -192,39 +200,39 @@@ static int compare_of(struct device *de
        return dev->of_node == data;
  }
  
+ /*
+  * The encoder drivers use drm_of_find_possible_crtcs to get upstream
+  * crtcs from the device tree using of_graph. For the results to be
+  * correct, encoders must be probed/bound after _all_ crtcs have been
+  * created. The existing code uses a depth first recursive traversal
+  * of the of_graph, which means the encoders downstream of the TCON
+  * get add right after the first TCON. The second TCON or CRTC will
+  * never be properly associated with encoders connected to it.
+  *
+  * Also, in a dual display pipeline setup, both frontends can feed
+  * either backend, and both backends can feed either TCON, we want
+  * all components of the same type to be added before the next type
+  * in the pipeline. Fortunately, the pipelines are perfectly symmetric,
+  * i.e. components of the same type are at the same depth when counted
+  * from the frontend. The only exception is the third pipeline in
+  * the A80 SoC, which we do not support anyway.
+  *
+  * Hence we can use a breadth first search traversal order to add
+  * components. We do not need to check for duplicates. The component
+  * matching system handles this for us.
+  */
+ struct endpoint_list {
+       struct device_node *node;
+       struct list_head list;
+ };
  static int sun4i_drv_add_endpoints(struct device *dev,
+                                  struct list_head *endpoints,
                                   struct component_match **match,
                                   struct device_node *node)
  {
        struct device_node *port, *ep, *remote;
+       struct endpoint_list *endpoint;
        int count = 0;
  
        /*
                        }
                }
  
-               /* Walk down our tree */
-               count += sun4i_drv_add_endpoints(dev, match, remote);
+               /* Add downstream nodes to the queue */
+               endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+               if (!endpoint) {
+                       of_node_put(remote);
+                       return -ENOMEM;
+               }
  
-               of_node_put(remote);
+               endpoint->node = remote;
+               list_add_tail(&endpoint->list, endpoints);
        }
  
        return count;
@@@ -277,7 -302,9 +310,9 @@@ static int sun4i_drv_probe(struct platf
  {
        struct component_match *match = NULL;
        struct device_node *np = pdev->dev.of_node;
-       int i, count = 0;
+       struct endpoint_list *endpoint, *endpoint_temp;
+       int i, ret, count = 0;
+       LIST_HEAD(endpoints);
  
        for (i = 0;; i++) {
                struct device_node *pipeline = of_parse_phandle(np,
                if (!pipeline)
                        break;
  
-               count += sun4i_drv_add_endpoints(&pdev->dev, &match,
-                                               pipeline);
-               of_node_put(pipeline);
+               endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+               if (!endpoint) {
+                       ret = -ENOMEM;
+                       goto err_free_endpoints;
+               }
  
-               DRM_DEBUG_DRIVER("Queued %d outputs on pipeline %d\n",
-                                count, i);
+               endpoint->node = pipeline;
+               list_add_tail(&endpoint->list, &endpoints);
+       }
+       list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+               /* process this endpoint */
+               ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match,
+                                             endpoint->node);
+               /* sun4i_drv_add_endpoints can fail to allocate memory */
+               if (ret < 0)
+                       goto err_free_endpoints;
+               count += ret;
+               /* delete and cleanup the current entry */
+               list_del(&endpoint->list);
+               of_node_put(endpoint->node);
+               kfree(endpoint);
        }
  
        if (count)
                                                       match);
        else
                return 0;
+ err_free_endpoints:
+       list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) {
+               list_del(&endpoint->list);
+               of_node_put(endpoint->node);
+               kfree(endpoint);
+       }
+       return ret;
  }
  
  static int sun4i_drv_remove(struct platform_device *pdev)
index 552c88ec16be38d82cf3041a73e9dd27d4aafd18,924c345820c0467f3346cf19cfbb9aac6c468aa6..5a219d1ccc261a17ec7e796282dc9935f2da648c
@@@ -37,6 -37,7 +37,7 @@@
  #define SUN4I_TCON0_CTL_TCON_ENABLE                   BIT(31)
  #define SUN4I_TCON0_CTL_CLK_DELAY_MASK                        GENMASK(8, 4)
  #define SUN4I_TCON0_CTL_CLK_DELAY(delay)              ((delay << 4) & SUN4I_TCON0_CTL_CLK_DELAY_MASK)
+ #define SUN4I_TCON0_CTL_SRC_SEL_MASK                  GENMASK(2, 0)
  
  #define SUN4I_TCON0_DCLK_REG                  0x44
  #define SUN4I_TCON0_DCLK_GATE_BIT                     (31)
@@@ -85,6 -86,7 +86,7 @@@
  #define SUN4I_TCON1_CTL_INTERLACE_ENABLE              BIT(20)
  #define SUN4I_TCON1_CTL_CLK_DELAY_MASK                        GENMASK(8, 4)
  #define SUN4I_TCON1_CTL_CLK_DELAY(delay)              ((delay << 4) & SUN4I_TCON1_CTL_CLK_DELAY_MASK)
+ #define SUN4I_TCON1_CTL_SRC_SEL_MASK                  GENMASK(1, 0)
  
  #define SUN4I_TCON1_BASIC0_REG                        0x94
  #define SUN4I_TCON1_BASIC0_X(width)                   ((((width) - 1) & 0xfff) << 16)
  struct sun4i_tcon_quirks {
        bool    has_unknown_mux; /* sun5i has undocumented mux */
        bool    has_channel_1;  /* a33 does not have channel 1 */
+       bool    needs_de_be_mux; /* sun6i needs mux to select backend */
  };
  
  struct sun4i_tcon {
@@@ -194,6 -197,8 +197,6 @@@ void sun4i_tcon_channel_enable(struct s
  void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
  
  /* Mode Related Controls */
 -void sun4i_tcon_switch_interlace(struct sun4i_tcon *tcon,
 -                               bool enable);
  void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
                        struct drm_encoder *encoder);
  void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
index 54fc38c3c3f1dbd4cd65f188e5ce8f0d29cc194a,e040c952accc0a9397630798e601eb03aff293bf..34b6bb34b0026715bedd2743c4c15efa71bd19cf
@@@ -715,24 -715,24 +715,24 @@@ struct drm_mode_atomic 
  struct drm_format_modifier_blob {
  #define FORMAT_BLOB_CURRENT 1
        /* Version of this blob format */
 -      u32 version;
 +      __u32 version;
  
        /* Flags */
 -      u32 flags;
 +      __u32 flags;
  
        /* Number of fourcc formats supported */
 -      u32 count_formats;
 +      __u32 count_formats;
  
        /* Where in this blob the formats exist (in bytes) */
 -      u32 formats_offset;
 +      __u32 formats_offset;
  
        /* Number of drm_format_modifiers */
 -      u32 count_modifiers;
 +      __u32 count_modifiers;
  
        /* Where in this blob the modifiers exist (in bytes) */
 -      u32 modifiers_offset;
 +      __u32 modifiers_offset;
  
 -      /* u32 formats[] */
 +      /* __u32 formats[] */
        /* struct drm_format_modifier modifiers[] */
  };
  
@@@ -749,9 -749,9 +749,9 @@@ struct drm_format_modifier 
         * If the number formats grew to 128, and formats 98-102 are
         * supported with the modifier:
         *
-        * 0x0000003c00000000 0000000000000000
+        * 0x0000007c00000000 0000000000000000
         *                ^
-        *                |__offset = 64, formats = 0x3c00000000
+        *                |__offset = 64, formats = 0x7c00000000
         *
         */
        __u64 formats;