Merge tag 'amd-drm-next-6.1-2022-09-08' of https://gitlab.freedesktop.org/agd5f/linux...
[linux-2.6-block.git] / drivers / gpu / drm / display / drm_dp_mst_topology.c
index 3ffa0e8936179b162092bbb4ec0956305e95699a..ecd22c038c8c0cae461ee14c42b95fdcf5e471ad 100644 (file)
@@ -68,8 +68,7 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
 static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port);
 
 static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
-                                    int id,
-                                    struct drm_dp_payload *payload);
+                                    int id, u8 start_slot, u8 num_slots);
 
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
                                 struct drm_dp_mst_port *port,
@@ -1235,57 +1234,6 @@ build_query_stream_enc_status(struct drm_dp_sideband_msg_tx *msg, u8 stream_id,
        return 0;
 }
 
-static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
-                                       struct drm_dp_vcpi *vcpi)
-{
-       int ret, vcpi_ret;
-
-       mutex_lock(&mgr->payload_lock);
-       ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
-       if (ret > mgr->max_payloads) {
-               ret = -EINVAL;
-               drm_dbg_kms(mgr->dev, "out of payload ids %d\n", ret);
-               goto out_unlock;
-       }
-
-       vcpi_ret = find_first_zero_bit(&mgr->vcpi_mask, mgr->max_payloads + 1);
-       if (vcpi_ret > mgr->max_payloads) {
-               ret = -EINVAL;
-               drm_dbg_kms(mgr->dev, "out of vcpi ids %d\n", ret);
-               goto out_unlock;
-       }
-
-       set_bit(ret, &mgr->payload_mask);
-       set_bit(vcpi_ret, &mgr->vcpi_mask);
-       vcpi->vcpi = vcpi_ret + 1;
-       mgr->proposed_vcpis[ret - 1] = vcpi;
-out_unlock:
-       mutex_unlock(&mgr->payload_lock);
-       return ret;
-}
-
-static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
-                                     int vcpi)
-{
-       int i;
-
-       if (vcpi == 0)
-               return;
-
-       mutex_lock(&mgr->payload_lock);
-       drm_dbg_kms(mgr->dev, "putting payload %d\n", vcpi);
-       clear_bit(vcpi - 1, &mgr->vcpi_mask);
-
-       for (i = 0; i < mgr->max_payloads; i++) {
-               if (mgr->proposed_vcpis[i] &&
-                   mgr->proposed_vcpis[i]->vcpi == vcpi) {
-                       mgr->proposed_vcpis[i] = NULL;
-                       clear_bit(i + 1, &mgr->payload_mask);
-               }
-       }
-       mutex_unlock(&mgr->payload_lock);
-}
-
 static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
                              struct drm_dp_sideband_msg_tx *txmsg)
 {
@@ -1738,6 +1686,20 @@ drm_dp_mst_dump_port_topology_history(struct drm_dp_mst_port *port) {}
 #define save_port_topology_ref(port, type)
 #endif
 
+struct drm_dp_mst_atomic_payload *
+drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
+                                struct drm_dp_mst_port *port)
+{
+       struct drm_dp_mst_atomic_payload *payload;
+
+       list_for_each_entry(payload, &state->payloads, next)
+               if (payload->port == port)
+                       return payload;
+
+       return NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_mst_payload_state);
+
 static void drm_dp_destroy_mst_branch_device(struct kref *kref)
 {
        struct drm_dp_mst_branch *mstb =
@@ -2496,7 +2458,7 @@ fail_put:
        return ret;
 }
 
-static void
+static int
 drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
                            struct drm_dp_connection_status_notify *conn_stat)
 {
@@ -2509,7 +2471,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
 
        port = drm_dp_get_port(mstb, conn_stat->port_number);
        if (!port)
-               return;
+               return 0;
 
        if (port->connector) {
                if (!port->input && conn_stat->input_port) {
@@ -2562,8 +2524,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
 
 out:
        drm_dp_mst_topology_put_port(port);
-       if (dowork)
-               queue_work(system_long_wq, &mstb->mgr->work);
+       return dowork;
 }
 
 static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_topology_mgr *mgr,
@@ -3240,6 +3201,8 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
                struct drm_dp_mst_port *port,
                struct drm_dp_query_stream_enc_status_ack_reply *status)
 {
+       struct drm_dp_mst_topology_state *state;
+       struct drm_dp_mst_atomic_payload *payload;
        struct drm_dp_sideband_msg_tx *txmsg;
        u8 nonce[7];
        int ret;
@@ -3256,6 +3219,10 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
 
        get_random_bytes(nonce, sizeof(nonce));
 
+       drm_modeset_lock(&mgr->base.lock, NULL);
+       state = to_drm_dp_mst_topology_state(mgr->base.state);
+       payload = drm_atomic_get_mst_payload_state(state, port);
+
        /*
         * "Source device targets the QUERY_STREAM_ENCRYPTION_STATUS message
         *  transaction at the MST Branch device directly connected to the
@@ -3263,7 +3230,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
         */
        txmsg->dst = mgr->mst_primary;
 
-       build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce);
+       build_query_stream_enc_status(txmsg, payload->vcpi, nonce);
 
        drm_dp_queue_down_tx(mgr, txmsg);
 
@@ -3280,6 +3247,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
        memcpy(status, &txmsg->reply.u.enc_status, sizeof(*status));
 
 out:
+       drm_modeset_unlock(&mgr->base.lock);
        drm_dp_mst_topology_put_port(port);
 out_get_port:
        kfree(txmsg);
@@ -3288,238 +3256,162 @@ out_get_port:
 EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status);
 
 static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
-                                      int id,
-                                      struct drm_dp_payload *payload)
+                                      struct drm_dp_mst_atomic_payload *payload)
 {
-       int ret;
-
-       ret = drm_dp_dpcd_write_payload(mgr, id, payload);
-       if (ret < 0) {
-               payload->payload_state = 0;
-               return ret;
-       }
-       payload->payload_state = DP_PAYLOAD_LOCAL;
-       return 0;
+       return drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot,
+                                        payload->time_slots);
 }
 
 static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
-                                      struct drm_dp_mst_port *port,
-                                      int id,
-                                      struct drm_dp_payload *payload)
+                                      struct drm_dp_mst_atomic_payload *payload)
 {
        int ret;
+       struct drm_dp_mst_port *port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
 
-       ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
-       if (ret < 0)
-               return ret;
-       payload->payload_state = DP_PAYLOAD_REMOTE;
+       if (!port)
+               return -EIO;
+
+       ret = drm_dp_payload_send_msg(mgr, port, payload->vcpi, payload->pbn);
+       drm_dp_mst_topology_put_port(port);
        return ret;
 }
 
 static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
-                                       struct drm_dp_mst_port *port,
-                                       int id,
-                                       struct drm_dp_payload *payload)
+                                       struct drm_dp_mst_topology_state *mst_state,
+                                       struct drm_dp_mst_atomic_payload *payload)
 {
        drm_dbg_kms(mgr->dev, "\n");
-       /* it's okay for these to fail */
-       if (port) {
-               drm_dp_payload_send_msg(mgr, port, id, 0);
-       }
 
-       drm_dp_dpcd_write_payload(mgr, id, payload);
-       payload->payload_state = DP_PAYLOAD_DELETE_LOCAL;
-       return 0;
-}
+       /* it's okay for these to fail */
+       drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0);
+       drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0);
 
