drm/dp_mst: Avoid to mess up payload table by ports in stale topology
authorjsg <jsg@openbsd.org>
Wed, 21 Jul 2021 00:59:32 +0000 (00:59 +0000)
committerjsg <jsg@openbsd.org>
Wed, 21 Jul 2021 00:59:32 +0000 (00:59 +0000)
From Wayne Lin
16fb4e9c39b9543efd0c3dbc3dbb8865d090646a in linux 5.10.y/5.10.52
3769e4c0af5b82c8ea21d037013cb9564dfaa51f in mainline linux

sys/dev/pci/drm/drm_dp_mst_topology.c

index 02ed709..6d1b443 100644 (file)
@@ -94,6 +94,9 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port);
 static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port);
 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
 
+static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port,
+                                                struct drm_dp_mst_branch *branch);
+
 #define DBG_PREFIX "[dp_mst]"
 
 #define DP_STR(x) [DP_ ## x] = #x
@@ -3372,6 +3375,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
        struct drm_dp_mst_port *port;
        int i, j;
        int cur_slots = 1;
+       bool skip;
 
        mutex_lock(&mgr->payload_lock);
        for (i = 0; i < mgr->max_payloads; i++) {
@@ -3386,6 +3390,14 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
                        port = container_of(vcpi, struct drm_dp_mst_port,
                                            vcpi);
 
+                       mutex_lock(&mgr->lock);
+                       skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
+                       mutex_unlock(&mgr->lock);
+
+                       if (skip) {
+                               drm_dbg_kms("Virtual channel %d is not in current topology\n", i);
+                               continue;
+                       }
                        /* Validated ports don't matter if we're releasing
                         * VCPI
                         */
@@ -3485,6 +3497,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
        struct drm_dp_mst_port *port;
        int i;
        int ret = 0;
+       bool skip;
 
        mutex_lock(&mgr->payload_lock);
        for (i = 0; i < mgr->max_payloads; i++) {
@@ -3494,6 +3507,13 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
 
                port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
 
+               mutex_lock(&mgr->lock);
+               skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
+               mutex_unlock(&mgr->lock);
+
+               if (skip)
+                       continue;
+
                DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state);
                if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
                        ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
@@ -4575,9 +4595,18 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
 void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
                                struct drm_dp_mst_port *port)
 {
+       bool skip;
+
        if (!port->vcpi.vcpi)
                return;
 
+       mutex_lock(&mgr->lock);
+       skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
+       mutex_unlock(&mgr->lock);
+
+       if (skip)
+               return;
+
        drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
        port->vcpi.num_slots = 0;
        port->vcpi.pbn = 0;