linux/drivers
Daniel Vetter 9128b040eb drm/i915: Fix modeset state confusion in the load detect code
This is a tricky story of the new atomic state handling and the legacy
code fighting over each another. The bug at hand is an underrun of the
framebuffer reference with subsequent hilarity caused by the load
detect code. Which is peculiar since the the exact same code works
fine as the implementation of the legacy setcrtc ioctl.

Let's look at the ingredients:

- Currently our code is a crazy mix of legacy modeset interfaces to
  set the parameters and half-baked atomic state tracking underneath.
  While this transition is going we're using the transitional plane
  helpers to update the atomic side (drm_plane_helper_disable/update
  and friends), i.e. plane->state->fb. Since the state structure owns
  the fb those functions take care of that themselves.

  The legacy state (specifically crtc->primary->fb) is still managed
  by the old code (and mostly by the drm core), with the fb reference
  counting done by callers (core drm for the ioctl or the i915 load
  detect code). The relevant commit is

  commit ea2c67bb4a
  Author: Matt Roper <matthew.d.roper@intel.com>
  Date:   Tue Dec 23 10:41:52 2014 -0800

      drm/i915: Move to atomic plane helpers (v9)

- drm_plane_helper_disable has special code to handle multiple calls
  in a row - it checks plane->crtc == NULL and bails out. This is to
  match the proper atomic implementation which needs the crtc to get
  at the implied locking context atomic updates always need. See

  commit acf24a395c
  Author: Daniel Vetter <daniel.vetter@ffwll.ch>
  Date:   Tue Jul 29 15:33:05 2014 +0200

      drm/plane-helper: transitional atomic plane helpers

- The universal plane code split out the implicit primary plane from
  the CRTC into it's own full-blown drm_plane object. As part of that
  the setcrtc ioctl (which updated both the crtc mode and primary
  plane) learned to set crtc->primary->crtc on modeset to make sure
  the plane->crtc assignments statate up to date in

  commit e13161af80
  Author: Matt Roper <matthew.d.roper@intel.com>
  Date:   Tue Apr 1 15:22:38 2014 -0700

      drm: Add drm_crtc_init_with_planes() (v2)

  Unfortunately we've forgotten to update the load detect code. Which
  wasn't a problem since the load detect modeset is temporary and
  always undone before we drop the locks.

- Finally there is a organically grown history (i.e. don't ask) around
  who sets the legacy plane->fb for the various driver entry points.
  Originally updating that was the drivers duty, but for almost all
  places we've moved that (plus updating the refcounts) into the core.
  Again the exception is the load detect code.

Taking all together the following happens:
- The load detect code doesn't set crtc->primary->crtc. This is only
  really an issue on crtcs never before used or when userspace
  explicitly disabled the primary plane.

- The plane helper glue code short-circuits because of that and leaves
  a non-NULL fb behind in plane->state->fb and plane->fb. The state
  fb isn't a real problem (it's properly refcounted on its own), it's
  just the canary.

- Load detect code drops the reference for that fb, but doesn't set
  plane->fb = NULL. This is ok since it's still living in that old
  world where drivers had to clear the pointer but the core/callers
  handled the refcounting.

- On the next modeset the drm core notices plane->fb and takes care of
  refcounting it properly by doing another unref. This drops the
  refcount to zero, leaving state->plane now pointing at freed memory.

- intel_plane_duplicate_state still assume it owns a reference to that
  very state->fb and bad things start to happen.