-static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
-                                       int id,
-                                       struct drm_dp_payload *payload)
-{
-       payload->payload_state = 0;
        return 0;
 }
 
 /**
- * drm_dp_update_payload_part1() - Execute payload update part 1
- * @mgr: manager to use.
- * @start_slot: this is the cur slot
- *
- * NOTE: start_slot is a temporary workaround for non-atomic drivers,
- * this will be removed when non-atomic mst helpers are moved out of the helper
+ * drm_dp_add_payload_part1() - Execute payload update part 1
+ * @mgr: Manager to use.
+ * @mst_state: The MST atomic state
+ * @payload: The payload to write
  *
- * This iterates over all proposed virtual channels, and tries to
- * allocate space in the link for them. For 0->slots transitions,
- * this step just writes the VCPI to the MST device. For slots->0
- * transitions, this writes the updated VCPIs and removes the
- * remote VC payloads.
+ * Determines the starting time slot for the given payload, and programs the VCPI for this payload
+ * into hardware. After calling this, the driver should generate ACT and payload packets.
  *
- * after calling this the driver should generate ACT and payload
- * packets.
+ * Returns: 0 on success, error code on failure. In the event that this fails,
+ * @payload.vc_start_slot will also be set to -1.
  */
-int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr, int start_slot)
+int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
+                            struct drm_dp_mst_topology_state *mst_state,
+                            struct drm_dp_mst_atomic_payload *payload)
 {
-       struct drm_dp_payload req_payload;
        struct drm_dp_mst_port *port;
-       int i, j;
-       int cur_slots = start_slot;
-       bool skip;
+       int ret;
 
-       mutex_lock(&mgr->payload_lock);
-       for (i = 0; i < mgr->max_payloads; i++) {
-               struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
-               struct drm_dp_payload *payload = &mgr->payloads[i];
-               bool put_port = false;
+       port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
+       if (!port)
+               return 0;
 
-               /* solve the current payloads - compare to the hw ones
-                  - update the hw view */
-               req_payload.start_slot = cur_slots;
-               if (vcpi) {
-                       port = container_of(vcpi, struct drm_dp_mst_port,
-                                           vcpi);
+       if (mgr->payload_count == 0)
+               mgr->next_start_slot = mst_state->start_slot;
 
-                       mutex_lock(&mgr->lock);
-                       skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary);
-                       mutex_unlock(&mgr->lock);
+       payload->vc_start_slot = mgr->next_start_slot;
 
-                       if (skip) {
-                               drm_dbg_kms(mgr->dev,
-                                           "Virtual channel %d is not in current topology\n",
-                                           i);
-                               continue;
-                       }
-                       /* Validated ports don't matter if we're releasing
-                        * VCPI
-                        */
-                       if (vcpi->num_slots) {
-                               port = drm_dp_mst_topology_get_port_validated(
-                                   mgr, port);
-                               if (!port) {
-                                       if (vcpi->num_slots == payload->num_slots) {
-                                               cur_slots += vcpi->num_slots;
-                                               payload->start_slot = req_payload.start_slot;
-                                               continue;
-                                       } else {
-                                               drm_dbg_kms(mgr->dev,
-                                                           "Fail:set payload to invalid sink");
-                                               mutex_unlock(&mgr->payload_lock);
-                                               return -EINVAL;
-                                       }
-                               }
-                               put_port = true;
-                       }
+       ret = drm_dp_create_payload_step1(mgr, payload);
+       drm_dp_mst_topology_put_port(port);
+       if (ret < 0) {
+               drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
+                        payload->port, ret);
+               payload->vc_start_slot = -1;
+               return ret;
+       }
 
-                       req_payload.num_slots = vcpi->num_slots;
-                       req_payload.vcpi = vcpi->vcpi;
-               } else {
-                       port = NULL;
-                       req_payload.num_slots = 0;
-               }
+       mgr->payload_count++;
+       mgr->next_start_slot += payload->time_slots;
 
-               payload->start_slot = req_payload.start_slot;
-               /* work out what is required to happen with this payload */
-               if (payload->num_slots != req_payload.num_slots) {
-
-                       /* need to push an update for this payload */
-                       if (req_payload.num_slots) {
-                               drm_dp_create_payload_step1(mgr, vcpi->vcpi,
-                                                           &req_payload);
-                               payload->num_slots = req_payload.num_slots;
-                               payload->vcpi = req_payload.vcpi;
-
-                       } else if (payload->num_slots) {
-                               payload->num_slots = 0;
-                               drm_dp_destroy_payload_step1(mgr, port,
-                                                            payload->vcpi,
-                                                            payload);
-                               req_payload.payload_state =
-                                       payload->payload_state;
-                               payload->start_slot = 0;
-                       }
-                       payload->payload_state = req_payload.payload_state;
-               }
-               cur_slots += req_payload.num_slots;
+       return 0;
+}
+EXPORT_SYMBOL(drm_dp_add_payload_part1);
 
-               if (put_port)
-                       drm_dp_mst_topology_put_port(port);
-       }
+/**
+ * drm_dp_remove_payload() - Remove an MST payload
+ * @mgr: Manager to use.
+ * @mst_state: The MST atomic state
+ * @payload: The payload to write
+ *
+ * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
+ * the starting time slots of all other payloads which would have been shifted towards the start of
+ * the VC table as a result. After calling this, the driver should generate ACT and payload packets.
+ */
+void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
+                          struct drm_dp_mst_topology_state *mst_state,
+                          struct drm_dp_mst_atomic_payload *payload)
+{
+       struct drm_dp_mst_atomic_payload *pos;
+       bool send_remove = false;
 
-       for (i = 0; i < mgr->max_payloads; /* do nothing */) {
-               if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) {
-                       i++;
-                       continue;
-               }
+       /* We failed to make the payload, so nothing to do */
+       if (payload->vc_start_slot == -1)
+               return;
 
-               drm_dbg_kms(mgr->dev, "removing payload %d\n", i);
-               for (j = i; j < mgr->max_payloads - 1; j++) {
-                       mgr->payloads[j] = mgr->payloads[j + 1];
-                       mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
+       mutex_lock(&mgr->lock);
+       send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
+       mutex_unlock(&mgr->lock);
 
-                       if (mgr->proposed_vcpis[j] &&
-                           mgr->proposed_vcpis[j]->num_slots) {
-                               set_bit(j + 1, &mgr->payload_mask);
-                       } else {
-                               clear_bit(j + 1, &mgr->payload_mask);
-                       }
-               }
+       if (send_remove)
+               drm_dp_destroy_payload_step1(mgr, mst_state, payload);
+       else
+               drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
+                           payload->vcpi);
 
-               memset(&mgr->payloads[mgr->max_payloads - 1], 0,
-                      sizeof(struct drm_dp_payload));
-               mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
-               clear_bit(mgr->max_payloads, &mgr->payload_mask);
+       list_for_each_entry(pos, &mst_state->payloads, next) {
+               if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
+                       pos->vc_start_slot -= payload->time_slots;
        }
-       mutex_unlock(&mgr->payload_lock);
+       payload->vc_start_slot = -1;
 
-       return 0;
+       mgr->payload_count--;
+       mgr->next_start_slot -= payload->time_slots;
 }
-EXPORT_SYMBOL(drm_dp_update_payload_part1);
+EXPORT_SYMBOL(drm_dp_remove_payload);
 
 /**
- * drm_dp_update_payload_part2() - Execute payload update part 2
- * @mgr: manager to use.
+ * drm_dp_add_payload_part2() - Execute payload update part 2
+ * @mgr: Manager to use.
+ * @state: The global atomic state
+ * @payload: The payload to update
+ *
+ * If @payload was successfully assigned a starting time slot by drm_dp_add_payload_part1(), this
+ * function will send the sideband messages to finish allocating this payload.
  *
- * This iterates over all proposed virtual channels, and tries to
- * allocate space in the link for them. For 0->slots transitions,
- * this step writes the remote VC payload commands. For slots->0
- * this just resets some internal state.
+ * Returns: 0 on success, negative error code on failure.
  */
