2016-06-21 19:49:02 +08:00
|
|
|
=============================
|
|
|
|
Mode Setting Helper Functions
|
|
|
|
=============================
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
The DRM subsystem aims for a strong separation between core code and helper
|
|
|
|
libraries. Core code takes care of general setup and teardown and decoding
|
|
|
|
userspace requests to kernel internal objects. Everything else is handled by a
|
|
|
|
large set of helper libraries, which can be combined freely to pick and choose
|
|
|
|
for each driver what fits, and avoid shared code where special behaviour is
|
|
|
|
needed.
|
|
|
|
|
|
|
|
This distinction between core code and helpers is especially strong in the
|
|
|
|
modesetting code, where there's a shared userspace ABI for all drivers. This is
|
|
|
|
in contrast to the render side, where pretty much everything (with very few
|
|
|
|
exceptions) can be considered optional helper code.
|
|
|
|
|
|
|
|
There are a few areas these helpers can grouped into:
|
|
|
|
|
|
|
|
* Helpers to implement modesetting. The important ones here are the atomic
|
|
|
|
helpers. Old drivers still often use the legacy CRTC helpers. They both share
|
|
|
|
the same set of common helper vtables. For really simple drivers (anything
|
|
|
|
that would have been a great fit in the deprecated fbdev subsystem) there's
|
|
|
|
also the simple display pipe helpers.
|
|
|
|
|
|
|
|
* There's a big pile of helpers for handling outputs. First the generic bridge
|
|
|
|
helpers for handling encoder and transcoder IP blocks. Second the panel helpers
|
|
|
|
for handling panel-related information and logic. Plus then a big set of
|
|
|
|
helpers for the various sink standards (DisplayPort, HDMI, MIPI DSI). Finally
|
|
|
|
there's also generic helpers for handling output probing, and for dealing with
|
|
|
|
EDIDs.
|
|
|
|
|
|
|
|
* The last group of helpers concerns itself with the frontend side of a display
|
|
|
|
pipeline: Planes, handling rectangles for visibility checking and scissoring,
|
|
|
|
flip queues and assorted bits.
|
|
|
|
|
|
|
|
Modeset Helper Reference for Common Vtables
|
|
|
|
===========================================
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
2017-03-02 23:16:36 +08:00
|
|
|
:doc: overview
|
2016-08-13 04:48:38 +08:00
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
2017-03-02 23:16:36 +08:00
|
|
|
:internal:
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2017-03-02 23:16:38 +08:00
|
|
|
.. _drm_atomic_helper:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
Atomic Modeset Helper Functions Reference
|
|
|
|
=========================================
|
|
|
|
|
|
|
|
Overview
|
|
|
|
--------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
Implementing Asynchronous Atomic Commit
|
|
|
|
---------------------------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
|
|
|
:doc: implementing nonblocking commit
|
|
|
|
|
2018-10-05 04:24:28 +08:00
|
|
|
Helper Functions Reference
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_atomic_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
Atomic State Reset and Initialization
|
|
|
|
-------------------------------------
|
|
|
|
|
2018-10-05 04:24:28 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
|
2016-06-21 19:49:02 +08:00
|
|
|
:doc: atomic state reset and initialization
|
|
|
|
|
2018-10-05 04:24:28 +08:00
|
|
|
Atomic State Helper Reference
|
|
|
|
-----------------------------
|
2016-11-22 01:18:02 +08:00
|
|
|
|
2018-10-05 04:24:28 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
|
2016-06-21 19:49:02 +08:00
|
|
|
:export:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
Simple KMS Helper Reference
|
|
|
|
===========================
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2017-03-02 23:16:36 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_simple_kms_helper.h
|
|
|
|
:internal:
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
2016-06-21 19:49:02 +08:00
|
|
|
:export:
|
|
|
|
|
|
|
|
fbdev Helper Functions Reference
|
|
|
|
================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
|
|
|
|
:doc: fbdev helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_fb_helper.h
|
|
|
|
:internal:
|
|
|
|
|
2017-03-02 23:16:36 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
|
|
|
|
:export:
|
|
|
|
|
2019-04-16 17:05:33 +08:00
|
|
|
format Helper Functions Reference
|
|
|
|
=================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_format_helper.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
Framebuffer CMA Helper Functions Reference
|
|
|
|
==========================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
|
|
|
:doc: framebuffer cma helper functions
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
|
|
|
:export:
|
|
|
|
|
2018-07-09 16:40:13 +08:00
|
|
|
Framebuffer GEM Helper Reference
|
|
|
|
================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
|
|
|
|
:export:
|
|
|
|
|
2019-01-12 00:40:47 +08:00
|
|
|
.. _drm_bridges:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
Bridges
|
|
|
|
=======
|
|
|
|
|
|
|
|
Overview
|
|
|
|
--------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
|
|
|
:doc: overview
|
|
|
|
|
2020-02-26 19:24:26 +08:00
|
|
|
Bridge Operations
|
|
|
|
-----------------
|
2016-08-13 04:48:38 +08:00
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
2020-02-26 19:24:26 +08:00
|
|
|
:doc: bridge operations
|
2016-08-13 04:48:38 +08:00
|
|
|
|
2020-02-26 19:24:40 +08:00
|
|
|
Bridge Connector Helper
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
|
|
|
|
:doc: overview
|
|
|
|
|
2016-09-01 00:09:05 +08:00
|
|
|
|
|
|
|
Bridge Helper Reference
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_bridge.h
|
|
|
|
:internal:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
|
|
|
:export:
|
|
|
|
|
2020-02-26 19:24:40 +08:00
|
|
|
Bridge Connector Helper Reference
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
|
|
|
|
:export:
|
|
|
|
|
2017-06-03 04:25:14 +08:00
|
|
|
Panel-Bridge Helper Reference
|
|
|
|
-----------------------------
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/bridge/panel.c
|
|
|
|
:export:
|
|
|
|
|
2017-03-02 23:16:35 +08:00
|
|
|
.. _drm_panel_helper:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
Panel Helper Reference
|
|
|
|
======================
|
|
|
|
|
2017-03-02 23:16:36 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
|
|
|
:doc: drm panel
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_panel.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
|
|
|
:export:
|
|
|
|
|
2017-11-26 03:35:48 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_panel_orientation_quirks.c
|
|
|
|
:export:
|
|
|
|
|
2019-06-12 22:50:19 +08:00
|
|
|
Panel Self Refresh Helper Reference
|
|
|
|
===================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c
|
|
|
|
:export:
|
|
|
|
|
2019-05-08 00:27:38 +08:00
|
|
|
HDCP Helper Functions Reference
|
|
|
|
===============================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_hdcp.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
Display Port Helper Functions Reference
|
|
|
|
=======================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
|
|
|
:doc: dp helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_dp_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
|
|
|
:export:
|
|
|
|
|
2018-07-11 21:29:08 +08:00
|
|
|
Display Port CEC Helper Functions Reference
|
|
|
|
===========================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
|
|
|
|
:doc: dp cec helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
Display Port Dual Mode Adaptor Helper Functions Reference
|
|
|
|
=========================================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
|
|
|
:doc: dp dual mode helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_dp_dual_mode_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
|
|
|
:export:
|
|
|
|
|
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 91a25e463130 ("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 263efde31f97 ("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 c54c7374ff44 ("drm/dp_mst: Skip validating ports during destruction, just ref")
But then that introduced use-after-free errors, so I quickly reverted
it:
commit 9765635b3075 ("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-11 08:53:29 +08:00
|
|
|
Display Port MST Helpers
|
|
|
|
========================
|
|
|
|
|
|
|
|
Overview
|
|
|
|
--------
|
2016-06-21 19:49:02 +08:00
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
|
|
|
:doc: dp mst helper
|
|
|
|
|
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 91a25e463130 ("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 263efde31f97 ("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 c54c7374ff44 ("drm/dp_mst: Skip validating ports during destruction, just ref")
But then that introduced use-after-free errors, so I quickly reverted
it:
commit 9765635b3075 ("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-11 08:53:29 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
|
|
|
:doc: Branch device and port refcounting
|
|
|
|
|
|
|
|
Functions Reference
|
|
|
|
-------------------
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_dp_mst_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
|
|
|
:export:
|
|
|
|
|
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 91a25e463130 ("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 263efde31f97 ("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 c54c7374ff44 ("drm/dp_mst: Skip validating ports during destruction, just ref")
But then that introduced use-after-free errors, so I quickly reverted
it:
commit 9765635b3075 ("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-11 08:53:29 +08:00
|
|
|
Topology Lifetime Internals
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
These functions aren't exported to drivers, but are documented here to help make
|
|
|
|
the MST topology helpers easier to understand
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
|
|
|
:functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb
|
|
|
|
drm_dp_mst_topology_put_mstb
|
|
|
|
drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
|
|
|
|
drm_dp_mst_topology_put_port
|
|
|
|
drm_dp_mst_get_mstb_malloc drm_dp_mst_put_mstb_malloc
|
|
|
|
|
2019-07-22 18:43:11 +08:00
|
|
|
MIPI DBI Helper Functions Reference
|
|
|
|
===================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dbi.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_mipi_dbi.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dbi.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
MIPI DSI Helper Functions Reference
|
|
|
|
===================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
|
|
|
|
:doc: dsi helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_mipi_dsi.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
|
|
|
|
:export:
|
|
|
|
|
2018-11-28 05:41:07 +08:00
|
|
|
Display Stream Compression Helper Functions Reference
|
|
|
|
=====================================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dsc.c
|
|
|
|
:doc: dsc helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_dsc.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_dsc.c
|
|
|
|
:export:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
Output Probing Helper Functions Reference
|
|
|
|
=========================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
|
|
|
:doc: output probing helper overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
EDID Helper Functions Reference
|
|
|
|
===============================
|
|
|
|
|
2016-09-01 00:09:06 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_edid.h
|
|
|
|
:internal:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_edid.c
|
|
|
|
:export:
|
|
|
|
|
2017-03-13 19:23:59 +08:00
|
|
|
SCDC Helper Functions Reference
|
|
|
|
===============================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c
|
|
|
|
:doc: scdc helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_scdc_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_scdc_helper.c
|
|
|
|
:export:
|
|
|
|
|
2016-06-21 19:49:02 +08:00
|
|
|
HDMI Infoframes Helper Reference
|
|
|
|
================================
|
|
|
|
|
|
|
|
Strictly speaking this is not a DRM helper library but generally useable
|
|
|
|
by any driver interfacing with HDMI outputs like v4l or alsa drivers.
|
|
|
|
But it nicely fits into the overall topic of mode setting helper
|
|
|
|
libraries and hence is also included here.
|
|
|
|
|
|
|
|
.. kernel-doc:: include/linux/hdmi.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/video/hdmi.c
|
|
|
|
:export:
|
|
|
|
|
2019-01-31 00:30:04 +08:00
|
|
|
Rectangle Utilities Reference
|
|
|
|
=============================
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_rect.h
|
|
|
|
:doc: rect utils
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_rect.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_rect.c
|
|
|
|
:export:
|
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
Flip-work Helper Reference
|
|
|
|
==========================
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_flip_work.h
|
|
|
|
:doc: flip utils
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: include/drm/drm_flip_work.h
|
|
|
|
:internal:
|
2016-06-21 19:49:02 +08:00
|
|
|
|
2016-08-13 04:48:38 +08:00
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
|
2016-06-21 19:49:02 +08:00
|
|
|
:export:
|
|
|
|
|
2016-08-13 04:48:39 +08:00
|
|
|
Auxiliary Modeset Helpers
|
|
|
|
=========================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
|
|
|
|
:doc: aux kms helpers
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
|
|
|
|
:export:
|
2017-08-13 21:31:44 +08:00
|
|
|
|
2018-07-09 16:40:14 +08:00
|
|
|
OF/DT Helpers
|
|
|
|
=============
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_of.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_of.c
|
|
|
|
:export:
|
|
|
|
|
2017-12-15 04:30:54 +08:00
|
|
|
Legacy Plane Helper Reference
|
|
|
|
=============================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
|
|
|
:export:
|
|
|
|
|
|
|
|
Legacy CRTC/Modeset Helper Functions Reference
|
|
|
|
==============================================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
|
|
|
:export:
|
2019-03-13 08:43:44 +08:00
|
|
|
|
|
|
|
SHMEM GEM Helper Reference
|
|
|
|
==========================
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
|
|
|
:doc: overview
|
|
|
|
|
|
|
|
.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
|
|
|
|
:internal:
|
|
|
|
|
|
|
|
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
|
|
|
:export:
|