linux-xiaomi-chiron/drivers
Lyude Paul ebcc0e6b50 drm/dp_mst: Introduce new refcounting scheme for mstbs and ports
The current way of handling refcounting in the DP MST helpers is really
confusing and probably just plain wrong because it's been hacked up many
times over the years without anyone actually going over the code and
seeing if things could be simplified.

To the best of my understanding, the current scheme works like this:
drm_dp_mst_port and drm_dp_mst_branch both have a single refcount. When
this refcount hits 0 for either of the two, they're removed from the
topology state, but not immediately freed. Both ports and branch devices
will reinitialize their kref once it's hit 0 before actually destroying
themselves. The intended purpose behind this is so that we can avoid
problems like not being able to free a remote payload that might still
be active, due to us having removed all of the port/branch device
structures in memory, as per:

commit 91a25e4631 ("drm/dp/mst: deallocate payload on port destruction")

Which may have worked, but then it caused use-after-free errors. Being
new to MST at the time, I tried fixing it;

commit 263efde31f ("drm/dp/mst: Get validated port ref in drm_dp_update_payload_part1()")

But, that was broken: both drm_dp_mst_port and drm_dp_mst_branch structs
are validated in almost every DP MST helper function. Simply put, this
means we go through the topology and try to see if the given
drm_dp_mst_branch or drm_dp_mst_port is still attached to something
before trying to use it in order to avoid dereferencing freed memory
(something that has happened a LOT in the past with this library).
Because of this it doesn't actually matter whether or not we keep keep
the ports and branches around in memory as that's not enough, because
any function that validates the branches and ports passed to it will
still reject them anyway since they're no longer in the topology
structure. So, use-after-free errors were fixed but payload deallocation
was completely broken.

Two years later, AMD informed me about this issue and I attempted to
come up with a temporary fix, pending a long-overdue cleanup of this
library:

commit c54c7374ff ("drm/dp_mst: Skip validating ports during destruction, just ref")

But then that introduced use-after-free errors, so I quickly reverted
it:

commit 9765635b30 ("Revert "drm/dp_mst: Skip validating ports during destruction, just ref"")

And in the process, learned that there is just no simple fix for this:
the design is just broken. Unfortunately, the usage of these helpers are
quite broken as well. Some drivers like i915 have been smart enough to
avoid accessing any kind of information from MST port structures, but
others like nouveau have assumed, understandably so, that
drm_dp_mst_port structures are normal and can just be accessed at any
time without worrying about use-after-free errors.

After a lot of discussion, me and Daniel Vetter came up with a better
idea to replace all of this.

To summarize, since this is documented far more indepth in the
documentation this patch introduces, we make it so that drm_dp_mst_port
and drm_dp_mst_branch structures have two different classes of
refcounts: topology_kref, and malloc_kref. topology_kref corresponds to
the lifetime of the given drm_dp_mst_port or drm_dp_mst_branch in it's
given topology. Once it hits zero, any associated connectors are removed
and the branch or port can no longer be validated. malloc_kref
corresponds to the lifetime of the memory allocation for the actual
structure, and will always be non-zero so long as the topology_kref is
non-zero. This gives us a way to allow callers to hold onto port and
branch device structures past their topology lifetime, and dramatically
simplifies the lifetimes of both structures. This also finally fixes the
port deallocation problem, properly.

Additionally: since this now means that we can keep ports and branch
devices allocated in memory for however long we need, we no longer need
a significant amount of the port validation that we currently do.

Additionally, there is one last scenario that this fixes, which couldn't
have been fixed properly beforehand:

- CPU1 unrefs port from topology (refcount 1->0)
- CPU2 refs port in topology(refcount 0->1)

Since we now can guarantee memory safety for ports and branches
as-needed, we also can make our main reference counting functions fix
this problem by using kref_get_unless_zero() internally so that topology
refcounts can only ever reach 0 once.

Changes since v4:
* Change the kernel-figure summary for dp-mst/topology-figure-1.dot a
  bit - danvet
* Remove figure numbers - danvet

Changes since v3:
* Remove rebase detritus - danvet
* Split out purely style changes into separate patches - hwentlan

Changes since v2:
* Fix commit message - checkpatch
* s/)-1/) - 1/g - checkpatch

Changes since v1:
* Remove forward declarations - danvet
* Move "Branch device and port refcounting" section from documentation
  into kernel-doc comments - danvet
* Export internal topology lifetime functions into their own section in
  the kernel-docs - danvet
* s/@/&/g for struct references in kernel-docs - danvet
* Drop the "when they are no longer being used" bits from the kernel
  docs - danvet
* Modify diagrams to show how the DRM driver interacts with the topology
  and payloads - danvet
* Make suggested documentation changes for
  drm_dp_mst_topology_get_mstb() and drm_dp_mst_topology_get_port() -
  danvet
* Better explain the relationship between malloc refs and topology krefs
  in the documentation for drm_dp_mst_topology_get_port() and
  drm_dp_mst_topology_get_mstb() - danvet
* Fix "See also" in drm_dp_mst_topology_get_mstb() - danvet
* Rename drm_dp_mst_topology_get_(port|mstb)() ->
  drm_dp_mst_topology_try_get_(port|mstb)() and
  drm_dp_mst_topology_ref_(port|mstb)() ->
  drm_dp_mst_topology_get_(port|mstb)() - danvet