-int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
+int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
+                            struct drm_atomic_state *state,
+                            struct drm_dp_mst_atomic_payload *payload)
 {
-       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++) {
-
-               if (!mgr->proposed_vcpis[i])
-                       continue;
-
-               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;
+       /* Skip failed payloads */
+       if (payload->vc_start_slot == -1) {
+               drm_dbg_kms(state->dev, "Part 1 of payload creation for %s failed, skipping part 2\n",
+                           payload->port->connector->name);
+               return -EIO;
+       }
 
-               drm_dbg_kms(mgr->dev, "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]);
-               } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
-                       ret = drm_dp_destroy_payload_step2(mgr, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
-               }
-               if (ret) {
-                       mutex_unlock(&mgr->payload_lock);
-                       return ret;
-               }
+       ret = drm_dp_create_payload_step2(mgr, payload);
+       if (ret < 0) {
+               if (!payload->delete)
+                       drm_err(mgr->dev, "Step 2 of creating MST payload for %p failed: %d\n",
+                               payload->port, ret);
+               else
+                       drm_dbg_kms(mgr->dev, "Step 2 of removing MST payload for %p failed: %d\n",
+                                   payload->port, ret);
        }
-       mutex_unlock(&mgr->payload_lock);
-       return 0;
+
+       return ret;
 }
-EXPORT_SYMBOL(drm_dp_update_payload_part2);
+EXPORT_SYMBOL(drm_dp_add_payload_part2);
 
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
                                 struct drm_dp_mst_port *port,
@@ -3699,7 +3591,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
        int ret = 0;
        struct drm_dp_mst_branch *mstb = NULL;
 
-       mutex_lock(&mgr->payload_lock);
        mutex_lock(&mgr->lock);
        if (mst_state == mgr->mst_state)
                goto out_unlock;
@@ -3707,10 +3598,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
        mgr->mst_state = mst_state;
        /* set the device into MST mode */
        if (mst_state) {
-               struct drm_dp_payload reset_pay;
-               int lane_count;
-               int link_rate;
-
                WARN_ON(mgr->mst_primary);
 
                /* get dpcd info */
@@ -3721,16 +3608,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
                        goto out_unlock;
                }
 
-               lane_count = min_t(int, mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK, mgr->max_lane_count);
-               link_rate = min_t(int, drm_dp_bw_code_to_link_rate(mgr->dpcd[1]), mgr->max_link_rate);
-               mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr,
-                                                       link_rate,
-                                                       lane_count);
-               if (mgr->pbn_div == 0) {
-                       ret = -EINVAL;
-                       goto out_unlock;
-               }
-
                /* add initial branch device at LCT 1 */
                mstb = drm_dp_add_mst_branch_device(1, NULL);
                if (mstb == NULL) {
@@ -3750,9 +3627,8 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
                if (ret < 0)
                        goto out_unlock;
 
-               reset_pay.start_slot = 0;
-               reset_pay.num_slots = 0x3f;
-               drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+               /* Write reset payload */
+               drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f);
 
                queue_work(system_long_wq, &mgr->work);
 
@@ -3764,19 +3640,11 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
                /* this can fail if the device is gone */
                drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
                ret = 0;
-               memset(mgr->payloads, 0,
-                      mgr->max_payloads * sizeof(mgr->payloads[0]));
-               memset(mgr->proposed_vcpis, 0,
-                      mgr->max_payloads * sizeof(mgr->proposed_vcpis[0]));
-               mgr->payload_mask = 0;
-               set_bit(0, &mgr->payload_mask);
-               mgr->vcpi_mask = 0;
                mgr->payload_id_table_cleared = false;
        }
 
 out_unlock:
        mutex_unlock(&mgr->lock);
-       mutex_unlock(&mgr->payload_lock);
        if (mstb)
                drm_dp_mst_topology_put_mstb(mstb);
        return ret;
@@ -4047,7 +3915,7 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
        struct drm_dp_mst_branch *mstb = NULL;
        struct drm_dp_sideband_msg_req_body *msg = &up_req->msg;
        struct drm_dp_sideband_msg_hdr *hdr = &up_req->hdr;
-       bool hotplug = false;
+       bool hotplug = false, dowork = false;
 
        if (hdr->broadcast) {
                const u8 *guid = NULL;
@@ -4070,11 +3938,14 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
 
        /* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
        if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
-               drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
+               dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
                hotplug = true;
        }
 
        drm_dp_mst_topology_put_mstb(mstb);
+
+       if (dowork)
+               queue_work(system_long_wq, &mgr->work);
        return hotplug;
 }
 
@@ -4293,341 +4164,352 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
 EXPORT_SYMBOL(drm_dp_mst_get_edid);
 
 /**
- * drm_dp_find_vcpi_slots() - Find VCPI slots for this PBN value
- * @mgr: manager to use
- * @pbn: payload bandwidth to convert into slots.
- *
- * Calculate the number of VCPI slots that will be required for the given PBN
- * value. This function is deprecated, and should not be used in atomic
- * drivers.
- *
- * RETURNS:
- * The total slots required for this port, or error.
- */
-int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
-                          int pbn)
-{
-       int num_slots;
-
-       num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
-
-       /* max. time slots - one slot for MTP header */
-       if (num_slots > 63)
-               return -ENOSPC;
-       return num_slots;
-}
-EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
-
-static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-                           struct drm_dp_vcpi *vcpi, int pbn, int slots)
-{
-       int ret;
-
-       vcpi->pbn = pbn;
-       vcpi->aligned_pbn = slots * mgr->pbn_div;
-       vcpi->num_slots = slots;
-
-       ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-/**
- * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
+ * drm_dp_atomic_find_time_slots() - Find and add time slots to the state
  * @state: global atomic state
  * @mgr: MST topology manager for the port
- * @port: port to find vcpi slots for
+ * @port: port to find time slots for
  * @pbn: bandwidth required for the mode in PBN
- * @pbn_div: divider for DSC mode that takes FEC into account
  *
- * Allocates VCPI slots to @port, replacing any previous VCPI allocations it
- * may have had. Any atomic drivers which support MST must call this function
- * in their &drm_encoder_helper_funcs.atomic_check() callback to change the
- * current VCPI allocation for the new state, but only when
- * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set
- * to ensure compatibility with userspace applications that still use the
- * legacy modesetting UAPI.
+ * Allocates time slots to @port, replacing any previous time slot allocations it may
+ * have had. Any atomic drivers which support MST must call this function in
+ * their &drm_encoder_helper_funcs.atomic_check() callback unconditionally to
+ * change the current time slot allocation for the new state, and ensure the MST
+ * atomic state is added whenever the state of payloads in the topology changes.
  *
  * Allocations set by this function are not checked against the bandwidth
  * restraints of @mgr until the driver calls drm_dp_mst_atomic_check().
  *
  * Additionally, it is OK to call this function multiple times on the same
  * @port as needed. It is not OK however, to call this function and
- * drm_dp_atomic_release_vcpi_slots() in the same atomic check phase.
+ * drm_dp_atomic_release_time_slots() in the same atomic check phase.
  *
  * See also:
- * drm_dp_atomic_release_vcpi_slots()
+ * drm_dp_atomic_release_time_slots()
  * drm_dp_mst_atomic_check()
  *
  * Returns:
  * Total slots in the atomic state assigned for this port, or a negative error
  * code if the port no longer exists
  */
-int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
+int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
                                  struct drm_dp_mst_topology_mgr *mgr,
-                                 struct drm_dp_mst_port *port, int pbn,
-                                 int pbn_div)
+                                 struct drm_dp_mst_port *port, int pbn)
 {
        struct drm_dp_mst_topology_state *topology_state;
-       struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
-       int prev_slots, prev_bw, req_slots;
+       struct drm_dp_mst_atomic_payload *payload = NULL;
+       struct drm_connector_state *conn_state;
+       int prev_slots = 0, prev_bw = 0, req_slots;
 
        topology_state = drm_atomic_get_mst_topology_state(state, mgr);
        if (IS_ERR(topology_state))
                return PTR_ERR(topology_state);
 
-       /* Find the current allocation for this port, if any */
-       list_for_each_entry(pos, &topology_state->vcpis, next) {
-               if (pos->port == port) {
-                       vcpi = pos;
-                       prev_slots = vcpi->vcpi;
-                       prev_bw = vcpi->pbn;
+       conn_state = drm_atomic_get_new_connector_state(state, port->connector);
+       topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
 
-                       /*
-                        * This should never happen, unless the driver tries
-                        * releasing and allocating the same VCPI allocation,
-                        * which is an error
-                        */
-                       if (WARN_ON(!prev_slots)) {
-                               drm_err(mgr->dev,
-                                       "cannot allocate and release VCPI on [MST PORT:%p] in the same state\n",
-                                       port);
-                               return -EINVAL;
-                       }
+       /* Find the current allocation for this port, if any */
+       payload = drm_atomic_get_mst_payload_state(topology_state, port);
+       if (payload) {
+               prev_slots = payload->time_slots;
+               prev_bw = payload->pbn;
 
-                       break;
+               /*
+                * This should never happen, unless the driver tries
+                * releasing and allocating the same timeslot allocation,
+                * which is an error
+                */
+               if (drm_WARN_ON(mgr->dev, payload->delete)) {
+                       drm_err(mgr->dev,
+                               "cannot allocate and release time slots on [MST PORT:%p] in the same state\n",
+                               port);
+                       return -EINVAL;
                }
        }
-       if (!vcpi) {
-               prev_slots = 0;
-               prev_bw = 0;
-       }
-
-       if (pbn_div <= 0)
-               pbn_div = mgr->pbn_div;
 
-       req_slots = DIV_ROUND_UP(pbn, pbn_div);
+       req_slots = DIV_ROUND_UP(pbn, topology_state->pbn_div);
 
-       drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n",
+       drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n",
                       port->connector->base.id, port->connector->name,
                       port, prev_slots, req_slots);
        drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] PBN %d -> %d\n",
                       port->connector->base.id, port->connector->name,
                       port, prev_bw, pbn);
 
