aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_dp_mst_topology.c
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2019-01-10 19:53:29 -0500
committerLyude Paul <lyude@redhat.com>2019-01-10 20:12:19 -0500
commitebcc0e6b509108b4a67daa4c55809a05ab7f4b77 (patch)
tree014d480572e9f7209710cae1e3595c19ca14b2fc /drivers/gpu/drm/drm_dp_mst_topology.c
parentd0757afd00d71dca98268d09884dc6248743d8ce (diff)
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
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c458
1 files changed, 395 insertions, 63 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 074e985093ca..796985609933 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -850,46 +850,212 @@ static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
850 if (lct > 1) 850 if (lct > 1)
851 memcpy(mstb->rad, rad, lct / 2); 851 memcpy(mstb->rad, rad, lct / 2);
852 INIT_LIST_HEAD(&mstb->ports); 852 INIT_LIST_HEAD(&mstb->ports);
853 kref_init(&mstb->kref); 853 kref_init(&mstb->topology_kref);
854 kref_init(&mstb->malloc_kref);
854 return mstb; 855 return mstb;
855} 856}
856 857
857static void drm_dp_free_mst_port(struct kref *kref);
858
859static void drm_dp_free_mst_branch_device(struct kref *kref) 858static void drm_dp_free_mst_branch_device(struct kref *kref)
860{ 859{
861 struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); 860 struct drm_dp_mst_branch *mstb =
862 if (mstb->port_parent) { 861 container_of(kref, struct drm_dp_mst_branch, malloc_kref);
863 if (list_empty(&mstb->port_parent->next)) 862
864 kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port); 863 if (mstb->port_parent)
865 } 864 drm_dp_mst_put_port_malloc(mstb->port_parent);
865
866 kfree(mstb); 866 kfree(mstb);
867} 867}
868 868
869/**
870 * DOC: Branch device and port refcounting
871 *
872 * Topology refcount overview
873 * ~~~~~~~~~~~~~~~~~~~~~~~~~~
874 *
875 * The refcounting schemes for &struct drm_dp_mst_branch and &struct
876 * drm_dp_mst_port are somewhat unusual. Both ports and branch devices have
877 * two different kinds of refcounts: topology refcounts, and malloc refcounts.
878 *
879 * Topology refcounts are not exposed to drivers, and are handled internally
880 * by the DP MST helpers. The helpers use them in order to prevent the
881 * in-memory topology state from being changed in the middle of critical
882 * operations like changing the internal state of payload allocations. This
883 * means each branch and port will be considered to be connected to the rest
884 * of the topology until it's topology refcount reaches zero. Additionally,
885 * for ports this means that their associated &struct drm_connector will stay
886 * registered with userspace until the port's refcount reaches 0.
887 *
888 * Malloc refcount overview
889 * ~~~~~~~~~~~~~~~~~~~~~~~~
890 *
891 * Malloc references are used to keep a &struct drm_dp_mst_port or &struct
892 * drm_dp_mst_branch allocated even after all of its topology references have
893 * been dropped, so that the driver or MST helpers can safely access each
894 * branch's last known state before it was disconnected from the topology.
895 * When the malloc refcount of a port or branch reaches 0, the memory
896 * allocation containing the &struct drm_dp_mst_branch or &struct
897 * drm_dp_mst_port respectively will be freed.
898 *
899 * For &struct drm_dp_mst_branch, malloc refcounts are not currently exposed
900 * to drivers. As of writing this documentation, there are no drivers that
901 * have a usecase for accessing &struct drm_dp_mst_branch outside of the MST
902 * helpers. Exposing this API to drivers in a race-free manner would take more
903 * tweaking of the refcounting scheme, however patches are welcome provided
904 * there is a legitimate driver usecase for this.
905 *
906 * Refcount relationships in a topology
907 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
908 *
909 * Let's take a look at why the relationship between topology and malloc
910 * refcounts is designed the way it is.
911 *
912 * .. kernel-figure:: dp-mst/topology-figure-1.dot
913 *
914 * An example of topology and malloc refs in a DP MST topology with two
915 * active payloads. Topology refcount increments are indicated by solid
916 * lines, and malloc refcount increments are indicated by dashed lines.
917 * Each starts from the branch which incremented the refcount, and ends at
918 * the branch to which the refcount belongs to, i.e. the arrow points the
919 * same way as the C pointers used to reference a structure.
920 *
921 * As you can see in the above figure, every branch increments the topology
922 * refcount of it's children, and increments the malloc refcount of it's
923 * parent. Additionally, every payload increments the malloc refcount of it's
924 * assigned port by 1.
925 *
926 * So, what would happen if MSTB #3 from the above figure was unplugged from
927 * the system, but the driver hadn't yet removed payload #2 from port #3? The
928 * topology would start to look like the figure below.
929 *
930 * .. kernel-figure:: dp-mst/topology-figure-2.dot
931 *
932 * Ports and branch devices which have been released from memory are
933 * colored grey, and references which have been removed are colored red.
934 *
935 * Whenever a port or branch device's topology refcount reaches zero, it will
936 * decrement the topology refcounts of all its children, the malloc refcount
937 * of its parent, and finally its own malloc refcount. For MSTB #4 and port
938 * #4, this means they both have been disconnected from the topology and freed
939 * from memory. But, because payload #2 is still holding a reference to port
940 * #3, port #3 is removed from the topology but it's &struct drm_dp_mst_port
941 * is still accessible from memory. This also means port #3 has not yet
942 * decremented the malloc refcount of MSTB #3, so it's &struct
943 * drm_dp_mst_branch will also stay allocated in memory until port #3's
944 * malloc refcount reaches 0.
945 *
946 * This relationship is necessary because in order to release payload #2, we
947 * need to be able to figure out the last relative of port #3 that's still
948 * connected to the topology. In this case, we would travel up the topology as
949 * shown below.
950 *
951 * .. kernel-figure:: dp-mst/topology-figure-3.dot
952 *
953 * And finally, remove payload #2 by communicating with port #2 through
954 * sideband transactions.
955 */
956
957/**
958 * drm_dp_mst_get_mstb_malloc() - Increment the malloc refcount of a branch
959 * device
960 * @mstb: The &struct drm_dp_mst_branch to increment the malloc refcount of
961 *
962 * Increments &drm_dp_mst_branch.malloc_kref. When
963 * &drm_dp_mst_branch.malloc_kref reaches 0, the memory allocation for @mstb
964 * will be released and @mstb may no longer be used.
965 *
966 * See also: drm_dp_mst_put_mstb_malloc()
967 */
968static void
969drm_dp_mst_get_mstb_malloc(struct drm_dp_mst_branch *mstb)
970{
971 kref_get(&mstb->malloc_kref);
972 DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->malloc_kref));
973}
974
975/**
976 * drm_dp_mst_put_mstb_malloc() - Decrement the malloc refcount of a branch
977 * device
978 * @mstb: The &struct drm_dp_mst_branch to decrement the malloc refcount of
979 *
980 * Decrements &drm_dp_mst_branch.malloc_kref. When
981 * &drm_dp_mst_branch.malloc_kref reaches 0, the memory allocation for @mstb
982 * will be released and @mstb may no longer be used.
983 *
984 * See also: drm_dp_mst_get_mstb_malloc()
985 */
986static void
987drm_dp_mst_put_mstb_malloc(struct drm_dp_mst_branch *mstb)
988{
989 DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->malloc_kref) - 1);
990 kref_put(&mstb->malloc_kref, drm_dp_free_mst_branch_device);
991}
992
993static void drm_dp_free_mst_port(struct kref *kref)
994{
995 struct drm_dp_mst_port *port =
996 container_of(kref, struct drm_dp_mst_port, malloc_kref);
997
998 drm_dp_mst_put_mstb_malloc(port->parent);
999 kfree(port);
1000}
1001
1002/**
1003 * drm_dp_mst_get_port_malloc() - Increment the malloc refcount of an MST port
1004 * @port: The &struct drm_dp_mst_port to increment the malloc refcount of
1005 *
1006 * Increments &drm_dp_mst_port.malloc_kref. When &drm_dp_mst_port.malloc_kref
1007 * reaches 0, the memory allocation for @port will be released and @port may
1008 * no longer be used.
1009 *
1010 * Because @port could potentially be freed at any time by the DP MST helpers
1011 * if &drm_dp_mst_port.malloc_kref reaches 0, including during a call to this
1012 * function, drivers that which to make use of &struct drm_dp_mst_port should
1013 * ensure that they grab at least one main malloc reference to their MST ports
1014 * in &drm_dp_mst_topology_cbs.add_connector. This callback is called before
1015 * there is any chance for &drm_dp_mst_port.malloc_kref to reach 0.
1016 *
1017 * See also: drm_dp_mst_put_port_malloc()
1018 */
1019void
1020drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port)
1021{
1022 kref_get(&port->malloc_kref);
1023 DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->malloc_kref));
1024}
1025EXPORT_SYMBOL(drm_dp_mst_get_port_malloc);
1026
1027/**
1028 * drm_dp_mst_put_port_malloc() - Decrement the malloc refcount of an MST port
1029 * @port: The &struct drm_dp_mst_port to decrement the malloc refcount of
1030 *
1031 * Decrements &drm_dp_mst_port.malloc_kref. When &drm_dp_mst_port.malloc_kref
1032 * reaches 0, the memory allocation for @port will be released and @port may
1033 * no longer be used.
1034 *
1035 * See also: drm_dp_mst_get_port_malloc()
1036 */
1037void
1038drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port)
1039{
1040 DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->malloc_kref) - 1);
1041 kref_put(&port->malloc_kref, drm_dp_free_mst_port);
1042}
1043EXPORT_SYMBOL(drm_dp_mst_put_port_malloc);
1044
869static void drm_dp_destroy_mst_branch_device(struct kref *kref) 1045static void drm_dp_destroy_mst_branch_device(struct kref *kref)
870{ 1046{
871 struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); 1047 struct drm_dp_mst_branch *mstb =
1048 container_of(kref, struct drm_dp_mst_branch, topology_kref);
1049 struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
872 struct drm_dp_mst_port *port, *tmp; 1050 struct drm_dp_mst_port *port, *tmp;
873 bool wake_tx = false; 1051 bool wake_tx = false;
874 1052
875 /* 1053 mutex_lock(&mgr->lock);
876 * init kref again to be used by ports to remove mst branch when it is
877 * not needed anymore
878 */
879 kref_init(kref);
880
881 if (mstb->port_parent && list_empty(&mstb->port_parent->next))
882 kref_get(&mstb->port_parent->kref);
883
884 /*
885 * destroy all ports - don't need lock
886 * as there are no more references to the mst branch
887 * device at this point.
888 */
889 list_for_each_entry_safe(port, tmp, &mstb->ports, next) { 1054 list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
890 list_del(&port->next); 1055 list_del(&port->next);
891 drm_dp_mst_topology_put_port(port); 1056 drm_dp_mst_topology_put_port(port);
892 } 1057 }
1058 mutex_unlock(&mgr->lock);
893 1059
894 /* drop any tx slots msg */ 1060 /* drop any tx slots msg */
895 mutex_lock(&mstb->mgr->qlock); 1061 mutex_lock(&mstb->mgr->qlock);
@@ -908,14 +1074,83 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
908 if (wake_tx) 1074 if (wake_tx)
909 wake_up_all(&mstb->mgr->tx_waitq); 1075 wake_up_all(&mstb->mgr->tx_waitq);
910 1076
911 kref_put(kref, drm_dp_free_mst_branch_device); 1077 drm_dp_mst_put_mstb_malloc(mstb);
912} 1078}
913 1079
914static void drm_dp_mst_topology_put_mstb(struct drm_dp_mst_branch *mstb) 1080/**
1081 * drm_dp_mst_topology_try_get_mstb() - Increment the topology refcount of a
1082 * branch device unless its zero
1083 * @mstb: &struct drm_dp_mst_branch to increment the topology refcount of
1084 *
1085 * Attempts to grab a topology reference to @mstb, if it hasn't yet been
1086 * removed from the topology (e.g. &drm_dp_mst_branch.topology_kref has
1087 * reached 0). Holding a topology reference implies that a malloc reference
1088 * will be held to @mstb as long as the user holds the topology reference.
1089 *
1090 * Care should be taken to ensure that the user has at least one malloc
1091 * reference to @mstb. If you already have a topology reference to @mstb, you
1092 * should use drm_dp_mst_topology_get_mstb() instead.
1093 *
1094 * See also:
1095 * drm_dp_mst_topology_get_mstb()
1096 * drm_dp_mst_topology_put_mstb()
1097 *
1098 * Returns:
1099 * * 1: A topology reference was grabbed successfully
1100 * * 0: @port is no longer in the topology, no reference was grabbed
1101 */
1102static int __must_check
1103drm_dp_mst_topology_try_get_mstb(struct drm_dp_mst_branch *mstb)
915{ 1104{
916 kref_put(&mstb->kref, drm_dp_destroy_mst_branch_device); 1105 int ret = kref_get_unless_zero(&mstb->topology_kref);
1106
1107 if (ret)
1108 DRM_DEBUG("mstb %p (%d)\n", mstb,
1109 kref_read(&mstb->topology_kref));
1110
1111 return ret;
917} 1112}
918 1113
1114/**
1115 * drm_dp_mst_topology_get_mstb() - Increment the topology refcount of a
1116 * branch device
1117 * @mstb: The &struct drm_dp_mst_branch to increment the topology refcount of
1118 *
1119 * Increments &drm_dp_mst_branch.topology_refcount without checking whether or
1120 * not it's already reached 0. This is only valid to use in scenarios where
1121 * you are already guaranteed to have at least one active topology reference
1122 * to @mstb. Otherwise, drm_dp_mst_topology_try_get_mstb() must be used.
1123 *
1124 * See also:
1125 * drm_dp_mst_topology_try_get_mstb()
1126 * drm_dp_mst_topology_put_mstb()
1127 */
1128static void drm_dp_mst_topology_get_mstb(struct drm_dp_mst_branch *mstb)
1129{
1130 WARN_ON(kref_read(&mstb->topology_kref) == 0);
1131 kref_get(&mstb->topology_kref);
1132 DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->topology_kref));
1133}
1134
1135/**
1136 * drm_dp_mst_topology_put_mstb() - release a topology reference to a branch
1137 * device
1138 * @mstb: The &struct drm_dp_mst_branch to release the topology reference from
1139 *
1140 * Releases a topology reference from @mstb by decrementing
1141 * &drm_dp_mst_branch.topology_kref.
1142 *
1143 * See also:
1144 * drm_dp_mst_topology_try_get_mstb()
1145 * drm_dp_mst_topology_get_mstb()
1146 */
1147static void
1148drm_dp_mst_topology_put_mstb(struct drm_dp_mst_branch *mstb)
1149{
1150 DRM_DEBUG("mstb %p (%d)\n",
1151 mstb, kref_read(&mstb->topology_kref) - 1);
1152 kref_put(&mstb->topology_kref, drm_dp_destroy_mst_branch_device);
1153}
919 1154
920static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt) 1155static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
921{ 1156{
@@ -937,7 +1172,8 @@ static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
937 1172
938static void drm_dp_destroy_port(struct kref *kref) 1173static void drm_dp_destroy_port(struct kref *kref)
939{ 1174{
940 struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref); 1175 struct drm_dp_mst_port *port =
1176 container_of(kref, struct drm_dp_mst_port, topology_kref);
941 struct drm_dp_mst_topology_mgr *mgr = port->mgr; 1177 struct drm_dp_mst_topology_mgr *mgr = port->mgr;
942 1178
943 if (!port->input) { 1179 if (!port->input) {
@@ -956,7 +1192,6 @@ static void drm_dp_destroy_port(struct kref *kref)
956 * from an EDID retrieval */ 1192 * from an EDID retrieval */
957 1193
958 mutex_lock(&mgr->destroy_connector_lock); 1194 mutex_lock(&mgr->destroy_connector_lock);
959 kref_get(&port->parent->kref);
960 list_add(&port->next, &mgr->destroy_connector_list); 1195 list_add(&port->next, &mgr->destroy_connector_list);
961 mutex_unlock(&mgr->destroy_connector_lock); 1196 mutex_unlock(&mgr->destroy_connector_lock);
962 schedule_work(&mgr->destroy_connector_work); 1197 schedule_work(&mgr->destroy_connector_work);
@@ -967,12 +1202,79 @@ static void drm_dp_destroy_port(struct kref *kref)
967 drm_dp_port_teardown_pdt(port, port->pdt); 1202 drm_dp_port_teardown_pdt(port, port->pdt);
968 port->pdt = DP_PEER_DEVICE_NONE; 1203 port->pdt = DP_PEER_DEVICE_NONE;
969 } 1204 }
970 kfree(port); 1205 drm_dp_mst_put_port_malloc(port);
1206}
1207
1208/**
1209 * drm_dp_mst_topology_try_get_port() - Increment the topology refcount of a
1210 * port unless its zero
1211 * @port: &struct drm_dp_mst_port to increment the topology refcount of
1212 *
1213 * Attempts to grab a topology reference to @port, if it hasn't yet been
1214 * removed from the topology (e.g. &drm_dp_mst_port.topology_kref has reached
1215 * 0). Holding a topology reference implies that a malloc reference will be
1216 * held to @port as long as the user holds the topology reference.
1217 *
1218 * Care should be taken to ensure that the user has at least one malloc
1219 * reference to @port. If you already have a topology reference to @port, you
1220 * should use drm_dp_mst_topology_get_port() instead.
1221 *
1222 * See also:
1223 * drm_dp_mst_topology_get_port()
1224 * drm_dp_mst_topology_put_port()
1225 *
1226 * Returns:
1227 * * 1: A topology reference was grabbed successfully
1228 * * 0: @port is no longer in the topology, no reference was grabbed
1229 */
1230static int __must_check
1231drm_dp_mst_topology_try_get_port(struct drm_dp_mst_port *port)
1232{
1233 int ret = kref_get_unless_zero(&port->topology_kref);
1234
1235 if (ret)
1236 DRM_DEBUG("port %p (%d)\n", port,
1237 kref_read(&port->topology_kref));
1238
1239 return ret;
971} 1240}
972 1241
1242/**
1243 * drm_dp_mst_topology_get_port() - Increment the topology refcount of a port
1244 * @port: The &struct drm_dp_mst_port to increment the topology refcount of
1245 *
1246 * Increments &drm_dp_mst_port.topology_refcount without checking whether or
1247 * not it's already reached 0. This is only valid to use in scenarios where
1248 * you are already guaranteed to have at least one active topology reference
1249 * to @port. Otherwise, drm_dp_mst_topology_try_get_port() must be used.
1250 *
1251 * See also:
1252 * drm_dp_mst_topology_try_get_port()
1253 * drm_dp_mst_topology_put_port()
1254 */
1255static void drm_dp_mst_topology_get_port(struct drm_dp_mst_port *port)
1256{
1257 WARN_ON(kref_read(&port->topology_kref) == 0);
1258 kref_get(&port->topology_kref);
1259 DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->topology_kref));
1260}
1261
1262/**
1263 * drm_dp_mst_topology_put_port() - release a topology reference to a port
1264 * @port: The &struct drm_dp_mst_port to release the topology reference from
1265 *
1266 * Releases a topology reference from @port by decrementing
1267 * &drm_dp_mst_port.topology_kref.
1268 *
1269 * See also:
1270 * drm_dp_mst_topology_try_get_port()
1271 * drm_dp_mst_topology_get_port()
1272 */
973static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port) 1273static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port)
974{ 1274{
975 kref_put(&port->kref, drm_dp_destroy_port); 1275 DRM_DEBUG("port %p (%d)\n",
1276 port, kref_read(&port->topology_kref) - 1);
1277 kref_put(&port->topology_kref, drm_dp_destroy_port);
976} 1278}
977 1279
978static struct drm_dp_mst_branch * 1280static struct drm_dp_mst_branch *
@@ -981,10 +1283,10 @@ drm_dp_mst_topology_get_mstb_validated_locked(struct drm_dp_mst_branch *mstb,
981{ 1283{
982 struct drm_dp_mst_port *port; 1284 struct drm_dp_mst_port *port;
983 struct drm_dp_mst_branch *rmstb; 1285 struct drm_dp_mst_branch *rmstb;
984 if (to_find == mstb) { 1286
985 kref_get(&mstb->kref); 1287 if (to_find == mstb)
986 return mstb; 1288 return mstb;
987 } 1289
988 list_for_each_entry(port, &mstb->ports, next) { 1290 list_for_each_entry(port, &mstb->ports, next) {
989 if (port->mstb) { 1291 if (port->mstb) {
990 rmstb = drm_dp_mst_topology_get_mstb_validated_locked( 1292 rmstb = drm_dp_mst_topology_get_mstb_validated_locked(
@@ -1001,25 +1303,32 @@ drm_dp_mst_topology_get_mstb_validated(struct drm_dp_mst_topology_mgr *mgr,
1001 struct drm_dp_mst_branch *mstb) 1303 struct drm_dp_mst_branch *mstb)
1002{ 1304{
1003 struct drm_dp_mst_branch *rmstb = NULL; 1305 struct drm_dp_mst_branch *rmstb = NULL;
1306
1004 mutex_lock(&mgr->lock); 1307 mutex_lock(&mgr->lock);
1005 if (mgr->mst_primary) 1308 if (mgr->mst_primary) {
1006 rmstb = drm_dp_mst_topology_get_mstb_validated_locked( 1309 rmstb = drm_dp_mst_topology_get_mstb_validated_locked(
1007 mgr->mst_primary, mstb); 1310 mgr->mst_primary, mstb);
1311
1312 if (rmstb && !drm_dp_mst_topology_try_get_mstb(rmstb))
1313 rmstb = NULL;
1314 }
1008 mutex_unlock(&mgr->lock); 1315 mutex_unlock(&mgr->lock);
1009 return rmstb; 1316 return rmstb;
1010} 1317}
1011 1318
1012static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_port *to_find) 1319static struct drm_dp_mst_port *
1320drm_dp_mst_topology_get_port_validated_locked(struct drm_dp_mst_branch *mstb,
1321 struct drm_dp_mst_port *to_find)
1013{ 1322{
1014 struct drm_dp_mst_port *port, *mport; 1323 struct drm_dp_mst_port *port, *mport;
1015 1324
1016 list_for_each_entry(port, &mstb->ports, next) { 1325 list_for_each_entry(port, &mstb->ports, next) {
1017 if (port == to_find) { 1326 if (port == to_find)
1018 kref_get(&port->kref);
1019 return port; 1327 return port;
1020 } 1328
1021 if (port->mstb) { 1329 if (port->mstb) {
1022 mport = drm_dp_mst_get_port_ref_locked(port->mstb, to_find); 1330 mport = drm_dp_mst_topology_get_port_validated_locked(
1331 port->mstb, to_find);
1023 if (mport) 1332 if (mport)
1024 return mport; 1333 return mport;
1025 } 1334 }
@@ -1032,9 +1341,15 @@ drm_dp_mst_topology_get_port_validated(struct drm_dp_mst_topology_mgr *mgr,
1032 struct drm_dp_mst_port *port) 1341 struct drm_dp_mst_port *port)
1033{ 1342{
1034 struct drm_dp_mst_port *rport = NULL; 1343 struct drm_dp_mst_port *rport = NULL;
1344
1035 mutex_lock(&mgr->lock); 1345 mutex_lock(&mgr->lock);
1036 if (mgr->mst_primary) 1346 if (mgr->mst_primary) {
1037 rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, port); 1347 rport = drm_dp_mst_topology_get_port_validated_locked(
1348 mgr->mst_primary, port);
1349
1350 if (rport && !drm_dp_mst_topology_try_get_port(rport))
1351 rport = NULL;
1352 }
1038 mutex_unlock(&mgr->lock); 1353 mutex_unlock(&mgr->lock);
1039 return rport; 1354 return rport;
1040} 1355}
@@ -1042,11 +1357,12 @@ drm_dp_mst_topology_get_port_validated(struct drm_dp_mst_topology_mgr *mgr,
1042static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u8 port_num) 1357static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u8 port_num)
1043{ 1358{
1044 struct drm_dp_mst_port *port; 1359 struct drm_dp_mst_port *port;
1360 int ret;
1045 1361
1046 list_for_each_entry(port, &mstb->ports, next) { 1362 list_for_each_entry(port, &mstb->ports, next) {
1047 if (port->port_num == port_num) { 1363 if (port->port_num == port_num) {
1048 kref_get(&port->kref); 1364 ret = drm_dp_mst_topology_try_get_port(port);
1049 return port; 1365 return ret ? port : NULL;
1050 } 1366 }
1051 } 1367 }
1052 1368
@@ -1095,6 +1411,11 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
1095 if (port->mstb) { 1411 if (port->mstb) {
1096 port->mstb->mgr = port->mgr; 1412 port->mstb->mgr = port->mgr;
1097 port->mstb->port_parent = port; 1413 port->mstb->port_parent = port;
1414 /*
1415 * Make sure this port's memory allocation stays
1416 * around until it's child MSTB releases it
1417 */
1418 drm_dp_mst_get_port_malloc(port);
1098 1419
1099 send_link = true; 1420 send_link = true;
1100 } 1421 }
@@ -1155,17 +1476,26 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
1155 bool created = false; 1476 bool created = false;
1156 int old_pdt = 0; 1477 int old_pdt = 0;
1157 int old_ddps = 0; 1478 int old_ddps = 0;
1479
1158 port = drm_dp_get_port(mstb, port_msg->port_number); 1480 port = drm_dp_get_port(mstb, port_msg->port_number);
1159 if (!port) { 1481 if (!port) {
1160 port = kzalloc(sizeof(*port), GFP_KERNEL); 1482 port = kzalloc(sizeof(*port), GFP_KERNEL);
1161 if (!port) 1483 if (!port)
1162 return; 1484 return;
1163 kref_init(&port->kref); 1485 kref_init(&port->topology_kref);
1486 kref_init(&port->malloc_kref);
1164 port->parent = mstb; 1487 port->parent = mstb;
1165 port->port_num = port_msg->port_number; 1488 port->port_num = port_msg->port_number;
1166 port->mgr = mstb->mgr; 1489 port->mgr = mstb->mgr;
1167 port->aux.name = "DPMST"; 1490 port->aux.name = "DPMST";
1168 port->aux.dev = dev->dev; 1491 port->aux.dev = dev->dev;
1492
1493 /*
1494 * Make sure the memory allocation for our parent branch stays
1495 * around until our own memory allocation is released
1496 */
1497 drm_dp_mst_get_mstb_malloc(mstb);
1498
1169 created = true; 1499 created = true;
1170 } else { 1500 } else {
1171 old_pdt = port->pdt; 1501 old_pdt = port->pdt;
@@ -1185,7 +1515,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
1185 for this list */ 1515 for this list */
1186 if (created) { 1516 if (created) {
1187 mutex_lock(&mstb->mgr->lock); 1517 mutex_lock(&mstb->mgr->lock);
1188 kref_get(&port->kref); 1518 drm_dp_mst_topology_get_port(port);
1189 list_add(&port->next, &mstb->ports); 1519 list_add(&port->next, &mstb->ports);
1190 mutex_unlock(&mstb->mgr->lock); 1520 mutex_unlock(&mstb->mgr->lock);
1191 } 1521 }
@@ -1284,7 +1614,7 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
1284{ 1614{
1285 struct drm_dp_mst_branch *mstb; 1615 struct drm_dp_mst_branch *mstb;
1286 struct drm_dp_mst_port *port; 1616 struct drm_dp_mst_port *port;
1287 int i; 1617 int i, ret;
1288 /* find the port by iterating down */ 1618 /* find the port by iterating down */
1289 1619
1290 mutex_lock(&mgr->lock); 1620 mutex_lock(&mgr->lock);
@@ -1309,7 +1639,9 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
1309 } 1639 }
1310 } 1640 }
1311 } 1641 }
1312 kref_get(&mstb->kref); 1642 ret = drm_dp_mst_topology_try_get_mstb(mstb);
1643 if (!ret)
1644 mstb = NULL;
1313out: 1645out:
1314 mutex_unlock(&mgr->lock); 1646 mutex_unlock(&mgr->lock);
1315 return mstb; 1647 return mstb;
@@ -1344,14 +1676,17 @@ drm_dp_get_mst_branch_device_by_guid(struct drm_dp_mst_topology_mgr *mgr,
1344 uint8_t *guid) 1676 uint8_t *guid)
1345{ 1677{
1346 struct drm_dp_mst_branch *mstb; 1678 struct drm_dp_mst_branch *mstb;
1679 int ret;
1347 1680
1348 /* find the port by iterating down */ 1681 /* find the port by iterating down */
1349 mutex_lock(&mgr->lock); 1682 mutex_lock(&mgr->lock);
1350 1683
1351 mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); 1684 mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
1352 1685 if (mstb) {
1353 if (mstb) 1686 ret = drm_dp_mst_topology_try_get_mstb(mstb);
1354 kref_get(&mstb->kref); 1687 if (!ret)
1688 mstb = NULL;
1689 }
1355 1690
1356 mutex_unlock(&mgr->lock); 1691 mutex_unlock(&mgr->lock);
1357 return mstb; 1692 return mstb;
@@ -1390,11 +1725,14 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
1390{ 1725{
1391 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work); 1726 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
1392 struct drm_dp_mst_branch *mstb; 1727 struct drm_dp_mst_branch *mstb;
1728 int ret;
1393 1729
1394 mutex_lock(&mgr->lock); 1730 mutex_lock(&mgr->lock);
1395 mstb = mgr->mst_primary; 1731 mstb = mgr->mst_primary;
1396 if (mstb) { 1732 if (mstb) {
1397 kref_get(&mstb->kref); 1733 ret = drm_dp_mst_topology_try_get_mstb(mstb);
1734 if (!ret)
1735 mstb = NULL;
1398 } 1736 }
1399 mutex_unlock(&mgr->lock); 1737 mutex_unlock(&mgr->lock);
1400 if (mstb) { 1738 if (mstb) {
@@ -1722,8 +2060,10 @@ static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct
1722 2060
1723 if (found_port) { 2061 if (found_port) {
1724 rmstb = found_port->parent; 2062 rmstb = found_port->parent;
1725 kref_get(&rmstb->kref); 2063 if (drm_dp_mst_topology_try_get_mstb(rmstb))
1726 *port_num = found_port->port_num; 2064 *port_num = found_port->port_num;
2065 else
2066 rmstb = NULL;
1727 } 2067 }
1728 } 2068 }
1729 mutex_unlock(&mgr->lock); 2069 mutex_unlock(&mgr->lock);
@@ -2176,7 +2516,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
2176 2516
2177 /* give this the main reference */ 2517 /* give this the main reference */
2178 mgr->mst_primary = mstb; 2518 mgr->mst_primary = mstb;
2179 kref_get(&mgr->mst_primary->kref); 2519 drm_dp_mst_topology_get_mstb(mgr->mst_primary);
2180 2520
2181 ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 2521 ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
2182 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); 2522 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
@@ -3096,13 +3436,6 @@ static void drm_dp_tx_work(struct work_struct *work)
3096 mutex_unlock(&mgr->qlock); 3436 mutex_unlock(&mgr->qlock);
3097} 3437}
3098 3438
3099static void drm_dp_free_mst_port(struct kref *kref)
3100{
3101 struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
3102 kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
3103 kfree(port);
3104}
3105
3106static void drm_dp_destroy_connector_work(struct work_struct *work) 3439static void drm_dp_destroy_connector_work(struct work_struct *work)
3107{ 3440{
3108 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); 3441 struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
@@ -3123,7 +3456,6 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
3123 list_del(&port->next); 3456 list_del(&port->next);
3124 mutex_unlock(&mgr->destroy_connector_lock); 3457 mutex_unlock(&mgr->destroy_connector_lock);
3125 3458
3126 kref_init(&port->kref);
3127 INIT_LIST_HEAD(&port->next); 3459 INIT_LIST_HEAD(&port->next);
3128 3460
3129 mgr->cbs->destroy_connector(mgr, port->connector); 3461 mgr->cbs->destroy_connector(mgr, port->connector);
@@ -3137,7 +3469,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
3137 drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); 3469 drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
3138 } 3470 }
3139 3471
3140 kref_put(&port->kref, drm_dp_free_mst_port); 3472 drm_dp_mst_put_port_malloc(port);
3141 send_hotplug = true; 3473 send_hotplug = true;
3142 } 3474 }
3143 if (send_hotplug) 3475 if (send_hotplug)