[Patch v2 2/3] drm/mst: Refactor the flow for payload allocation/removement
Lin, Wayne
Wayne.Lin at amd.com
Tue Aug 8 03:49:00 UTC 2023
[AMD Official Use Only - General]
Thanks for your time, Lyude!
Regards,
Wayne
> -----Original Message-----
> From: Lyude Paul <lyude at redhat.com>
> Sent: Tuesday, August 8, 2023 4:23 AM
> To: Lin, Wayne <Wayne.Lin at amd.com>; dri-devel at lists.freedesktop.org;
> amd-gfx at lists.freedesktop.org
> Cc: jani.nikula at intel.com; ville.syrjala at linux.intel.com; imre.deak at intel.com;
> Wentland, Harry <Harry.Wentland at amd.com>; Zuo, Jerry
> <Jerry.Zuo at amd.com>
> Subject: Re: [Patch v2 2/3] drm/mst: Refactor the flow for payload
> allocation/removement
>
> Oooooo! This is a wonderful idea so far - keeping track of the status of
> allocations like this solves a lot of problems, especially with regards to the fact
> this actually seems to make it possible for us to have much better handling of
> payload failures in drivers - especially in situations like suspend/resume. The
> naming changes here are awesome too.
>
> I think this patch is good as far as I can tell review-wise! I haven't been able to
> test it quite yet but I'll do it asap.
>
> On Mon, 2023-08-07 at 10:56 +0800, Wayne Lin wrote:
> > [Why]
> > Today, the allocation/deallocation steps and status is a bit unclear.
> >
> > For instance, payload->vc_start_slot = -1 stands for "the failure of
> > updating DPCD payload ID table" and can also represent as "payload is
> > not allocated yet". These two cases should be handled differently and
> > hence better to distinguish them for better understanding.
> >
> > [How]
> > Define enumeration - ALLOCATION_LOCAL, ALLOCATION_DFP and
> > ALLOCATION_REMOTE to distinguish different allocation status. Adjust
> > the code to handle different status accordingly for better
> > understanding the sequence of payload allocation and payload
> removement.
> >
> > For payload creation, the procedure should look like this:
> > DRM part 1:
> > * step 1 - update sw mst mgr variables to add a new payload
> > * step 2 - add payload at immediate DFP DPCD payload table
> >
> > Driver:
> > * Add new payload in HW and sync up with DFP by sending ACT
> >
> > DRM Part 2:
> > * Send ALLOCATE_PAYLOAD sideband message to allocate bandwidth along
> the
> > virtual channel.
> >
> > And as for payload removement, the procedure should look like this:
> > DRM part 1:
> > * step 1 - Send ALLOCATE_PAYLOAD sideband message to release bandwidth
> > along the virtual channel
> > * step 2 - Clear payload allocation at immediate DFP DPCD payload
> > table
> >
> > Driver:
> > * Remove the payload in HW and sync up with DFP by sending ACT
> >
> > DRM part 2:
> > * update sw mst mgr variables to remove the payload
> >
> > Note that it's fine to fail when communicate with the branch device
> > connected at immediate downstrean-facing port, but updating variables
> > of SW mst mgr and HW configuration should be conducted anyway. That's
> > because it's under commit_tail and we need to complete the HW
> programming.
>
> yay!
>
> >
> > Changes since v1:
> > * Remove the set but not use variable 'old_payload' in function
> > 'nv50_msto_prepare'. Catched by kernel test robot <lkp at intel.com>
> >
> > Signed-off-by: Wayne Lin <Wayne.Lin at amd.com>
> > ---
> > .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 20 ++-
> > drivers/gpu/drm/display/drm_dp_mst_topology.c | 159 +++++++++++------
> -
> > drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 +-
> > drivers/gpu/drm/nouveau/dispnv50/disp.c | 21 +--
> > include/drm/display/drm_dp_mst_helper.h | 23 ++-
> > 5 files changed, 153 insertions(+), 88 deletions(-)
> >
> > diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > index d9a482908380..9ad509279b0a 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > @@ -219,7 +219,7 @@ static void dm_helpers_construct_old_payload(
> > /* Set correct time_slots/PBN of old payload.
> > * other fields (delete & dsc_enabled) in
> > * struct drm_dp_mst_atomic_payload are don't care fields
> > - * while calling drm_dp_remove_payload()
> > + * while calling drm_dp_remove_payload_part2()
> > */
> > for (i = 0; i < current_link_table.stream_count; i++) {
> > dc_alloc =
> > @@ -262,13 +262,12 @@ bool
> > dm_helpers_dp_mst_write_payload_allocation_table(
> >
> > mst_mgr = &aconnector->mst_root->mst_mgr;
> > mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
> > -
> > - /* It's OK for this to fail */
> > new_payload = drm_atomic_get_mst_payload_state(mst_state,
> > aconnector->mst_output_port);
> >
> > if (enable) {
> > target_payload = new_payload;
> >
> > + /* It's OK for this to fail */
> > drm_dp_add_payload_part1(mst_mgr, mst_state,
> new_payload);
> > } else {
> > /* construct old payload by VCPI*/
> > @@ -276,7 +275,7 @@ bool
> dm_helpers_dp_mst_write_payload_allocation_table(
> > new_payload, &old_payload);
> > target_payload = &old_payload;
> >
> > - drm_dp_remove_payload(mst_mgr, mst_state,
> &old_payload, new_payload);
> > + drm_dp_remove_payload_part1(mst_mgr, mst_state,
> new_payload);
> > }
> >
> > /* mst_mgr->->payloads are VC payload notify MST branch using
> DPCD
> > or @@ -342,7 +341,7 @@ bool
> dm_helpers_dp_mst_send_payload_allocation(
> > struct amdgpu_dm_connector *aconnector;
> > struct drm_dp_mst_topology_state *mst_state;
> > struct drm_dp_mst_topology_mgr *mst_mgr;
> > - struct drm_dp_mst_atomic_payload *payload;
> > + struct drm_dp_mst_atomic_payload *new_payload, *old_payload;
> > enum mst_progress_status set_flag =
> MST_ALLOCATE_NEW_PAYLOAD;
> > enum mst_progress_status clr_flag =
> MST_CLEAR_ALLOCATED_PAYLOAD;
> > int ret = 0;
> > @@ -355,15 +354,20 @@ bool
> dm_helpers_dp_mst_send_payload_allocation(
> > mst_mgr = &aconnector->mst_root->mst_mgr;
> > mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
> >
> > - payload = drm_atomic_get_mst_payload_state(mst_state,
> aconnector->mst_output_port);
> > + new_payload = drm_atomic_get_mst_payload_state(mst_state,
> > +aconnector->mst_output_port);
> >
> > if (!enable) {
> > set_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
> > clr_flag = MST_ALLOCATE_NEW_PAYLOAD;
> > }
> >
> > - if (enable)
> > - ret = drm_dp_add_payload_part2(mst_mgr, mst_state-
> >base.state, payload);
> > + if (enable) {
> > + ret = drm_dp_add_payload_part2(mst_mgr, mst_state-
> >base.state, new_payload);
> > + } else {
> > + dm_helpers_construct_old_payload(stream->link, mst_state-
> >pbn_div,
> > + new_payload, old_payload);
> > + drm_dp_remove_payload_part2(mst_mgr, mst_state,
> old_payload, new_payload);
> > + }
> >
> > if (ret) {
> > amdgpu_dm_set_mst_status(&aconnector->mst_status,
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 4d80426757ab..e04f87ff755a 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -3255,15 +3255,15 @@ int
> drm_dp_send_query_stream_enc_status(struct
> > drm_dp_mst_topology_mgr *mgr, }
> > EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status);
> >
> > -static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr
> *mgr,
> > - struct drm_dp_mst_atomic_payload
> *payload)
> > +static int drm_dp_create_payload_at_dfp(struct
> drm_dp_mst_topology_mgr *mgr,
> > + struct drm_dp_mst_atomic_payload
> *payload)
> > {
> > 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_atomic_payload
> *payload)
> > +static int drm_dp_create_payload_to_remote(struct
> drm_dp_mst_topology_mgr *mgr,
> > + 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); @@ -
> 3276,17 +3276,20 @@ static int drm_dp_create_payload_step2(struct
> drm_dp_mst_topology_mgr *mgr,
> > return ret;
> > }
> >
> > -static int drm_dp_destroy_payload_step1(struct
> drm_dp_mst_topology_mgr *mgr,
> > - struct drm_dp_mst_topology_state
> *mst_state,
> > - struct drm_dp_mst_atomic_payload
> *payload)
> > +static void drm_dp_destroy_payload_at_remote_and_dfp(struct
> drm_dp_mst_topology_mgr *mgr,
> > + 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 */
> > - drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0);
> > - drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload-
> >vc_start_slot, 0);
> > + if (payload->payload_allocation_status ==
> DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE) {
> > + drm_dp_payload_send_msg(mgr, payload->port, payload-
> >vcpi, 0);
> > + payload->payload_allocation_status =
> DRM_DP_MST_PAYLOAD_ALLOCATION_DFP;
> > + }
> >
> > - return 0;
> > + if (payload->payload_allocation_status ==
> DRM_DP_MST_PAYLOAD_ALLOCATION_DFP)
> > + drm_dp_dpcd_write_payload(mgr, payload->vcpi,
> > +payload->vc_start_slot, 0);
> > }
> >
> > /**
> > @@ -3296,81 +3299,105 @@ static int
> drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
> > * @payload: The payload to write
> > *
> > * 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.
> > + * into the DPCD of DPRX. 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.
> > + * Returns: 0 on success, error code on failure.
> > */
> > 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_mst_port *port;
> > - int ret;
> > + int ret = 0;
> > + bool allocate = true;
> > +
> > + /* Update mst mgr info */
> > + if (mgr->payload_count == 0)
> > + mgr->next_start_slot = mst_state->start_slot;
> > +
> > + payload->vc_start_slot = mgr->next_start_slot;
> > +
> > + mgr->payload_count++;
> > + mgr->next_start_slot += payload->time_slots;
> >
> > + /* Allocate payload to immediate downstream facing port */
> > port = drm_dp_mst_topology_get_port_validated(mgr, payload-
> >port);
> > if (!port) {
> > drm_dbg_kms(mgr->dev,
> > - "VCPI %d for port %p not in topology, not creating a
> payload\n",
> > + "VCPI %d for port %p not in topology, not creating a
> payload
> > +to remote\n",
> > payload->vcpi, payload->port);
> > - payload->vc_start_slot = -1;
> > - return 0;
> > + allocate = false;
> > }
> >
> > - if (mgr->payload_count == 0)
> > - mgr->next_start_slot = mst_state->start_slot;
> > -
> > - payload->vc_start_slot = mgr->next_start_slot;
> > + if (allocate) {
> > + ret = drm_dp_create_payload_at_dfp(mgr, payload);
> > + if (ret < 0)
> > + drm_warn(mgr->dev, "Failed to create MST payload
> for port %p: %d\n",
> > + payload->port, ret);
> >
> > - 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;
> > }
> >
> > - mgr->payload_count++;
> > - mgr->next_start_slot += payload->time_slots;
> > + payload->payload_allocation_status =
> > + (!allocate || ret < 0) ?
> DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL :
> > +
> DRM_DP_MST_PAYLOAD_ALLOCATION_DFP;
> >
> > - return 0;
> > + drm_dp_mst_topology_put_port(port);
> > +
> > + return ret;
> > }
> > EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >
> > /**
> > - * drm_dp_remove_payload() - Remove an MST payload
> > + * drm_dp_remove_payload_part1() - Remove an MST payload along the
> > + virtual channel
> > * @mgr: Manager to use.
> > * @mst_state: The MST atomic state
> > - * @old_payload: The payload with its old state
> > - * @new_payload: The payload to write
> > + * @payload: The payload to remove
> > *
> > - * 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.
> > + * Removes a payload along the virtual channel if it was successfully
> allocated.
> > + * After calling this, the driver should set HW to generate ACT and
> > + then switch to new
> > + * payload allocation state.
> > */
> > -void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > - struct drm_dp_mst_topology_state *mst_state,
> > - const struct drm_dp_mst_atomic_payload
> *old_payload,
> > - struct drm_dp_mst_atomic_payload *new_payload)
> > +void drm_dp_remove_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_mst_atomic_payload *pos;
> > + /* Remove remote payload allocation */
> > bool send_remove = false;
> >
> > - /* We failed to make the payload, so nothing to do */
> > - if (new_payload->vc_start_slot == -1)
> > - return;
> > -
> > mutex_lock(&mgr->lock);
> > - send_remove =
> drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr-
> >mst_primary);
> > + send_remove = drm_dp_mst_port_downstream_of_branch(payload-
> >port,
> > +mgr->mst_primary);
> > mutex_unlock(&mgr->lock);
> >
> > if (send_remove)
> > - drm_dp_destroy_payload_step1(mgr, mst_state,
> new_payload);
> > + drm_dp_destroy_payload_at_remote_and_dfp(mgr,
> mst_state, payload);
> > else
> > drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in
> topology, not sending remove\n",
> > - new_payload->vcpi);
> > + payload->vcpi);
> > +
> > + payload->payload_allocation_status =
> > +DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL;
> > +}
> > +EXPORT_SYMBOL(drm_dp_remove_payload_part1);
> >
> > +/**
> > + * drm_dp_remove_payload_part2() - Remove an MST payload locally
> > + * @mgr: Manager to use.
> > + * @mst_state: The MST atomic state
> > + * @old_payload: The payload with its old state
> > + * @new_payload: The payload with its latest state
> > + *
> > + * Updates the starting time slots of all other payloads which would
> > +have been shifted towards
> > + * the start of the payload ID table as a result of removing a
> > +payload. Driver should call this
> > + * function whenever it removes a payload in its HW. It's independent
> > +to the result of payload
> > + * allocation/deallocation at branch devices along the virtual channel.
> > + */
> > +void drm_dp_remove_payload_part2(struct drm_dp_mst_topology_mgr
> *mgr,
> > + struct drm_dp_mst_topology_state
> *mst_state,
> > + const struct drm_dp_mst_atomic_payload
> *old_payload,
> > + struct drm_dp_mst_atomic_payload
> *new_payload) {
> > + struct drm_dp_mst_atomic_payload *pos;
> > +
> > + /* Remove local payload allocation */
> > list_for_each_entry(pos, &mst_state->payloads, next) {
> > if (pos != new_payload && pos->vc_start_slot > new_payload-
> >vc_start_slot)
> > pos->vc_start_slot -= old_payload->time_slots; @@ -
> 3382,9 +3409,10
> > @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr
> *mgr,
> >
> > if (new_payload->delete)
> > drm_dp_mst_put_port_malloc(new_payload->port);
> > -}
> > -EXPORT_SYMBOL(drm_dp_remove_payload);
> >
> > + new_payload->payload_allocation_status =
> > +DRM_DP_MST_PAYLOAD_ALLOCATION_NONE;
> > +}
> > +EXPORT_SYMBOL(drm_dp_remove_payload_part2);
> > /**
> > * drm_dp_add_payload_part2() - Execute payload update part 2
> > * @mgr: Manager to use.
> > @@ -3403,17 +3431,19 @@ int drm_dp_add_payload_part2(struct
> drm_dp_mst_topology_mgr *mgr,
> > int ret = 0;
> >
> > /* Skip failed payloads */
> > - if (payload->vc_start_slot == -1) {
> > - drm_dbg_kms(mgr->dev, "Part 1 of payload creation for %s
> failed, skipping part 2\n",
> > + if (payload->payload_allocation_status !=
> DRM_DP_MST_PAYLOAD_ALLOCATION_DFP) {
> > + drm_dbg_kms(state->dev, "Part 1 of payload creation for %s
> failed,
> > +skipping part 2\n",
> > payload->port->connector->name);
> > return -EIO;
> > }
> >
> > - ret = drm_dp_create_payload_step2(mgr, payload);
> > - if (ret < 0) {
> > + /* Allocate payload to remote end */
> > + ret = drm_dp_create_payload_to_remote(mgr, payload);
> > + if (ret < 0)
> > drm_err(mgr->dev, "Step 2 of creating MST payload for %p
> failed: %d\n",
> > payload->port, ret);
> > - }
> > + else
> > + payload->payload_allocation_status =
> > +DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE;
> >
> > return ret;
> > }
> > @@ -4324,6 +4354,7 @@ int drm_dp_atomic_find_time_slots(struct
> drm_atomic_state *state,
> > drm_dp_mst_get_port_malloc(port);
> > payload->port = port;
> > payload->vc_start_slot = -1;
> > + payload->payload_allocation_status =
> > +DRM_DP_MST_PAYLOAD_ALLOCATION_NONE;
> > list_add(&payload->next, &topology_state->payloads);
> > }
> > payload->time_slots = req_slots;
> > @@ -4493,7 +4524,7 @@ void
> drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state
> *state)
> > }
> >
> > /* Now that previous state is committed, it's safe to copy over
> the start slot
> > - * assignments
> > + * and allocation status assignments
> > */
> > list_for_each_entry(old_payload, &old_mst_state->payloads,
> next) {
> > if (old_payload->delete)
> > @@ -4502,6 +4533,8 @@ void
> drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state
> *state)
> > new_payload =
> drm_atomic_get_mst_payload_state(new_mst_state,
> >
> old_payload->port);
> > new_payload->vc_start_slot = old_payload-
> >vc_start_slot;
> > + new_payload->payload_allocation_status =
> > + old_payload-
> >payload_allocation_status;
> > }
> > }
> > }
> > @@ -4818,6 +4851,13 @@ void drm_dp_mst_dump_topology(struct
> seq_file *m,
> > struct drm_dp_mst_atomic_payload *payload;
> > int i, ret;
> >
> > + static const char *const status[] = {
> > + "None",
> > + "Local",
> > + "DFP",
> > + "Remote",
> > + };
> > +
> > mutex_lock(&mgr->lock);
> > if (mgr->mst_primary)
> > drm_dp_mst_dump_mstb(m, mgr->mst_primary); @@ -
> 4834,7 +4874,7 @@
> > void drm_dp_mst_dump_topology(struct seq_file *m,
> > 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 | vcpi | slots | pbn | dsc | sink name
> |\n");
> > + seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | status | sink
> name |\n");
> > for (i = 0; i < mgr->max_payloads; i++) {
> > list_for_each_entry(payload, &state->payloads, next) {
> > char name[14];
> > @@ -4843,7 +4883,7 @@ void drm_dp_mst_dump_topology(struct
> seq_file *m,
> > continue;
> >
> > fetch_monitor_name(mgr, payload->port, name,
> sizeof(name));
> > - seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s
> %19s\n",
> > + seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s
> %8s %19s\n",
> > i,
> > payload->port->port_num,
> > payload->vcpi,
> > @@ -4851,6 +4891,7 @@ void drm_dp_mst_dump_topology(struct
> seq_file *m,
> > payload->vc_start_slot + payload-
> >time_slots - 1,
> > payload->pbn,
> > payload->dsc_enabled ? "Y" : "N",
> > + status[payload->payload_allocation_status],
> > (*name != 0) ? name : "Unknown");
> > }
> > }
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index e3f176a093d2..5f73cdabe7a1 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -557,12 +557,8 @@ static void intel_mst_disable_dp(struct
> intel_atomic_state *state,
> > struct intel_dp *intel_dp = &dig_port->dp;
> > struct intel_connector *connector =
> > to_intel_connector(old_conn_state->connector);
> > - struct drm_dp_mst_topology_state *old_mst_state =
> > - drm_atomic_get_old_mst_topology_state(&state->base,
> &intel_dp->mst_mgr);
> > struct drm_dp_mst_topology_state *new_mst_state =
> > drm_atomic_get_new_mst_topology_state(&state->base,
> &intel_dp->mst_mgr);
> > - const struct drm_dp_mst_atomic_payload *old_payload =
> > - drm_atomic_get_mst_payload_state(old_mst_state,
> connector->port);
> > struct drm_dp_mst_atomic_payload *new_payload =
> > drm_atomic_get_mst_payload_state(new_mst_state,
> connector->port);
> > struct drm_i915_private *i915 = to_i915(connector->base.dev); @@
> > -572,8 +568,7 @@ static void intel_mst_disable_dp(struct
> > intel_atomic_state *state,
> >
> > intel_hdcp_disable(intel_mst->connector);
> >
> > - drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
> > - old_payload, new_payload);
> > + drm_dp_remove_payload_part1(&intel_dp->mst_mgr,
> new_mst_state,
> > +new_payload);
> >
> > intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > } @@ -588,6 +583,14 @@ static void intel_mst_post_disable_dp(struct
> > intel_atomic_state *state,
> > struct intel_dp *intel_dp = &dig_port->dp;
> > struct intel_connector *connector =
> > to_intel_connector(old_conn_state->connector);
> > + struct drm_dp_mst_topology_state *old_mst_state =
> > + drm_atomic_get_old_mst_topology_state(&state->base,
> &intel_dp->mst_mgr);
> > + struct drm_dp_mst_topology_state *new_mst_state =
> > + drm_atomic_get_new_mst_topology_state(&state->base,
> &intel_dp->mst_mgr);
> > + const struct drm_dp_mst_atomic_payload *old_payload =
> > + drm_atomic_get_mst_payload_state(old_mst_state,
> connector->port);
> > + struct drm_dp_mst_atomic_payload *new_payload =
> > + drm_atomic_get_mst_payload_state(new_mst_state,
> connector->port);
> > struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> > bool last_mst_stream;
> >
> > @@ -608,6 +611,9 @@ static void intel_mst_post_disable_dp(struct
> > intel_atomic_state *state,
> >
> > wait_for_act_sent(encoder, old_crtc_state);
> >
> > + drm_dp_remove_payload_part2(&intel_dp->mst_mgr,
> new_mst_state,
> > + old_payload, new_payload);
> > +
> > intel_ddi_disable_transcoder_func(old_crtc_state);
> >
> > if (DISPLAY_VER(dev_priv) >= 9)
> > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > index 4e7c9c353c51..bba01fa0780c 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > @@ -882,21 +882,26 @@ struct nouveau_encoder *nv50_real_outp(struct
> > drm_encoder *encoder)
> >
> > static void
> > nv50_msto_cleanup(struct drm_atomic_state *state,
> > - struct drm_dp_mst_topology_state *mst_state,
> > + struct drm_dp_mst_topology_state *new_mst_state,
> > struct drm_dp_mst_topology_mgr *mgr,
> > struct nv50_msto *msto)
> > {
> > struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
> > - struct drm_dp_mst_atomic_payload *payload =
> > - drm_atomic_get_mst_payload_state(mst_state, msto->mstc-
> >port);
> > + struct drm_dp_mst_atomic_payload *new_payload =
> > + drm_atomic_get_mst_payload_state(new_mst_state, msto-
> >mstc->port);
> > + struct drm_dp_mst_topology_state *old_mst_state =
> > + drm_atomic_get_old_mst_topology_state(state, mgr);
> > + const struct drm_dp_mst_atomic_payload *old_payload =
> > + drm_atomic_get_mst_payload_state(old_mst_state, msto-
> >mstc->port);
> >
> > NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
> >
> > if (msto->disabled) {
> > msto->mstc = NULL;
> > msto->disabled = false;
> > + drm_dp_remove_payload_part2(mgr, new_mst_state,
> old_payload,
> > +new_payload);
> > } else if (msto->enabled) {
> > - drm_dp_add_payload_part2(mgr, state, payload);
> > + drm_dp_add_payload_part2(mgr, state, new_payload);
> > msto->enabled = false;
> > }
> > }
> > @@ -910,19 +915,15 @@ nv50_msto_prepare(struct drm_atomic_state
> *state,
> > struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
> > struct nv50_mstc *mstc = msto->mstc;
> > struct nv50_mstm *mstm = mstc->mstm;
> > - struct drm_dp_mst_topology_state *old_mst_state;
> > - struct drm_dp_mst_atomic_payload *payload, *old_payload;
> > + struct drm_dp_mst_atomic_payload *payload;
> >
> > NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
> >
> > - old_mst_state = drm_atomic_get_old_mst_topology_state(state,
> mgr);
> > -
> > payload = drm_atomic_get_mst_payload_state(mst_state, mstc-
> >port);
> > - old_payload = drm_atomic_get_mst_payload_state(old_mst_state,
> mstc->port);
> >
> > // TODO: Figure out if we want to do a better job of handling VCPI
> allocation failures here?
> > if (msto->disabled) {
> > - drm_dp_remove_payload(mgr, mst_state, old_payload,
> payload);
> > + drm_dp_remove_payload_part1(mgr, mst_state, payload);
> >
> > nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head-
> >base.index, 0, 0, 0, 0);
> > } else {
> > diff --git a/include/drm/display/drm_dp_mst_helper.h
> > b/include/drm/display/drm_dp_mst_helper.h
> > index ed5c9660563c..4429d3b1745b 100644
> > --- a/include/drm/display/drm_dp_mst_helper.h
> > +++ b/include/drm/display/drm_dp_mst_helper.h
> > @@ -46,6 +46,13 @@ struct drm_dp_mst_topology_ref_history { };
> > #endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */
> >
> > +enum drm_dp_mst_payload_allocation {
> > + DRM_DP_MST_PAYLOAD_ALLOCATION_NONE,
> > + DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL,
> > + DRM_DP_MST_PAYLOAD_ALLOCATION_DFP,
> > + DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE,
> > +};
> > +
> > struct drm_dp_mst_branch;
> >
> > /**
> > @@ -537,7 +544,7 @@ struct drm_dp_mst_atomic_payload {
> > * drm_dp_mst_atomic_wait_for_dependencies() has been called,
> which will ensure the
> > * previous MST states payload start slots have been copied over to
> the new state. Note
> > * that a new start slot won't be assigned/removed from this payload
> until
> > - * drm_dp_add_payload_part1()/drm_dp_remove_payload() have
> been called.
> > + * drm_dp_add_payload_part1()/drm_dp_remove_payload_part2()
> have been called.
> > * * Acquire the MST modesetting lock, and then wait for any pending
> MST-related commits to
> > * get committed to hardware by calling drm_crtc_commit_wait() on
> each of the
> > * &drm_crtc_commit structs in
> &drm_dp_mst_topology_state.commit_deps.
> > @@ -564,6 +571,9 @@ struct drm_dp_mst_atomic_payload {
> > /** @dsc_enabled: Whether or not this payload has DSC enabled */
> > bool dsc_enabled : 1;
> >
> > + /** @payload_allocation_status: The allocation status of this payload
> */
> > + enum drm_dp_mst_payload_allocation payload_allocation_status;
> > +
> > /** @next: The list node for this payload */
> > struct list_head next;
> > };
> > @@ -842,10 +852,13 @@ int drm_dp_add_payload_part1(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); -
> void
> > drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > - struct drm_dp_mst_topology_state *mst_state,
> > - const struct drm_dp_mst_atomic_payload
> *old_payload,
> > - struct drm_dp_mst_atomic_payload
> *new_payload);
> > +void drm_dp_remove_payload_part1(struct drm_dp_mst_topology_mgr
> *mgr,
> > + struct drm_dp_mst_topology_state
> *mst_state,
> > + struct drm_dp_mst_atomic_payload
> *payload); void
> > +drm_dp_remove_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > + struct drm_dp_mst_topology_state
> *mst_state,
> > + const struct drm_dp_mst_atomic_payload
> *old_payload,
> > + struct drm_dp_mst_atomic_payload
> *new_payload);
> >
> > int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> >
>
> --
> Cheers,
> Lyude Paul (she/her)
> Software Engineer at Red Hat
More information about the dri-devel
mailing list