-       /* Add the new allocation to the state */
-       if (!vcpi) {
-               vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
-               if (!vcpi)
+       /* Add the new allocation to the state, note the VCPI isn't assigned until the end */
+       if (!payload) {
+               payload = kzalloc(sizeof(*payload), GFP_KERNEL);
+               if (!payload)
                        return -ENOMEM;
 
                drm_dp_mst_get_port_malloc(port);
-               vcpi->port = port;
-               list_add(&vcpi->next, &topology_state->vcpis);
+               payload->port = port;
+               payload->vc_start_slot = -1;
+               list_add(&payload->next, &topology_state->payloads);
        }
-       vcpi->vcpi = req_slots;
-       vcpi->pbn = pbn;
+       payload->time_slots = req_slots;
+       payload->pbn = pbn;
 
        return req_slots;
 }
-EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
+EXPORT_SYMBOL(drm_dp_atomic_find_time_slots);
 
 /**
- * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
+ * drm_dp_atomic_release_time_slots() - Release allocated time slots
  * @state: global atomic state
  * @mgr: MST topology manager for the port
- * @port: The port to release the VCPI slots from
+ * @port: The port to release the time slots from
  *
- * Releases any VCPI slots that have been allocated to a port in the atomic
- * state. Any atomic drivers which support MST must call this function in
- * their &drm_connector_helper_funcs.atomic_check() callback when the
- * connector will no longer have VCPI allocated (e.g. because its CRTC was
- * removed) when it had VCPI allocated in the previous atomic state.
+ * Releases any time slots that have been allocated to a port in the atomic
+ * state. Any atomic drivers which support MST must call this function
+ * unconditionally in their &drm_connector_helper_funcs.atomic_check() callback.
+ * This helper will check whether time slots would be released by the new state and
+ * respond accordingly, along with ensuring the MST state is always added to the
+ * atomic state whenever a new state would modify the state of payloads on the
+ * topology.
  *
  * It is OK to call this even if @port has been removed from the system.
  * Additionally, it is OK to call this function multiple times on the same
  * @port as needed. It is not OK however, to call this function and
- * drm_dp_atomic_find_vcpi_slots() on the same @port in a single atomic check
+ * drm_dp_atomic_find_time_slots() on the same @port in a single atomic check
  * phase.
  *
  * See also:
- * drm_dp_atomic_find_vcpi_slots()
+ * drm_dp_atomic_find_time_slots()
  * drm_dp_mst_atomic_check()
  *
  * Returns:
- * 0 if all slots for this port were added back to
- * &drm_dp_mst_topology_state.avail_slots or negative error code
+ * 0 on success, negative error code otherwise
  */
-int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
+int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
                                     struct drm_dp_mst_topology_mgr *mgr,
                                     struct drm_dp_mst_port *port)
 {
        struct drm_dp_mst_topology_state *topology_state;
-       struct drm_dp_vcpi_allocation *pos;
-       bool found = false;
+       struct drm_dp_mst_atomic_payload *payload;
+       struct drm_connector_state *old_conn_state, *new_conn_state;
+       bool update_payload = true;
+
+       old_conn_state = drm_atomic_get_old_connector_state(state, port->connector);
+       if (!old_conn_state->crtc)
+               return 0;
+
+       /* If the CRTC isn't disabled by this state, don't release it's payload */
+       new_conn_state = drm_atomic_get_new_connector_state(state, port->connector);
+       if (new_conn_state->crtc) {
+               struct drm_crtc_state *crtc_state =
+                       drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+
+               /* No modeset means no payload changes, so it's safe to not pull in the MST state */
+               if (!crtc_state || !drm_atomic_crtc_needs_modeset(crtc_state))
+                       return 0;
+
+               if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+                       update_payload = false;
+       }
 
        topology_state = drm_atomic_get_mst_topology_state(state, mgr);
        if (IS_ERR(topology_state))
                return PTR_ERR(topology_state);
 
-       list_for_each_entry(pos, &topology_state->vcpis, next) {
-               if (pos->port == port) {
-                       found = true;
-                       break;
-               }
-       }
-       if (WARN_ON(!found)) {
-               drm_err(mgr->dev, "no VCPI for [MST PORT:%p] found in mst state %p\n",
+       topology_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc);
+       if (!update_payload)
+               return 0;
+
+       payload = drm_atomic_get_mst_payload_state(topology_state, port);
+       if (WARN_ON(!payload)) {
+               drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst state %p\n",
                        port, &topology_state->base);
                return -EINVAL;
        }
 
-       drm_dbg_atomic(mgr->dev, "[MST PORT:%p] VCPI %d -> 0\n", port, pos->vcpi);
-       if (pos->vcpi) {
+       if (new_conn_state->crtc)
+               return 0;
+
+       drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);
+       if (!payload->delete) {
                drm_dp_mst_put_port_malloc(port);
-               pos->vcpi = 0;
-               pos->pbn = 0;
+               payload->pbn = 0;
+               payload->delete = true;
+               topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
        }
 
        return 0;
 }