* s/should/must in docs - danvet
* WARN_ON(refcount == 0) in topology_get_(mstb|port) - danvet
* Move kdocs for mstb/port structs inline - danvet
* Split drm_dp_get_last_connected_port_and_mstb() changes into their own
  commit - danvet

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Daniel Vetter <daniel@ffwll.ch>
Cc: David Airlie <airlied@redhat.com>
Cc: Jerry Zuo <Jerry.Zuo@amd.com>
Cc: Juston Li <juston.li@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190111005343.17443-7-lyude@redhat.com
2019-01-10 20:12:19 -05:00
..
accessibility
acpi ACPI / platform: Add SMB0001 HID to forbidden_id_list 2018-11-21 13:30:13 +01:00
amba
android
ata libata: blacklist SAMSUNG MZ7TD256HAFV-000L9 SSD 2018-11-12 12:44:19 -07:00
atm
auxdisplay
base
bcma
block for-linus-20181115 2018-11-16 09:31:59 -06:00
bluetooth
bus
cdrom
char
clk clk: qcom: gcc: Fix board clock node name 2018-11-09 14:13:55 -08:00
clocksource Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-11-11 16:41:50 -06:00
connector
cpufreq cpufreq: ti-cpufreq: Only register platform_device when supported 2018-11-19 11:26:06 +01:00
cpuidle ARM: cpuidle: Convert to use cpuidle_register|unregister() 2018-11-08 18:53:00 +01:00
crypto crypto: hisilicon - Fix reference after free of memories on error path 2018-11-09 17:35:43 +08:00
dax
dca
devfreq
dio
dma
dma-buf dma-buf: Change to use DEFINE_SHOW_ATTRIBUTE macro 2018-12-24 11:17:04 +01:00
edac
eisa
extcon
firewire
firmware efi: Permit calling efi_mem_reserve_persistent() from atomic context 2018-11-15 10:04:47 +01:00
fmc
fpga
fsi
gnss gnss: sirf: fix synchronous write timeout 2018-11-14 20:37:41 +01:00
gpio gpio: mockup: fix indicated direction 2018-11-16 23:06:29 +01:00
gpu drm/dp_mst: Introduce new refcounting scheme for mstbs and ports 2019-01-10 20:12:19 -05:00
hid Revert "HID: input: Create a utility class for counting scroll events" 2018-11-22 08:57:38 +01:00
hsi
hv Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up 2018-11-11 09:00:20 -08:00
hwmon hwmon: (ibmpowernv) Remove bogus __init annotations 2018-11-04 15:55:12 -08:00
hwspinlock
hwtracing
i2c i2c: nvidia-gpu: make pm_ops static 2018-11-09 17:56:44 +01:00
ide
idle
iio
infiniband
input
iommu iommu/vt-d: Use memunmap to free memremap 2018-11-22 17:02:21 +01:00
ipack
irqchip
isdn
leds LED fixes for 4.20-rc2 2018-11-08 17:49:04 -06:00
lightnvm
macintosh
mailbox
mcb
md
media Linux 4.20-rc4 2018-11-29 10:34:03 +10:00
memory
memstick
message
mfd
misc misc: atmel-ssc: Fix section annotation on atmel_ssc_get_driver_data 2018-11-11 09:13:19 -08:00
mmc mmc: sdhci-pci: Workaround GLK firmware failing to restore the tuning value 2018-11-19 14:11:07 +01:00
mtd mtd: spi-nor: fix selection of uniform erase type in flexible conf 2018-11-20 14:26:59 +01:00
mux
net net: gemini: Fix copy/paste error 2018-11-23 22:35:38 -08:00
nfc
ntb
nubus
nvdimm
nvme nvme-fc: resolve io failures during connect 2018-11-15 11:37:55 +01:00
nvmem nvmem: core: fix regression in of_nvmem_cell_get() 2018-11-11 09:15:29 -08:00
of Devicetree fixes for 4.20-rc: 2018-11-09 16:41:58 -06:00
opp opp: ti-opp-supply: Correct the supply in _get_optimal_vdd_voltage call 2018-11-13 09:40:29 +05:30
oprofile
parisc
parport
pci Revert "ACPI/PCI: Pay attention to device-specific _PXM node values" 2018-11-13 08:38:17 -06:00
pcmcia
perf
phy
pinctrl pinctrl: meson: fix meson8b ao pull register bits 2018-11-05 09:33:22 +01:00
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc rtc: pcf2127: fix a kmemleak caused in pcf2127_i2c_gather_write 2018-11-07 17:13:56 +01:00
s390 s390/ism: clear dmbe_mask bit before SMC IRQ handling 2018-11-14 14:21:20 -08:00
sbus
scsi SCSI fixes on 20181121 2018-11-22 08:31:46 -08:00
sfi
sh
siox
slimbus slimbus: ngd: remove unnecessary check 2018-11-07 14:59:28 +01:00
sn
soc
soundwire
spi
spmi
ssb
staging Linux 4.20-rc4 2018-11-29 10:34:03 +10:00
target scsi: target/core: Avoid that a kernel oops is triggered when COMPARE AND WRITE fails 2018-11-05 22:16:00 -05:00
tc
tee
thermal
thunderbolt
tty TTY/Serial fixes for 4.20-rc2 2018-11-10 13:32:14 -06:00
uio uio: Fix an Oops on load 2018-11-11 09:21:46 -08:00
usb USB fixes for 4.20-rc4 2018-11-22 08:39:29 -08:00
uwb
vfio
vhost
video drm-misc-next for v4.21, part 1: 2018-11-19 10:40:33 +10:00
virt
virtio
visorbus
vlynq
vme
w1
watchdog
xen xen: fixes for 4.20-rc2 2018-11-10 08:58:48 -06:00
zorro
Kconfig
Makefile