@@ -3255,15 +3255,15 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
3255
3255
}
3256
3256
EXPORT_SYMBOL (drm_dp_send_query_stream_enc_status );
3257
3257
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 )
3260
3260
{
3261
3261
return drm_dp_dpcd_write_payload (mgr , payload -> vcpi , payload -> vc_start_slot ,
3262
3262
payload -> time_slots );
3263
3263
}
3264
3264
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 )
3267
3267
{
3268
3268
int ret ;
3269
3269
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,
3276
3276
return ret ;
3277
3277
}
3278
3278
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 )
3282
3282
{
3283
3283
drm_dbg_kms (mgr -> dev , "\n" );
3284
3284
3285
3285
/* 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
+ }
3288
3290
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 );
3290
3293
}
3291
3294
3292
3295
/**
@@ -3296,81 +3299,105 @@ static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
3296
3299
* @payload: The payload to write
3297
3300
*
3298
3301
* 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.
3300
3303
*
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.
3303
3305
*/
3304
3306
int drm_dp_add_payload_part1 (struct drm_dp_mst_topology_mgr * mgr ,
3305
3307
struct drm_dp_mst_topology_state * mst_state ,
3306
3308
struct drm_dp_mst_atomic_payload * payload )
3307
3309
{
3308
3310
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 ;
3310
3322
3323
+ /* Allocate payload to immediate downstream facing port */
3311
3324
port = drm_dp_mst_topology_get_port_validated (mgr , payload -> port );
3312
3325
if (!port ) {
3313
3326
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" ,
3315
3328
payload -> vcpi , payload -> port );
3316
- payload -> vc_start_slot = -1 ;
3317
- return 0 ;
3329
+ allocate = false;
3318
3330
}
3319
3331
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 );
3324
3337
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 ;
3332
3338
}
3333
3339
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 ;
3336
3343
3337
- return 0 ;
3344
+ drm_dp_mst_topology_put_port (port );
3345
+
3346
+ return ret ;
3338
3347
}
3339
3348
EXPORT_SYMBOL (drm_dp_add_payload_part1 );
3340
3349
3341
3350
/**
3342
- * drm_dp_remove_payload () - Remove an MST payload
3351
+ * drm_dp_remove_payload_part1 () - Remove an MST payload along the virtual channel
3343
3352
* @mgr: Manager to use.
3344
3353
* @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
3347
3355
*
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 .
3351
3359
*/
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 )
3356
3363
{
3357
- struct drm_dp_mst_atomic_payload * pos ;
3364
+ /* Remove remote payload allocation */
3358
3365
bool send_remove = false;
3359
3366
3360
- /* We failed to make the payload, so nothing to do */
3361
- if (new_payload -> vc_start_slot == -1 )
3362
- return ;
3363
-
3364
3367
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 );
3366
3369
mutex_unlock (& mgr -> lock );
3367
3370
3368
3371
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 );
3370
3373
else
3371
3374
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 );
3373
3380
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 */
3374
3401
list_for_each_entry (pos , & mst_state -> payloads , next ) {
3375
3402
if (pos != new_payload && pos -> vc_start_slot > new_payload -> vc_start_slot )
3376
3403
pos -> vc_start_slot -= old_payload -> time_slots ;
@@ -3382,9 +3409,10 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
3382
3409
3383
3410
if (new_payload -> delete )
3384
3411
drm_dp_mst_put_port_malloc (new_payload -> port );
3385
- }
3386
- EXPORT_SYMBOL (drm_dp_remove_payload );
3387
3412
3413
+ new_payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE ;
3414
+ }
3415
+ EXPORT_SYMBOL (drm_dp_remove_payload_part2 );
3388
3416
/**
3389
3417
* drm_dp_add_payload_part2() - Execute payload update part 2
3390
3418
* @mgr: Manager to use.
@@ -3403,17 +3431,19 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
3403
3431
int ret = 0 ;
3404
3432
3405
3433
/* 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" ,
3408
3436
payload -> port -> connector -> name );
3409
3437
return - EIO ;
3410
3438
}
3411
3439
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 )
3414
3443
drm_err (mgr -> dev , "Step 2 of creating MST payload for %p failed: %d\n" ,
3415
3444
payload -> port , ret );
3416
- }
3445
+ else
3446
+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE ;
3417
3447
3418
3448
return ret ;
3419
3449
}
@@ -4324,6 +4354,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
4324
4354
drm_dp_mst_get_port_malloc (port );
4325
4355
payload -> port = port ;
4326
4356
payload -> vc_start_slot = -1 ;
4357
+ payload -> payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE ;
4327
4358
list_add (& payload -> next , & topology_state -> payloads );
4328
4359
}
4329
4360
payload -> time_slots = req_slots ;
@@ -4493,7 +4524,7 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
4493
4524
}
4494
4525
4495
4526
/* Now that previous state is committed, it's safe to copy over the start slot
4496
- * assignments
4527
+ * and allocation status assignments
4497
4528
*/
4498
4529
list_for_each_entry (old_payload , & old_mst_state -> payloads , next ) {
4499
4530
if (old_payload -> delete )
@@ -4502,6 +4533,8 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state)
4502
4533
new_payload = drm_atomic_get_mst_payload_state (new_mst_state ,
4503
4534
old_payload -> port );
4504
4535
new_payload -> vc_start_slot = old_payload -> vc_start_slot ;
4536
+ new_payload -> payload_allocation_status =
4537
+ old_payload -> payload_allocation_status ;
4505
4538
}
4506
4539
}
4507
4540
}
@@ -4818,6 +4851,13 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
4818
4851
struct drm_dp_mst_atomic_payload * payload ;
4819
4852
int i , ret ;
4820
4853
4854
+ static const char * const status [] = {
4855
+ "None" ,
4856
+ "Local" ,
4857
+ "DFP" ,
4858
+ "Remote" ,
4859
+ };
4860
+
4821
4861
mutex_lock (& mgr -> lock );
4822
4862
if (mgr -> mst_primary )
4823
4863
drm_dp_mst_dump_mstb (m , mgr -> mst_primary );
@@ -4834,7 +4874,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
4834
4874
seq_printf (m , "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n" ,
4835
4875
state -> payload_mask , mgr -> max_payloads , state -> start_slot , state -> pbn_div );
4836
4876
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" );
4838
4878
for (i = 0 ; i < mgr -> max_payloads ; i ++ ) {
4839
4879
list_for_each_entry (payload , & state -> payloads , next ) {
4840
4880
char name [14 ];
@@ -4843,14 +4883,15 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
4843
4883
continue ;
4844
4884
4845
4885
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" ,
4847
4887
i ,
4848
4888
payload -> port -> port_num ,
4849
4889
payload -> vcpi ,
4850
4890
payload -> vc_start_slot ,
4851
4891
payload -> vc_start_slot + payload -> time_slots - 1 ,
4852
4892
payload -> pbn ,
4853
4893
payload -> dsc_enabled ? "Y" : "N" ,
4894
+ status [payload -> payload_allocation_status ],
4854
4895
(* name != 0 ) ? name : "Unknown" );
4855
4896
}
4856
4897
}
0 commit comments