-EXPORT_SYMBOL(drm_dp_atomic_release_vcpi_slots);
+EXPORT_SYMBOL(drm_dp_atomic_release_time_slots);
 
 /**
- * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format
- * @mst_state: mst_state to update
- * @link_encoding_cap: the ecoding format on the link
- */
-void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap)
-{
-       if (link_encoding_cap == DP_CAP_ANSI_128B132B) {
-               mst_state->total_avail_slots = 64;
-               mst_state->start_slot = 0;
-       } else {
-               mst_state->total_avail_slots = 63;
-               mst_state->start_slot = 1;
-       }
-
-       DRM_DEBUG_KMS("%s encoding format on mst_state 0x%p\n",
-                     (link_encoding_cap == DP_CAP_ANSI_128B132B) ? "128b/132b":"8b/10b",
-                     mst_state);
-}
-EXPORT_SYMBOL(drm_dp_mst_update_slots);
-
-/**
- * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
- * @mgr: manager for this port
- * @port: port to allocate a virtual channel for.
- * @pbn: payload bandwidth number to request
- * @slots: returned number of slots for this PBN.
+ * drm_dp_mst_atomic_setup_commit() - setup_commit hook for MST helpers
+ * @state: global atomic state
+ *
+ * This function saves all of the &drm_crtc_commit structs in an atomic state that touch any CRTCs
+ * currently assigned to an MST topology. Drivers must call this hook from their
+ * &drm_mode_config_helper_funcs.atomic_commit_setup hook.
+ *
+ * Returns:
+ * 0 if all CRTC commits were retrieved successfully, negative error code otherwise
  */
-bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-                             struct drm_dp_mst_port *port, int pbn, int slots)
+int drm_dp_mst_atomic_setup_commit(struct drm_atomic_state *state)
 {
-       int ret;
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       int i, j, commit_idx, num_commit_deps;
 
-       if (slots < 0)
-               return false;
+       for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
+               if (!mst_state->pending_crtc_mask)
+                       continue;
 
-       port = drm_dp_mst_topology_get_port_validated(mgr, port);
-       if (!port)
-               return false;
+               num_commit_deps = hweight32(mst_state->pending_crtc_mask);
+               mst_state->commit_deps = kmalloc_array(num_commit_deps,
+                                                      sizeof(*mst_state->commit_deps), GFP_KERNEL);
+               if (!mst_state->commit_deps)
+                       return -ENOMEM;
+               mst_state->num_commit_deps = num_commit_deps;
 
-       if (port->vcpi.vcpi > 0) {
-               drm_dbg_kms(mgr->dev,
-                           "payload: vcpi %d already allocated for pbn %d - requested pbn %d\n",
-                           port->vcpi.vcpi, port->vcpi.pbn, pbn);
-               if (pbn == port->vcpi.pbn) {
-                       drm_dp_mst_topology_put_port(port);
-                       return true;
+               commit_idx = 0;
+               for_each_new_crtc_in_state(state, crtc, crtc_state, j) {
+                       if (mst_state->pending_crtc_mask & drm_crtc_mask(crtc)) {
+                               mst_state->commit_deps[commit_idx++] =
+                                       drm_crtc_commit_get(crtc_state->commit);
+                       }
                }
        }
 
-       ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
-       if (ret) {
-               drm_dbg_kms(mgr->dev, "failed to init vcpi slots=%d ret=%d\n",
-                           DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
-               drm_dp_mst_topology_put_port(port);
-               goto out;
-       }
-       drm_dbg_kms(mgr->dev, "initing vcpi for pbn=%d slots=%d\n", pbn, port->vcpi.num_slots);
-
-       /* Keep port allocated until its payload has been removed */
-       drm_dp_mst_get_port_malloc(port);
-       drm_dp_mst_topology_put_port(port);
-       return true;
-out:
-       return false;
+       return 0;
 }
-EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
+EXPORT_SYMBOL(drm_dp_mst_atomic_setup_commit);
 
-int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+/**
+ * drm_dp_mst_atomic_wait_for_dependencies() - Wait for all pending commits on MST topologies,
+ * prepare new MST state for commit
+ * @state: global atomic state
+ *
+ * Goes through any MST topologies in this atomic state, and waits for any pending commits which
+ * touched CRTCs that were/are on an MST topology to be programmed to hardware and flipped to before
+ * returning. This is to prevent multiple non-blocking commits affecting an MST topology from racing
+ * with eachother by forcing them to be executed sequentially in situations where the only resources
+ * the modeset objects in these commits share are an MST topology.
+ *
+ * This function also prepares the new MST state for commit by performing some state preparation
+ * which can't be done until this point, such as reading back the final VC start slots (which are
+ * determined at commit-time) from the previous state.
+ *
+ * All MST drivers must call this function after calling drm_atomic_helper_wait_for_dependencies(),
+ * or whatever their equivalent of that is.
+ */
+void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
 {
-       int slots = 0;
+       struct drm_dp_mst_topology_state *old_mst_state, *new_mst_state;
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_atomic_payload *old_payload, *new_payload;
+       int i, j, ret;
+
+       for_each_oldnew_mst_mgr_in_state(state, mgr, old_mst_state, new_mst_state, i) {
+               for (j = 0; j < old_mst_state->num_commit_deps; j++) {
+                       ret = drm_crtc_commit_wait(old_mst_state->commit_deps[j]);
+                       if (ret < 0)
+                               drm_err(state->dev, "Failed to wait for %s: %d\n",
+                                       old_mst_state->commit_deps[j]->crtc->name, ret);
+               }
 
-       port = drm_dp_mst_topology_get_port_validated(mgr, port);
-       if (!port)
-               return slots;
+               /* Now that previous state is committed, it's safe to copy over the start slot
+                * assignments
+                */
+               list_for_each_entry(old_payload, &old_mst_state->payloads, next) {
+                       if (old_payload->delete)
+                               continue;
 
-       slots = port->vcpi.num_slots;
-       drm_dp_mst_topology_put_port(port);
-       return slots;
+                       new_payload = drm_atomic_get_mst_payload_state(new_mst_state,
+                                                                      old_payload->port);
+                       new_payload->vc_start_slot = old_payload->vc_start_slot;
+               }
+       }
 }
-EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
+EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies);
 
 /**
- * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
- * @mgr: manager for this port
- * @port: unverified pointer to a port.
+ * drm_dp_mst_root_conn_atomic_check() - Serialize CRTC commits on MST-capable connectors operating
+ * in SST mode
+ * @new_conn_state: The new connector state of the &drm_connector
+ * @mgr: The MST topology manager for the &drm_connector
+ *
+ * Since MST uses fake &drm_encoder structs, the generic atomic modesetting code isn't able to
+ * serialize non-blocking commits happening on the real DP connector of an MST topology switching
+ * into/away from MST mode - as the CRTC on the real DP connector and the CRTCs on the connector's
+ * MST topology will never share the same &drm_encoder.
  *
- * This just resets the number of slots for the ports VCPI for later programming.
+ * This function takes care of this serialization issue, by checking a root MST connector's atomic
+ * state to determine if it is about to have a modeset - and then pulling in the MST topology state
+ * if so, along with adding any relevant CRTCs to &drm_dp_mst_topology_state.pending_crtc_mask.
+ *
+ * Drivers implementing MST must call this function from the
+ * &drm_connector_helper_funcs.atomic_check hook of any physical DP &drm_connector capable of
+ * driving MST sinks.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise
  */
-void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+int drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state,
+                                     struct drm_dp_mst_topology_mgr *mgr)
 {
-       /*
-        * A port with VCPI will remain allocated until its VCPI is
-        * released, no verified ref needed
-        */
+       struct drm_atomic_state *state = new_conn_state->state;
+       struct drm_connector_state *old_conn_state =
+               drm_atomic_get_old_connector_state(state, new_conn_state->connector);
+       struct drm_crtc_state *crtc_state;
+       struct drm_dp_mst_topology_state *mst_state = NULL;
+
+       if (new_conn_state->crtc) {
+               crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+               if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) {
+                       mst_state = drm_atomic_get_mst_topology_state(state, mgr);
+                       if (IS_ERR(mst_state))
+                               return PTR_ERR(mst_state);
+
+                       mst_state->pending_crtc_mask |= drm_crtc_mask(new_conn_state->crtc);
+               }
+       }
 
