linux/Documentation/gpu/drm-kms-helpers.rst

426 lines
10 KiB
ReStructuredText
Raw Normal View History

=============================
Mode Setting Helper Functions
=============================
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
:doc: overview
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
:internal:
.. _drm_atomic_helper:
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
Helper Functions Reference
--------------------------
.. kernel-doc:: include/drm/drm_atomic_helper.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
:export:
Atomic State Reset and Initialization
-------------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
:doc: atomic state reset and initialization
Atomic State Helper Reference
-----------------------------
.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
:export:
Simple KMS Helper Reference
===========================
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
:doc: overview
.. kernel-doc:: include/drm/drm_simple_kms_helper.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
: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:
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
:export:
format Helper Functions Reference
=================================
.. kernel-doc:: drivers/gpu/drm/drm_format_helper.c
:export:
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:
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:
.. _drm_bridges:
Bridges
=======
Overview
--------
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: overview
Bridge Operations
-----------------
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: bridge operations
drm: Add helper to create a connector for a chain of bridges Most bridge drivers create a DRM connector to model the connector at the output of the bridge. This model is historical and has worked pretty well so far, but causes several issues: - It prevents supporting more complex display pipelines where DRM connector operations are split over multiple components. For instance a pipeline with a bridge connected to the DDC signals to read EDID data, and another one connected to the HPD signal to detect connection and disconnection, will not be possible to support through this model. - It requires every bridge driver to implement similar connector handling code, resulting in code duplication. - It assumes that a bridge will either be wired to a connector or to another bridge, but doesn't support bridges that can be used in both positions very well (although there is some ad-hoc support for this in the analogix_dp bridge driver). In order to solve these issues, ownership of the connector needs to be moved to the display controller driver. To avoid code duplication in display controller drivers, add a new helper to create and manage a DRM connector backed by a chain of bridges. All connector operations are delegating to the appropriate bridge in the chain. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-21-laurent.pinchart@ideasonboard.com
2020-02-26 19:24:40 +08:00
Bridge Connector Helper
-----------------------
.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
:doc: overview
Bridge Helper Reference
-------------------------
.. kernel-doc:: include/drm/drm_bridge.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:export:
drm: Add helper to create a connector for a chain of bridges Most bridge drivers create a DRM connector to model the connector at the output of the bridge. This model is historical and has worked pretty well so far, but causes several issues: - It prevents supporting more complex display pipelines where DRM connector operations are split over multiple components. For instance a pipeline with a bridge connected to the DDC signals to read EDID data, and another one connected to the HPD signal to detect connection and disconnection, will not be possible to support through this model. - It requires every bridge driver to implement similar connector handling code, resulting in code duplication. - It assumes that a bridge will either be wired to a connector or to another bridge, but doesn't support bridges that can be used in both positions very well (although there is some ad-hoc support for this in the analogix_dp bridge driver). In order to solve these issues, ownership of the connector needs to be moved to the display controller driver. To avoid code duplication in display controller drivers, add a new helper to create and manage a DRM connector backed by a chain of bridges. All connector operations are delegating to the appropriate bridge in the chain. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-21-laurent.pinchart@ideasonboard.com
2020-02-26 19:24:40 +08:00
Bridge Connector Helper Reference
---------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_bridge_connector.c
:export:
Panel-Bridge Helper Reference
-----------------------------
.. kernel-doc:: drivers/gpu/drm/bridge/panel.c
:export:
.. _drm_panel_helper:
Panel Helper Reference
======================
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
:doc: drm panel
.. kernel-doc:: include/drm/drm_panel.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
:export:
.. kernel-doc:: drivers/gpu/drm/drm_panel_orientation_quirks.c
:export:
drm: Add helpers to kick off self refresh mode in drivers This patch adds a new drm helper library to help drivers implement self refresh. Drivers choosing to use it will register crtcs and will receive callbacks when it's time to enter or exit self refresh mode. In its current form, it has a timer which will trigger after a driver-specified amount of inactivity. When the timer triggers, the helpers will submit a new atomic commit to shut the refreshing pipe off. On the next atomic commit, the drm core will revert the self refresh state and bring everything back up to be actively driven. From the driver's perspective, this works like a regular disable/enable cycle. The driver need only check the 'self_refresh_active' state in crtc_state. It should initiate self refresh mode on the panel and enter an off or low-power state. Changes in v2: - s/psr/self_refresh/ (Daniel) - integrated the psr exit into the commit that wakes it up (Jose/Daniel) - made the psr state per-crtc (Jose/Daniel) Changes in v3: - Remove the self_refresh_(active|changed) from connector state (Daniel) - Simplify loop in drm_self_refresh_helper_alter_state (Daniel) - Improve self_refresh_aware comment (Daniel) - s/self_refresh_state/self_refresh_data/ (Daniel) Changes in v4: - Move docbook location below panel (Daniel) - Improve docbook with references and more detailed explanation (Daniel) - Instead of register/unregister, use init/cleanup (Daniel) Changes in v5: - Resolved conflict in drm_atomic_helper.c #include block - Resolved conflict in rst with HDCP helper docs Changes in v6: - Fix include ordering, clean up forward declarations (Sam) Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-2-sean@poorly.run Link to v2: https://patchwork.freedesktop.org/patch/msgid/20190326204509.96515-1-sean@poorly.run Link to v3: https://patchwork.freedesktop.org/patch/msgid/20190502194956.218441-6-sean@poorly.run Link to v4: https://patchwork.freedesktop.org/patch/msgid/20190508160920.144739-6-sean@poorly.run Link to v5: https://patchwork.freedesktop.org/patch/msgid/20190611160844.257498-6-sean@poorly.run Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Jose Souza <jose.souza@intel.com> Cc: Zain Wang <wzz@rock-chips.com> Cc: Tomasz Figa <tfiga@chromium.org> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Sam Ravnborg <sam@ravnborg.org> Tested-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20190612145026.191846-1-sean@poorly.run
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:
HDCP Helper Functions Reference
===============================
.. kernel-doc:: drivers/gpu/drm/drm_hdcp.c
:export:
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:
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:
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
--------
.. 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
-------------------
.. 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
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:
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:
drm/dsc: Add helpers for DSC picture parameter set infoframes According to Display Stream compression spec 1.2, the picture parameter set metadata is sent from source to sink device using the DP Secondary data packet. An infoframe is formed for the PPS SDP header and PPS SDP payload bytes. This patch adds helpers to fill the PPS SDP header and PPS SDP payload according to the DSC 1.2 specification. v7: * Use BUILD_BUG_ON() to protect changing struct size (Ville) * Remove typecaseting (Ville) * Include byteorder.h in drm_dsc.c (Ville) * Correct kernel doc spacing (Anusha) v6: * Use proper sequence points for breaking down the assignments (Chris Wilson) * Use SPDX identifier v5: Do not use bitfields for DRM structs (Jani N) v4: * Use DSC constants for params that dont change across configurations v3: * Add reference to added kernel-docs in Documentation/gpu/drm-kms-helpers.rst (Daniel Vetter) v2: * Add EXPORT_SYMBOL for the drm functions (Manasi) Cc: dri-devel@lists.freedesktop.org Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Ville Syrjala <ville.syrjala@linux.intel.com> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com> Cc: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Manasi Navare <manasi.d.navare@intel.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Reviewed-by: Anusha Srivatsa <anusha.srivatsa@intel.com> Acked-by: Sean Paul <seanpaul@chromium.org> (For merging through drm-intel) Link: https://patchwork.freedesktop.org/patch/msgid/20181127214125.17658-5-manasi.d.navare@intel.com
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:
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:
EDID Helper Functions Reference
===============================
.. kernel-doc:: include/drm/drm_edid.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_edid.c
:export:
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:
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:
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:
Flip-work Helper Reference
==========================
.. kernel-doc:: include/drm/drm_flip_work.h
:doc: flip utils
.. kernel-doc:: include/drm/drm_flip_work.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
:export:
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:
OF/DT Helpers
=============
.. kernel-doc:: drivers/gpu/drm/drm_of.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_of.c
:export:
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:
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: