@@ -3255,15 +3255,15 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
32553255}
32563256EXPORT_SYMBOL (drm_dp_send_query_stream_enc_status );
32573257
3258- static int drm_dp_create_payload_step1 (struct drm_dp_mst_topology_mgr * mgr ,
3259- struct drm_dp_mst_atomic_payload * payload )
3258+ static int drm_dp_create_payload_at_dfp (struct drm_dp_mst_topology_mgr * mgr ,
3259+ struct drm_dp_mst_atomic_payload * payload )
32603260{
32613261 return drm_dp_dpcd_write_payload (mgr , payload -> vcpi , payload -> vc_start_slot ,
32623262 payload -> time_slots );
32633263}
32643264
3265- static int drm_dp_create_payload_step2 (struct drm_dp_mst_topology_mgr * mgr ,
3266- struct drm_dp_mst_atomic_payload * payload )
3265+ static int drm_dp_create_payload_to_remote (struct drm_dp_mst_topology_mgr * mgr ,
3266+ struct drm_dp_mst_atomic_payload * payload )
32673267{
32683268 int ret ;
32693269 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,
32763276 return ret ;
32773277}
32783278
3279- static int drm_dp_destroy_payload_step1 (struct drm_dp_mst_topology_mgr * mgr ,
3280- struct drm_dp_mst_topology_state * mst_state ,
3281- struct drm_dp_mst_atomic_payload * payload )
3279+ static void drm_dp_destroy_payload_at_remote_and_dfp (struct drm_dp_mst_topology_mgr * mgr ,
3280+ struct drm_dp_mst_topology_state * mst_state ,
3281+ struct drm_dp_mst_atomic_payload * payload )
32823282{
32833283 drm_dbg_kms (mgr -> dev , "\n" );
32843284
32853285 /* it's okay for these to fail */
3286- drm_dp_payload_send_msg (mgr , payload -> port , payload -> vcpi , 0 );
3287- drm_dp_dpcd_write_payload (mgr , payload -> vcpi , payload -> vc_start_slot , 0 );
3286+ if (payload -> payload_allocation_status == DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE ) {
3287+ drm_dp_payload_send_msg (mgr , payload -> port , payload -> vcpi , 0 );
3288+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_DFP ;
3289+ }
32883290
3289- return 0 ;
3291+ if (payload -> payload_allocation_status == DRM_DP_MST_PAYLOAD_ALLOCATION_DFP )
3292+ drm_dp_dpcd_write_payload (mgr , payload -> vcpi , payload -> vc_start_slot , 0 );
32903293}
32913294
32923295/**
@@ -3296,81 +3299,105 @@ static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
32963299 * @payload: The payload to write
32973300 *
32983301 * Determines the starting time slot for the given payload, and programs the VCPI for this payload
3299- * into hardware . After calling this, the driver should generate ACT and payload packets.
3302+ * into the DPCD of DPRX . After calling this, the driver should generate ACT and payload packets.
33003303 *
3301- * Returns: 0 on success, error code on failure. In the event that this fails,
3302- * @payload.vc_start_slot will also be set to -1.
3304+ * Returns: 0 on success, error code on failure.
33033305 */
33043306int drm_dp_add_payload_part1 (struct drm_dp_mst_topology_mgr * mgr ,
33053307 struct drm_dp_mst_topology_state * mst_state ,
33063308 struct drm_dp_mst_atomic_payload * payload )
33073309{
33083310 struct drm_dp_mst_port * port ;
3309- int ret ;
3311+ int ret = 0 ;
3312+ bool allocate = true;
3313+
3314+ /* Update mst mgr info */
3315+ if (mgr -> payload_count == 0 )
3316+ mgr -> next_start_slot = mst_state -> start_slot ;
3317+
3318+ payload -> vc_start_slot = mgr -> next_start_slot ;
3319+
3320+ mgr -> payload_count ++ ;
3321+ mgr -> next_start_slot += payload -> time_slots ;
33103322
3323+ /* Allocate payload to immediate downstream facing port */
33113324 port = drm_dp_mst_topology_get_port_validated (mgr , payload -> port );
33123325 if (!port ) {
33133326 drm_dbg_kms (mgr -> dev ,
3314- "VCPI %d for port %p not in topology, not creating a payload\n" ,
3327+ "VCPI %d for port %p not in topology, not creating a payload to remote \n" ,
33153328 payload -> vcpi , payload -> port );
3316- payload -> vc_start_slot = -1 ;
3317- return 0 ;
3329+ allocate = false;
33183330 }
33193331
3320- if (mgr -> payload_count == 0 )
3321- mgr -> next_start_slot = mst_state -> start_slot ;
3322-
3323- payload -> vc_start_slot = mgr -> next_start_slot ;
3332+ if (allocate ) {
3333+ ret = drm_dp_create_payload_at_dfp (mgr , payload );
3334+ if (ret < 0 )
3335+ drm_warn (mgr -> dev , "Failed to create MST payload for port %p: %d\n" ,
3336+ payload -> port , ret );
33243337
3325- ret = drm_dp_create_payload_step1 (mgr , payload );
3326- drm_dp_mst_topology_put_port (port );
3327- if (ret < 0 ) {
3328- drm_warn (mgr -> dev , "Failed to create MST payload for port %p: %d\n" ,
3329- payload -> port , ret );
3330- payload -> vc_start_slot = -1 ;
3331- return ret ;
33323338 }
33333339
3334- mgr -> payload_count ++ ;
3335- mgr -> next_start_slot += payload -> time_slots ;
3340+ payload -> payload_allocation_status =
3341+ (!allocate || ret < 0 ) ? DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL :
3342+ DRM_DP_MST_PAYLOAD_ALLOCATION_DFP ;
33363343
3337- return 0 ;
3344+ drm_dp_mst_topology_put_port (port );
3345+
3346+ return ret ;
33383347}
33393348EXPORT_SYMBOL (drm_dp_add_payload_part1 );
33403349
33413350/**
3342- * drm_dp_remove_payload () - Remove an MST payload
3351+ * drm_dp_remove_payload_part1 () - Remove an MST payload along the virtual channel
33433352 * @mgr: Manager to use.
33443353 * @mst_state: The MST atomic state
3345- * @old_payload: The payload with its old state
3346- * @new_payload: The payload to write
3354+ * @payload: The payload to remove
33473355 *
3348- * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
3349- * the starting time slots of all other payloads which would have been shifted towards the start of
3350- * the VC table as a result. After calling this, the driver should generate ACT and payload packets .
3356+ * Removes a payload along the virtual channel if it was successfully allocated.
3357+ * After calling this, the driver should set HW to generate ACT and then switch to new
3358+ * payload allocation state .
33513359 */
3352- void drm_dp_remove_payload (struct drm_dp_mst_topology_mgr * mgr ,
3353- struct drm_dp_mst_topology_state * mst_state ,
3354- const struct drm_dp_mst_atomic_payload * old_payload ,
3355- struct drm_dp_mst_atomic_payload * new_payload )
3360+ void drm_dp_remove_payload_part1 (struct drm_dp_mst_topology_mgr * mgr ,
3361+ struct drm_dp_mst_topology_state * mst_state ,
3362+ struct drm_dp_mst_atomic_payload * payload )
33563363{
3357- struct drm_dp_mst_atomic_payload * pos ;
3364+ /* Remove remote payload allocation */
33583365 bool send_remove = false;
33593366
3360- /* We failed to make the payload, so nothing to do */
3361- if (new_payload -> vc_start_slot == -1 )
3362- return ;
3363-
33643367 mutex_lock (& mgr -> lock );
3365- send_remove = drm_dp_mst_port_downstream_of_branch (new_payload -> port , mgr -> mst_primary );
3368+ send_remove = drm_dp_mst_port_downstream_of_branch (payload -> port , mgr -> mst_primary );
33663369 mutex_unlock (& mgr -> lock );
33673370
33683371 if (send_remove )
3369- drm_dp_destroy_payload_step1 (mgr , mst_state , new_payload );
3372+ drm_dp_destroy_payload_at_remote_and_dfp (mgr , mst_state , payload );
33703373 else
33713374 drm_dbg_kms (mgr -> dev , "Payload for VCPI %d not in topology, not sending remove\n" ,
3372- new_payload -> vcpi );
3375+ payload -> vcpi );
3376+
3377+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL ;
3378+ }
3379+ EXPORT_SYMBOL (drm_dp_remove_payload_part1 );
33733380
3381+ /**
3382+ * drm_dp_remove_payload_part2() - Remove an MST payload locally
3383+ * @mgr: Manager to use.
3384+ * @mst_state: The MST atomic state
3385+ * @old_payload: The payload with its old state
3386+ * @new_payload: The payload with its latest state
3387+ *
3388+ * Updates the starting time slots of all other payloads which would have been shifted towards
3389+ * the start of the payload ID table as a result of removing a payload. Driver should call this
3390+ * function whenever it removes a payload in its HW. It's independent to the result of payload
3391+ * allocation/deallocation at branch devices along the virtual channel.
3392+ */
3393+ void drm_dp_remove_payload_part2 (struct drm_dp_mst_topology_mgr * mgr ,
3394+ struct drm_dp_mst_topology_state * mst_state ,
3395+ const struct drm_dp_mst_atomic_payload * old_payload ,
3396+ struct drm_dp_mst_atomic_payload * new_payload )
3397+ {
3398+ struct drm_dp_mst_atomic_payload * pos ;
3399+
3400+ /* Remove local payload allocation */
33743401 list_for_each_entry (pos , & mst_state -> payloads , next ) {
33753402 if (pos != new_payload && pos -> vc_start_slot > new_payload -> vc_start_slot )
33763403 pos -> vc_start_slot -= old_payload -> time_slots ;
@@ -3382,9 +3409,10 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
33823409
33833410 if (new_payload -> delete )
33843411 drm_dp_mst_put_port_malloc (new_payload -> port );
3385- }
3386- EXPORT_SYMBOL (drm_dp_remove_payload );
33873412
3413+ new_payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE ;
3414+ }
3415+ EXPORT_SYMBOL (drm_dp_remove_payload_part2 );
33883416/**
33893417 * drm_dp_add_payload_part2() - Execute payload update part 2
33903418 * @mgr: Manager to use.
@@ -3403,17 +3431,19 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
34033431 int ret = 0 ;
34043432
34053433 /* Skip failed payloads */
3406- if (payload -> vc_start_slot == -1 ) {
3407- drm_dbg_kms (mgr -> dev , "Part 1 of payload creation for %s failed, skipping part 2\n" ,
3434+ if (payload -> payload_allocation_status != DRM_DP_MST_PAYLOAD_ALLOCATION_DFP ) {
3435+ drm_dbg_kms (state -> dev , "Part 1 of payload creation for %s failed, skipping part 2\n" ,
34083436 payload -> port -> connector -> name );
34093437 return - EIO ;
34103438 }
34113439
3412- ret = drm_dp_create_payload_step2 (mgr , payload );
3413- if (ret < 0 ) {
3440+ /* Allocate payload to remote end */
3441+ ret = drm_dp_create_payload_to_remote (mgr , payload );
3442+ if (ret < 0 )
34143443 drm_err (mgr -> dev , "Step 2 of creating MST payload for %p failed: %d\n" ,
34153444 payload -> port , ret );
3416- }
3445+ else
3446+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE ;
34173447
34183448 return ret ;
34193449}
@@ -4324,6 +4354,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
43244354 drm_dp_mst_get_port_malloc (port );
43254355 payload -> port = port ;
43264356 payload -> vc_start_slot = -1 ;
4357+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE ;
43274358 list_add (& payload -> next , & topology_state -> payloads );
43284359 }
43294360 payload -> time_slots = req_slots ;
@@ -4493,7 +4524,7 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
44934524 }
44944525
44954526 /* Now that previous state is committed, it's safe to copy over the start slot
4496- * assignments
4527+ * and allocation status assignments
44974528 */
44984529 list_for_each_entry (old_payload , & old_mst_state -> payloads , next ) {
44994530 if (old_payload -> delete )
@@ -4502,6 +4533,8 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
45024533 new_payload = drm_atomic_get_mst_payload_state (new_mst_state ,
45034534 old_payload -> port );
45044535 new_payload -> vc_start_slot = old_payload -> vc_start_slot ;
4536+ new_payload -> payload_allocation_status =
4537+ old_payload -> payload_allocation_status ;
45054538 }
45064539 }
45074540}
@@ -4818,6 +4851,13 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
48184851 struct drm_dp_mst_atomic_payload * payload ;
48194852 int i , ret ;
48204853
4854+ static const char * const status [] = {
4855+ "None" ,
4856+ "Local" ,
4857+ "DFP" ,
4858+ "Remote" ,
4859+ };
4860+
48214861 mutex_lock (& mgr -> lock );
48224862 if (mgr -> mst_primary )
48234863 drm_dp_mst_dump_mstb (m , mgr -> mst_primary );
@@ -4834,7 +4874,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
48344874 seq_printf (m , "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n" ,
48354875 state -> payload_mask , mgr -> max_payloads , state -> start_slot , state -> pbn_div );
48364876
4837- seq_printf (m , "\n| idx | port | vcpi | slots | pbn | dsc | sink name |\n" );
4877+ seq_printf (m , "\n| idx | port | vcpi | slots | pbn | dsc | status | sink name |\n" );
48384878 for (i = 0 ; i < mgr -> max_payloads ; i ++ ) {
48394879 list_for_each_entry (payload , & state -> payloads , next ) {
48404880 char name [14 ];
@@ -4843,14 +4883,15 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
48434883 continue ;
48444884
48454885 fetch_monitor_name (mgr , payload -> port , name , sizeof (name ));
4846- seq_printf (m , " %5d %6d %6d %02d - %02d %5d %5s %19s\n" ,
4886+ seq_printf (m , " %5d %6d %6d %02d - %02d %5d %5s %8s % 19s\n" ,
48474887 i ,
48484888 payload -> port -> port_num ,
48494889 payload -> vcpi ,
48504890 payload -> vc_start_slot ,
48514891 payload -> vc_start_slot + payload -> time_slots - 1 ,
48524892 payload -> pbn ,
48534893 payload -> dsc_enabled ? "Y" : "N" ,
4894+ status [payload -> payload_allocation_status ],
48544895 (* name != 0 ) ? name : "Unknown" );
48554896 }
48564897 }
0 commit comments