-       port->vcpi.num_slots = 0;
+       if (old_conn_state->crtc) {
+               crtc_state = drm_atomic_get_new_crtc_state(state, old_conn_state->crtc);
+               if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) {
+                       if (!mst_state) {
+                               mst_state = drm_atomic_get_mst_topology_state(state, mgr);
+                               if (IS_ERR(mst_state))
+                                       return PTR_ERR(mst_state);
+                       }
+
+                       mst_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc);
+               }
+       }
+
+       return 0;
 }
-EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
+EXPORT_SYMBOL(drm_dp_mst_root_conn_atomic_check);
 
 /**
- * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI
- * @mgr: manager for this port
- * @port: port to deallocate vcpi for
- *
- * This can be called unconditionally, regardless of whether
- * drm_dp_mst_allocate_vcpi() succeeded or not.
+ * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format
+ * @mst_state: mst_state to update
+ * @link_encoding_cap: the ecoding format on the link
  */
-void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
-                               struct drm_dp_mst_port *port)
+void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap)
 {
-       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;
+       if (link_encoding_cap == DP_CAP_ANSI_128B132B) {
+               mst_state->total_avail_slots = 64;
+               mst_state->start_slot = 0;
+       } else {
+               mst_state->total_avail_slots = 63;
+               mst_state->start_slot = 1;
+       }
 
-       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-       port->vcpi.num_slots = 0;
-       port->vcpi.pbn = 0;
-       port->vcpi.aligned_pbn = 0;
-       port->vcpi.vcpi = 0;
-       drm_dp_mst_put_port_malloc(port);
+       DRM_DEBUG_KMS("%s encoding format on mst_state 0x%p\n",
+                     (link_encoding_cap == DP_CAP_ANSI_128B132B) ? "128b/132b":"8b/10b",
+                     mst_state);
 }
-EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
+EXPORT_SYMBOL(drm_dp_mst_update_slots);
 
 static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
-                                    int id, struct drm_dp_payload *payload)
+                                    int id, u8 start_slot, u8 num_slots)
 {
        u8 payload_alloc[3], status;
        int ret;
@@ -4637,8 +4519,8 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
                           DP_PAYLOAD_TABLE_UPDATED);
 
        payload_alloc[0] = id;
