BRANCH DEVICE AND PORT REFCOUNTING(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… Branch device and port refcounting β€” a 9 girly's guide (Kernel API Manual) ✨

okay bestie, buckle up, because we're talking about Branch device and port refcounting and it's genuinely a whole vibe. This is the kernel API manual, section 9, and honestly? The refcounting here is not like other refcounting. Let's get into it πŸ’–


πŸŒ€ Topology refcount overview

So the refcounting schemes for struct drm_dp_mst_branch and struct drm_dp_mst_port are, like, somewhat unusual β€” not in a bad way, in an iconic way. Both ports and branch devices have two different kinds of refcounts: topology refcounts and malloc refcounts. Two. Not one. That's the whole thing, that's the tea 🍡

Topology refcounts are not exposed to drivers β€” nope, they're handled internally by the DP MST helpers only, iykyk. The helpers use them specifically so that the in-memory topology state doesn't get changed in the middle of critical operations, like changing the internal state of payload allocations. Literally cannot let that happen mid-operation, that's a disaster.

Which means: each branch and port is considered connected to the rest of the topology until its topology refcount reaches zero. And for ports specifically, this also means their associated struct drm_connector stays registered with userspace until the port's refcount hits 0. Slay, registered, staying put 🌸


🧚 Malloc refcount overview

Now for the second flavor: malloc references. These are what keep a struct drm_dp_mst_port or a struct drm_dp_mst_branch allocated even after all of its topology references have been dropped β€” so the driver or the MST helpers can still safely peek at each branch's last known state before it got disconnected from the topology. It's giving "keep the receipts" energy πŸŽ€

When the malloc refcount of a port or branch reaches 0, the memory allocation containing the struct drm_dp_mst_branch or struct drm_dp_mst_port (respectively) gets freed. Gone. Bye. πŸ’€

For struct drm_dp_mst_branch, malloc refcounts are not currently exposed to drivers. As of writing this documentation, there are literally no drivers that have a usecase for accessing struct drm_dp_mst_branch outside of the MST helpers. Exposing this API to drivers in a race-free manner would take more tweaking of the refcounting scheme β€” however, patches are welcome, provided there is a legitimate driver usecase for this. So like, bring receipts if you're gonna bring a patch 🫢


🌈 Refcount relationships in a topology

Let's take a look at why the relationship between topology and malloc refcounts is designed the way it is. Because bestie, there's a reason πŸ‘‘

.. kernel-figure:: dp-mst/topology-figure-1.dot

That's an example of topology and malloc refs in a DP MST topology with two active payloads. Topology refcount increments are indicated by solid lines, and malloc refcount increments are indicated by dashed lines. Each one starts from the branch which incremented the refcount, and ends at the branch to which the refcount belongs β€” i.e. the arrow points the same way as the C pointers used to reference a structure. Pointers and arrows, matching, as they should ✨

As you can see in the above figure, every branch increments the topology refcount of its children, and increments the malloc refcount of its parent. Additionally, every payload increments the malloc refcount of its assigned port by 1.

So, what would happen if MSTB #3 from the above figure was unplugged from the system, but the driver hadn't yet removed payload #2 from port #3? The topology would start to look like the figure below. Drama incoming 😭

.. kernel-figure:: dp-mst/topology-figure-2.dot

In that one, ports and branch devices which have been released from memory are colored grey, and references which have been removed are colored red. Rip to those references πŸ’€

Whenever a port or branch device's topology refcount reaches zero, it will decrement the topology refcounts of all its children, the malloc refcount of its parent, and finally its own malloc refcount.

For MSTB #4 and port #4, this means they both have been disconnected from the topology and freed from memory. But β€” and this is the main character plot twist β€” because payload #2 is still holding a reference to port #3, port #3 is removed from the topology but its struct drm_dp_mst_port is still accessible from memory. This also means port #3 has not yet decremented the malloc refcount of MSTB #3, so its struct drm_dp_mst_branch will also stay allocated in memory until port #3's malloc refcount reaches 0. Not me being kept alive by a payload 🧚

This relationship is necessary, okay, because in order to release payload #2, we need to be able to figure out the last relative of port #3 that's still connected to the topology. In this case, we would travel up the topology as shown below. Climbing the family tree πŸ¦‹

.. kernel-figure:: dp-mst/topology-figure-3.dot

And finally, remove payload #2 by communicating with port #2 through sideband transactions. Periodt. πŸ’…


πŸ‘€ SEE ALSO

Kernel file ./drivers/gpu/drm/display/drm_dp_mst_topology.c


and that's the whole page bestie, you ate πŸ’…βœ¨

shoutout to the source at ./drivers/gpu/drm/display, dated October 2026, for gracing us with this β€” Branch device and port refcounting(9), mwah, no notes πŸŽ€πŸ¦‹πŸ’–

πŸ“¦ where this page comes from