Fix this all by applying the same duct-tape as for the legacy setcrtc
ioctl code and set crtc->primary->crtc properly.

Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Paul Bolle <pebolle@tiscali.nl>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Matt Roper <matthew.d.roper@intel.com>
Reported-and-tested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: Paul Bolle <pebolle@tiscali.nl>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-03-03 09:04:33 -08:00
..
accessibility
acpi Additional power management and ACPI updates for v3.20-rc1 2015-02-21 13:40:41 -08:00
amba ARM: 8256/1: driver coamba: add device binding path 'driver_override' 2015-02-10 10:23:15 +00:00
android
ata Merge branch 'for-3.20/drivers' of git://git.kernel.dk/linux-block 2015-02-12 14:30:53 -08:00
atm
auxdisplay
base driver core patches for 3.20-rc1 2015-02-15 11:11:47 -08:00
bcma
block Merge branch 'for-linus' of git://git.kernel.dk/linux-block 2015-02-28 10:21:57 -08:00
bluetooth TTY/Serial driver patches for 3.20-rc1 2015-02-15 11:37:02 -08:00
bus ARM: SoC platform changes 2015-02-17 09:27:54 -08:00
cdrom
char ipmi: Fix a memory ordering issue 2015-02-19 20:58:42 -06:00
clk The clock framework changes for 3.20 contain the usual driver additions, 2015-02-21 12:30:30 -08:00
clocksource clocksource: pxa: Fix section mismatch 2015-02-25 10:28:55 +01:00
connector
coresight coresight: fix function etm_writel_cp14() parameter order 2015-02-04 10:42:55 -08:00
cpufreq Additional power management and ACPI updates for v3.20-rc1 2015-02-21 13:40:41 -08:00
cpuidle Merge branches 'pnp', 'pm-cpuidle' and 'pm-cpufreq' 2015-02-21 04:29:16 +01:00
crypto Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-02-18 08:49:20 -08:00
dca
devfreq Merge branches 'pm-cpufreq', 'pm-cpuidle', 'pm-devfreq', 'pm-opp' and 'pm-tools' 2015-02-13 21:39:06 +01:00
dio
dma Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-02-18 08:49:20 -08:00
dma-buf
edac * A fix to sb_edac for proper detection on SNB machines 2015-02-19 11:18:14 -08:00
eisa
extcon
firewire firewire: core: use correct vendor/model IDs 2015-02-02 21:56:03 +01:00
firmware Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-02-21 10:41:29 -08:00
fmc
gpio gpio: tps65912: fix wrong container_of arguments 2015-02-23 15:40:32 +01:00
gpu drm/i915: Fix modeset state confusion in the load detect code 2015-03-03 09:04:33 -08:00
hid HID: microsoft: Add ID for NE7K wireless keyboard 2015-02-23 15:28:40 +01:00
hsi
hv Char / Misc patches for 3.20-rc1 2015-02-15 10:48:44 -08:00
hwmon hwmon: (ads7828) Check return value of devm_regmap_init_i2c 2015-02-22 20:10:30 -08:00
hwspinlock
i2c Merge branch 'i2c/for-3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux 2015-02-21 12:41:50 -08:00
ide
idle intel_idle: Add ->enter_freeze callbacks 2015-02-15 19:40:09 +01:00
iio Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
infiniband Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-02-22 17:42:14 -08:00
input Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input 2015-02-21 12:59:04 -08:00
iommu IOMMU Updates for Linux v3.20 2015-02-12 09:16:56 -08:00
ipack
irqchip Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus 2015-02-21 19:41:38 -08:00
isdn Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
leds leds: leds-gpio: Pass on error codes unmodified 2015-02-02 14:36:10 -08:00
lguest OK, this has the big virtio 1.0 implementation, as specified by OASIS. 2015-02-18 09:24:01 -08:00
macintosh
mailbox Merge branch 'mailbox-devel' of git://git.linaro.org/landing-teams/working/fujitsu/integration 2015-02-11 12:56:40 -08:00
mcb mcb: Fix error path of mcb_pci_probe 2015-02-03 15:48:51 -08:00
md md: mark some attributes as pre-alloc 2015-02-25 11:38:46 +11:00
media mm: gup: use get_user_pages_unlocked 2015-02-11 17:06:05 -08:00
memory
memstick
message i2o: move to staging 2015-02-03 15:58:39 -08:00
mfd Changes to existing drivers: 2015-02-18 09:05:48 -08:00
misc Char / Misc patches for 3.20-rc1 2015-02-15 10:48:44 -08:00
mmc The clock framework changes for 3.20 contain the usual driver additions, 2015-02-21 12:30:30 -08:00
mtd MTD updates for 3.20-rc1 2015-02-18 08:01:44 -08:00
net Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
nfc NFC: nci: Move NFCEE discovery logic 2015-02-04 09:15:18 +01:00
ntb
nubus
of PCI updates for v3.20: 2015-02-18 09:43:46 -08:00
oprofile
parisc
parport
pci Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
pcmcia ARM: SoC driver updates 2015-02-17 09:38:59 -08:00
phy USB patches for 3.20-rc1 2015-02-15 10:24:55 -08:00
pinctrl This is the bulk of pin control changes for the v3.20 cycle: 2015-02-11 11:23:13 -08:00
platform Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-02-21 11:12:07 -08:00
pnp Merge branches 'pnp', 'pm-cpuidle' and 'pm-cpufreq' 2015-02-21 04:29:16 +01:00
power
powercap
pps
ps3
ptp
pwm pwm: tegra: Use NSEC_PER_SEC 2015-02-18 08:40:29 +01:00
rapidio Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-02-18 08:49:20 -08:00
ras
regulator Changes to existing drivers: 2015-02-18 09:05:48 -08:00
remoteproc
reset
rpmsg
rtc drivers/rtc/rtc-ds1685.c: fix conditional in ds1685_rtc_sysfs_time_regs_{show,store} 2015-02-28 09:57:51 -08:00
s390 Fairly small update, but there are some interesting new features. 2015-02-13 09:55:09 -08:00
sbus
scsi SCSI misc on 20150221 2015-02-21 19:16:42 -08:00
sfi
sh drivers: sh: Disable PM runtime for multi-platform r8a7740 with genpd 2015-02-24 07:26:12 +09:00
sn
soc ARM: SoC driver updates 2015-02-17 09:38:59 -08:00
spi Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
spmi
ssb treewide: Remove unnecessary SSB_DEVTABLE_END macro 2015-02-11 14:38:29 -08:00
staging Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-02-22 17:42:14 -08:00
target Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-02-21 13:21:19 -08:00
tc
thermal thermal: int340x_thermal: Ignore missing _ART, _TRT tables 2015-02-28 13:58:36 +08:00
thunderbolt
tty Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
uio
usb Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild 2015-02-19 10:36:45 -08:00
uwb USB patches for 3.20-rc1 2015-02-15 10:24:55 -08:00
vfio vfio-pci: Add device request interface 2015-02-10 12:38:14 -07:00
vhost Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-02-21 13:21:19 -08:00
video mm: gup: use get_user_pages_unlocked 2015-02-11 17:06:05 -08:00
virt
virtio virtio: don't set VIRTIO_CONFIG_S_DRIVER_OK twice. 2015-02-17 16:19:29 +10:30
vlynq
vme
w1
watchdog watchdog: bcm47xx_wdt.c: allow enabling on BCM5301X arch 2015-02-17 21:34:13 +01:00
xen xen-scsiback: mark pvscsi frontend request consumed only after last read 2015-02-23 16:30:25 +00:00
zorro
Kconfig i2o: move to staging 2015-02-03 15:58:39 -08:00
Makefile