-       payload_alloc[1] = payload->start_slot;
-       payload_alloc[2] = payload->num_slots;
+       payload_alloc[1] = start_slot;
+       payload_alloc[2] = num_slots;
 
        ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3);
        if (ret != 3) {
@@ -4853,8 +4735,9 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
 void drm_dp_mst_dump_topology(struct seq_file *m,
                              struct drm_dp_mst_topology_mgr *mgr)
 {
-       int i;
-       struct drm_dp_mst_port *port;
+       struct drm_dp_mst_topology_state *state;
+       struct drm_dp_mst_atomic_payload *payload;
+       int i, ret;
 
        mutex_lock(&mgr->lock);
        if (mgr->mst_primary)
@@ -4863,36 +4746,35 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
        /* dump VCPIs */
        mutex_unlock(&mgr->lock);
 
-       mutex_lock(&mgr->payload_lock);
-       seq_printf(m, "\n*** VCPI Info ***\n");
-       seq_printf(m, "payload_mask: %lx, vcpi_mask: %lx, max_payloads: %d\n", mgr->payload_mask, mgr->vcpi_mask, mgr->max_payloads);
+       ret = drm_modeset_lock_single_interruptible(&mgr->base.lock);
+       if (ret < 0)
+               return;
+
+       state = to_drm_dp_mst_topology_state(mgr->base.state);
+       seq_printf(m, "\n*** Atomic state info ***\n");
+       seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n",
+                  state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
 
-       seq_printf(m, "\n|   idx   |  port # |  vcp_id | # slots |     sink name     |\n");
+       seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc |     sink name     |\n");
        for (i = 0; i < mgr->max_payloads; i++) {
-               if (mgr->proposed_vcpis[i]) {
+               list_for_each_entry(payload, &state->payloads, next) {
                        char name[14];
 
-                       port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
-                       fetch_monitor_name(mgr, port, name, sizeof(name));
-                       seq_printf(m, "%10d%10d%10d%10d%20s\n",
+                       if (payload->vcpi != i || payload->delete)
+                               continue;
+
+                       fetch_monitor_name(mgr, payload->port, name, sizeof(name));
+                       seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
                                   i,
-                                  port->port_num,
-                                  port->vcpi.vcpi,
-                                  port->vcpi.num_slots,
+                                  payload->port->port_num,
+                                  payload->vcpi,
+                                  payload->vc_start_slot,
+                                  payload->vc_start_slot + payload->time_slots - 1,
+                                  payload->pbn,
+                                  payload->dsc_enabled ? "Y" : "N",
                                   (*name != 0) ? name : "Unknown");
-               } else
-                       seq_printf(m, "%6d - Unused\n", i);
-       }
-       seq_printf(m, "\n*** Payload Info ***\n");
-       seq_printf(m, "|   idx   |  state  |  start slot  | # slots |\n");
-       for (i = 0; i < mgr->max_payloads; i++) {
-               seq_printf(m, "%10d%10d%15d%10d\n",
-                          i,
-                          mgr->payloads[i].payload_state,
-                          mgr->payloads[i].start_slot,
-                          mgr->payloads[i].num_slots);
+               }
        }
-       mutex_unlock(&mgr->payload_lock);
 
        seq_printf(m, "\n*** DPCD Info ***\n");
        mutex_lock(&mgr->lock);
@@ -4907,14 +4789,14 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
                seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
 
                ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
-               if (ret) {
+               if (ret != 2) {
                        seq_printf(m, "faux/mst read failed\n");
                        goto out;
                }
                seq_printf(m, "faux/mst: %*ph\n", 2, buf);
 
                ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
-               if (ret) {
+               if (ret != 1) {
                        seq_printf(m, "mst ctrl read failed\n");
                        goto out;
                }
@@ -4922,7 +4804,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 
                /* dump the standard OUI branch header */
                ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
-               if (ret) {
+               if (ret != DP_BRANCH_OUI_HEADER_SIZE) {
                        seq_printf(m, "branch oui read failed\n");
                        goto out;
                }
@@ -4938,7 +4820,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 
 out:
        mutex_unlock(&mgr->lock);
-
+       drm_modeset_unlock(&mgr->base.lock);
 }
 EXPORT_SYMBOL(drm_dp_mst_dump_topology);
 
@@ -5060,7 +4942,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 {
        struct drm_dp_mst_topology_state *state, *old_state =
                to_dp_mst_topology_state(obj->state);
-       struct drm_dp_vcpi_allocation *pos, *vcpi;
+       struct drm_dp_mst_atomic_payload *pos, *payload;
 
        state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
        if (!state)
@@ -5068,25 +4950,28 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
        __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
 
-       INIT_LIST_HEAD(&state->vcpis);
+       INIT_LIST_HEAD(&state->payloads);
+       state->commit_deps = NULL;
+       state->num_commit_deps = 0;
+       state->pending_crtc_mask = 0;
 
-       list_for_each_entry(pos, &old_state->vcpis, next) {
-               /* Prune leftover freed VCPI allocations */
-               if (!pos->vcpi)
+       list_for_each_entry(pos, &old_state->payloads, next) {
+               /* Prune leftover freed timeslot allocations */
+               if (pos->delete)
                        continue;
 
-               vcpi = kmemdup(pos, sizeof(*vcpi), GFP_KERNEL);
-               if (!vcpi)
+               payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL);
+               if (!payload)
                        goto fail;
 
-               drm_dp_mst_get_port_malloc(vcpi->port);
-               list_add(&vcpi->next, &state->vcpis);
+               drm_dp_mst_get_port_malloc(payload->port);
+               list_add(&payload->next, &state->payloads);
        }
 
        return &state->base;
 
 fail:
-       list_for_each_entry_safe(pos, vcpi, &state->vcpis, next) {
+       list_for_each_entry_safe(pos, payload, &state->payloads, next) {
                drm_dp_mst_put_port_malloc(pos->port);
                kfree(pos);
        }
@@ -5100,15 +4985,20 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj,
 {
        struct drm_dp_mst_topology_state *mst_state =
                to_dp_mst_topology_state(state);
-       struct drm_dp_vcpi_allocation *pos, *tmp;
+       struct drm_dp_mst_atomic_payload *pos, *tmp;
+       int i;
 
-       list_for_each_entry_safe(pos, tmp, &mst_state->vcpis, next) {
-               /* We only keep references to ports with non-zero VCPIs */
-               if (pos->vcpi)
+       list_for_each_entry_safe(pos, tmp, &mst_state->payloads, next) {
+               /* We only keep references to ports with active payloads */
+               if (!pos->delete)
                        drm_dp_mst_put_port_malloc(pos->port);
                kfree(pos);
        }
 
+       for (i = 0; i < mst_state->num_commit_deps; i++)
+               drm_crtc_commit_put(mst_state->commit_deps[i]);
+
+       kfree(mst_state->commit_deps);
        kfree(mst_state);
 }
 
@@ -5135,7 +5025,7 @@ static int
 drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
                                      struct drm_dp_mst_topology_state *state)
 {
-       struct drm_dp_vcpi_allocation *vcpi;
+       struct drm_dp_mst_atomic_payload *payload;
        struct drm_dp_mst_port *port;
        int pbn_used = 0, ret;
        bool found = false;
@@ -5143,9 +5033,9 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
        /* Check that we have at least one port in our state that's downstream
         * of this branch, otherwise we can skip this branch
         */
-       list_for_each_entry(vcpi, &state->vcpis, next) {
-               if (!vcpi->pbn ||
-                   !drm_dp_mst_port_downstream_of_branch(vcpi->port, mstb))
+       list_for_each_entry(payload, &state->payloads, next) {
+               if (!payload->pbn ||
+                   !drm_dp_mst_port_downstream_of_branch(payload->port, mstb))
                        continue;
 
                found = true;
@@ -5176,25 +5066,15 @@ static int
 drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
                                      struct drm_dp_mst_topology_state *state)
 {
-       struct drm_dp_vcpi_allocation *vcpi;
+       struct drm_dp_mst_atomic_payload *payload;
        int pbn_used = 0;
 
        if (port->pdt == DP_PEER_DEVICE_NONE)
                return 0;
 
        if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
-               bool found = false;
-
-               list_for_each_entry(vcpi, &state->vcpis, next) {
-                       if (vcpi->port != port)
-                               continue;
-                       if (!vcpi->pbn)
-                               return 0;
-
-                       found = true;
-                       break;
-               }
-               if (!found)
+               payload = drm_atomic_get_mst_payload_state(state, port);
+               if (!payload)
                        return 0;
 
                /*
@@ -5208,7 +5088,7 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
                        return -EINVAL;
                }
 
-               pbn_used = vcpi->pbn;
+               pbn_used = payload->pbn;
        } else {
                pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
                                                                 state);
@@ -5230,28 +5110,28 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 }
 
 static inline int
-drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr,
-                                        struct drm_dp_mst_topology_state *mst_state)
+drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr,
+                                            struct drm_dp_mst_topology_state *mst_state)
 {
-       struct drm_dp_vcpi_allocation *vcpi;
+       struct drm_dp_mst_atomic_payload *payload;
        int avail_slots = mst_state->total_avail_slots, payload_count = 0;
 
-       list_for_each_entry(vcpi, &mst_state->vcpis, next) {
-               /* Releasing VCPI is always OK-even if the port is gone */
-               if (!vcpi->vcpi) {
-                       drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all VCPI slots\n",
-                                      vcpi->port);
+       list_for_each_entry(payload, &mst_state->payloads, next) {
+               /* Releasing payloads is always OK-even if the port is gone */
+               if (payload->delete) {
+                       drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all time slots\n",
+                                      payload->port);
                        continue;
                }
 
-               drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d vcpi slots\n",
-                              vcpi->port, vcpi->vcpi);
+               drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d time slots\n",
+                              payload->port, payload->time_slots);
 
-               avail_slots -= vcpi->vcpi;
+               avail_slots -= payload->time_slots;
                if (avail_slots < 0) {
                        drm_dbg_atomic(mgr->dev,
-                                      "[MST PORT:%p] not enough VCPI slots in mst state %p (avail=%d)\n",
-                                      vcpi->port, mst_state, avail_slots + vcpi->vcpi);
+                                      "[MST PORT:%p] not enough time slots in mst state %p (avail=%d)\n",
+                                      payload->port, mst_state, avail_slots + payload->time_slots);
                        return -ENOSPC;
                }
 
@@ -5261,9 +5141,22 @@ drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr,
                                       mgr, mst_state, mgr->max_payloads);
                        return -EINVAL;
                }
+
+               /* Assign a VCPI */
+               if (!payload->vcpi) {
+                       payload->vcpi = ffz(mst_state->payload_mask) + 1;
+                       drm_dbg_atomic(mgr->dev, "[MST PORT:%p] assigned VCPI #%d\n",
+                                      payload->port, payload->vcpi);
+                       mst_state->payload_mask |= BIT(payload->vcpi - 1);
+               }
        }
-       drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p VCPI avail=%d used=%d\n",
-                      mgr, mst_state, avail_slots, mst_state->total_avail_slots - avail_slots);
+
+       if (!payload_count)
+               mst_state->pbn_div = 0;
+
+       drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n",
+                      mgr, mst_state, mst_state->pbn_div, avail_slots,
+                      mst_state->total_avail_slots - avail_slots);
 
        return 0;
 }
@@ -5284,7 +5177,7 @@ drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr,
 int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr)
 {
        struct drm_dp_mst_topology_state *mst_state;
-       struct drm_dp_vcpi_allocation *pos;
+       struct drm_dp_mst_atomic_payload *pos;
        struct drm_connector *connector;
        struct drm_connector_state *conn_state;
        struct drm_crtc *crtc;
@@ -5295,7 +5188,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm
        if (IS_ERR(mst_state))
                return -EINVAL;
 
-       list_for_each_entry(pos, &mst_state->vcpis, next) {
+       list_for_each_entry(pos, &mst_state->payloads, next) {
 
                connector = pos->port->connector;
 
@@ -5334,7 +5227,6 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs);
  * @state: Pointer to the new drm_atomic_state
  * @port: Pointer to the affected MST Port
  * @pbn: Newly recalculated bw required for link with DSC enabled
- * @pbn_div: Divider to calculate correct number of pbn per slot
  * @enable: Boolean flag to enable or disable DSC on the port
  *
  * This function enables DSC on the given Port
@@ -5345,54 +5237,46 @@ EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs);
  */
 int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
                                 struct drm_dp_mst_port *port,
-                                int pbn, int pbn_div,
-                                bool enable)
+                                int pbn, bool enable)
 {
        struct drm_dp_mst_topology_state *mst_state;
-       struct drm_dp_vcpi_allocation *pos;
-       bool found = false;
-       int vcpi = 0;
+       struct drm_dp_mst_atomic_payload *payload;
+       int time_slots = 0;
 
        mst_state = drm_atomic_get_mst_topology_state(state, port->mgr);
-
        if (IS_ERR(mst_state))
                return PTR_ERR(mst_state);
 
-       list_for_each_entry(pos, &mst_state->vcpis, next) {
-               if (pos->port == port) {
-                       found = true;
-                       break;
-               }
-       }
-
-       if (!found) {
+       payload = drm_atomic_get_mst_payload_state(mst_state, port);
+       if (!payload) {
                drm_dbg_atomic(state->dev,
-                              "[MST PORT:%p] Couldn't find VCPI allocation in mst state %p\n",
+                              "[MST PORT:%p] Couldn't find payload in mst state %p\n",
                               port, mst_state);
                return -EINVAL;
        }
 
-       if (pos->dsc_enabled == enable) {
+       if (payload->dsc_enabled == enable) {
                drm_dbg_atomic(state->dev,
-                              "[MST PORT:%p] DSC flag is already set to %d, returning %d VCPI slots\n",
-                              port, enable, pos->vcpi);
-               vcpi = pos->vcpi;
+                              "[MST PORT:%p] DSC flag is already set to %d, returning %d time slots\n",
+                              port, enable, payload->time_slots);
+               time_slots = payload->time_slots;
        }
 
        if (enable) {
-               vcpi = drm_dp_atomic_find_vcpi_slots(state, port->mgr, port, pbn, pbn_div);
+               time_slots = drm_dp_atomic_find_time_slots(state, port->mgr, port, pbn);
                drm_dbg_atomic(state->dev,
-                              "[MST PORT:%p] Enabling DSC flag, reallocating %d VCPI slots on the port\n",
-                              port, vcpi);
-               if (vcpi < 0)
+                              "[MST PORT:%p] Enabling DSC flag, reallocating %d time slots on the port\n",
+                              port, time_slots);
+               if (time_slots < 0)
                        return -EINVAL;
        }
 
-       pos->dsc_enabled = enable;
+       payload->dsc_enabled = enable;
 
-       return vcpi;
+       return time_slots;
 }
 EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
+
 /**
  * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
  * atomic update is valid
@@ -5400,15 +5284,15 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
  *
  * Checks the given topology state for an atomic update to ensure that it's
  * valid. This includes checking whether there's enough bandwidth to support
- * the new VCPI allocations in the atomic update.
+ * the new timeslot allocations in the atomic update.
  *
  * Any atomic drivers supporting DP MST must make sure to call this after
  * checking the rest of their state in their
  * &drm_mode_config_funcs.atomic_check() callback.
  *
  * See also:
- * drm_dp_atomic_find_vcpi_slots()
- * drm_dp_atomic_release_vcpi_slots()
+ * drm_dp_atomic_find_time_slots()
+ * drm_dp_atomic_release_time_slots()
  *
  * Returns:
  *
@@ -5424,7 +5308,7 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
                if (!mgr->mst_state)
                        continue;
 
-               ret = drm_dp_mst_atomic_check_vcpi_alloc_limit(mgr, mst_state);
+               ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
                if (ret)
                        break;
 
@@ -5450,7 +5334,6 @@ EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs);
 
 /**
  * drm_atomic_get_mst_topology_state: get MST topology state
- *
  * @state: global atomic state
  * @mgr: MST topology manager, also the private object in this case
  *
@@ -5469,6 +5352,31 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
 }
 EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
 
+/**
+ * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
+ * @state: global atomic state
+ * @mgr: MST topology manager, also the private object in this case
+ *
+ * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
+ * state vtable so that the private object state returned is that of a MST
+ * topology object.
+ *
+ * Returns:
+ *
+ * The MST topology state, or NULL if there's no topology state for this MST mgr
+ * in the global atomic state
+ */
+struct drm_dp_mst_topology_state *
+drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
+                                     struct drm_dp_mst_topology_mgr *mgr)
+{
+       struct drm_private_state *priv_state =
+               drm_atomic_get_new_private_obj_state(state, &mgr->base);
+
+       return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
+
 /**
  * drm_dp_mst_topology_mgr_init - initialise a topology manager
  * @mgr: manager struct to initialise
@@ -5476,8 +5384,6 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
  * @aux: DP helper aux channel to talk to this device
  * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
  * @max_payloads: maximum number of payloads this GPU can source
- * @max_lane_count: maximum number of lanes this GPU supports
- * @max_link_rate: maximum link rate per lane this GPU supports in kHz
  * @conn_base_id: the connector object ID the MST device is connected to.
  *
  * Return 0 for success, or negative error code on failure
@@ -5485,14 +5391,12 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
 int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
                                 struct drm_device *dev, struct drm_dp_aux *aux,
                                 int max_dpcd_transaction_bytes, int max_payloads,
-                                int max_lane_count, int max_link_rate,
                                 int conn_base_id)
 {
        struct drm_dp_mst_topology_state *mst_state;
 
        mutex_init(&mgr->lock);
        mutex_init(&mgr->qlock);
-       mutex_init(&mgr->payload_lock);
        mutex_init(&mgr->delayed_destroy_lock);
        mutex_init(&mgr->up_req_lock);
        mutex_init(&mgr->probe_lock);
@@ -5522,19 +5426,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
        mgr->aux = aux;
        mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
        mgr->max_payloads = max_payloads;
-       mgr->max_lane_count = max_lane_count;
-       mgr->max_link_rate = max_link_rate;
        mgr->conn_base_id = conn_base_id;
-       if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 ||
-           max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8)
-               return -EINVAL;
-       mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL);
-       if (!mgr->payloads)
-               return -ENOMEM;
-       mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL);
-       if (!mgr->proposed_vcpis)
-               return -ENOMEM;
-       set_bit(0, &mgr->payload_mask);
 
        mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL);
        if (mst_state == NULL)
@@ -5544,7 +5436,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
        mst_state->start_slot = 1;
 
        mst_state->mgr = mgr;
-       INIT_LIST_HEAD(&mst_state->vcpis);
+       INIT_LIST_HEAD(&mst_state->payloads);
 
        drm_atomic_private_obj_init(dev, &mgr->base,
                                    &mst_state->base,
@@ -5567,19 +5459,12 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
                destroy_workqueue(mgr->delayed_destroy_wq);
                mgr->delayed_destroy_wq = NULL;
        }
-       mutex_lock(&mgr->payload_lock);
-       kfree(mgr->payloads);
-       mgr->payloads = NULL;
-       kfree(mgr->proposed_vcpis);
-       mgr->proposed_vcpis = NULL;
-       mutex_unlock(&mgr->payload_lock);
        mgr->dev = NULL;
        mgr->aux = NULL;
        drm_atomic_private_obj_fini(&mgr->base);
        mgr->funcs = NULL;
 
        mutex_destroy(&mgr->delayed_destroy_lock);
-       mutex_destroy(&mgr->payload_lock);
        mutex_destroy(&mgr->qlock);
        mutex_destroy(&mgr->lock);
        mutex_destroy(&mgr->up_req_lock);