@@ -5180,11 +5180,13 @@ EXPORT_SYMBOL(drm_dp_mst_port_downstream_of_parent);
51805180
51815181static int
51825182drm_dp_mst_atomic_check_port_bw_limit (struct drm_dp_mst_port * port ,
5183- struct drm_dp_mst_topology_state * state );
5183+ struct drm_dp_mst_topology_state * state ,
5184+ struct drm_dp_mst_port * * failing_port );
51845185
51855186static int
51865187drm_dp_mst_atomic_check_mstb_bw_limit (struct drm_dp_mst_branch * mstb ,
5187- struct drm_dp_mst_topology_state * state )
5188+ struct drm_dp_mst_topology_state * state ,
5189+ struct drm_dp_mst_port * * failing_port )
51885190{
51895191 struct drm_dp_mst_atomic_payload * payload ;
51905192 struct drm_dp_mst_port * port ;
@@ -5213,7 +5215,7 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
52135215 drm_dbg_atomic (mstb -> mgr -> dev , "[MSTB:%p] Checking bandwidth limits\n" , mstb );
52145216
52155217 list_for_each_entry (port , & mstb -> ports , next ) {
5216- ret = drm_dp_mst_atomic_check_port_bw_limit (port , state );
5218+ ret = drm_dp_mst_atomic_check_port_bw_limit (port , state , failing_port );
52175219 if (ret < 0 )
52185220 return ret ;
52195221
@@ -5225,7 +5227,8 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
52255227
52265228static int
52275229drm_dp_mst_atomic_check_port_bw_limit (struct drm_dp_mst_port * port ,
5228- struct drm_dp_mst_topology_state * state )
5230+ struct drm_dp_mst_topology_state * state ,
5231+ struct drm_dp_mst_port * * failing_port )
52295232{
52305233 struct drm_dp_mst_atomic_payload * payload ;
52315234 int pbn_used = 0 ;
@@ -5246,13 +5249,15 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
52465249 drm_dbg_atomic (port -> mgr -> dev ,
52475250 "[MSTB:%p] [MST PORT:%p] no BW available for the port\n" ,
52485251 port -> parent , port );
5252+ * failing_port = port ;
52495253 return - EINVAL ;
52505254 }
52515255
52525256 pbn_used = payload -> pbn ;
52535257 } else {
52545258 pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit (port -> mstb ,
5255- state );
5259+ state ,
5260+ failing_port );
52565261 if (pbn_used <= 0 )
52575262 return pbn_used ;
52585263 }
@@ -5261,6 +5266,7 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
52615266 drm_dbg_atomic (port -> mgr -> dev ,
52625267 "[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n" ,
52635268 port -> parent , port , pbn_used , port -> full_pbn );
5269+ * failing_port = port ;
52645270 return - ENOSPC ;
52655271 }
52665272
@@ -5438,20 +5444,79 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
54385444}
54395445EXPORT_SYMBOL (drm_dp_mst_atomic_enable_dsc );
54405446
5447+ /**
5448+ * drm_dp_mst_atomic_check_mgr - Check the atomic state of an MST topology manager
5449+ * @state: The global atomic state
5450+ * @mgr: Manager to check
5451+ * @mst_state: The MST atomic state for @mgr
5452+ * @failing_port: Returns the port with a BW limitation
5453+ *
5454+ * Checks the given MST manager's topology state for an atomic update to ensure
5455+ * that it's valid. This includes checking whether there's enough bandwidth to
5456+ * support the new timeslot allocations in the atomic update.
5457+ *
5458+ * Any atomic drivers supporting DP MST must make sure to call this or
5459+ * the drm_dp_mst_atomic_check() function after checking the rest of their state
5460+ * in their &drm_mode_config_funcs.atomic_check() callback.
5461+ *
5462+ * See also:
5463+ * drm_dp_mst_atomic_check()
5464+ * drm_dp_atomic_find_time_slots()
5465+ * drm_dp_atomic_release_time_slots()
5466+ *
5467+ * Returns:
5468+ * - 0 if the new state is valid
5469+ * - %-ENOSPC, if the new state is invalid, because of BW limitation
5470+ * @failing_port is set to:
5471+ * - The non-root port where a BW limit check failed
5472+ * The returned port pointer is valid until at least
5473+ * one payload downstream of it exists.
5474+ * - %NULL if the BW limit check failed at the root port
5475+ * - %-EINVAL, if the new state is invalid, because the root port has
5476+ * too many payloads.
5477+ */
5478+ int drm_dp_mst_atomic_check_mgr (struct drm_atomic_state * state ,
5479+ struct drm_dp_mst_topology_mgr * mgr ,
5480+ struct drm_dp_mst_topology_state * mst_state ,
5481+ struct drm_dp_mst_port * * failing_port )
5482+ {
5483+ int ret ;
5484+
5485+ * failing_port = NULL ;
5486+
5487+ if (!mgr -> mst_state )
5488+ return 0 ;
5489+
5490+ ret = drm_dp_mst_atomic_check_payload_alloc_limits (mgr , mst_state );
5491+ if (ret )
5492+ return ret ;
5493+
5494+ mutex_lock (& mgr -> lock );
5495+ ret = drm_dp_mst_atomic_check_mstb_bw_limit (mgr -> mst_primary ,
5496+ mst_state ,
5497+ failing_port );
5498+ mutex_unlock (& mgr -> lock );
5499+
5500+ return ret < 0 ? ret : 0 ;
5501+ }
5502+ EXPORT_SYMBOL (drm_dp_mst_atomic_check_mgr );
5503+
54415504/**
54425505 * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
54435506 * atomic update is valid
54445507 * @state: Pointer to the new &struct drm_dp_mst_topology_state
54455508 *
54465509 * Checks the given topology state for an atomic update to ensure that it's
5447- * valid. This includes checking whether there's enough bandwidth to support
5448- * the new timeslot allocations in the atomic update.
5510+ * valid, calling drm_dp_mst_atomic_check_mgr() for all MST manager in the
5511+ * atomic state. This includes checking whether there's enough bandwidth to
5512+ * support the new timeslot allocations in the atomic update.
54495513 *
54505514 * Any atomic drivers supporting DP MST must make sure to call this after
54515515 * checking the rest of their state in their
54525516 * &drm_mode_config_funcs.atomic_check() callback.
54535517 *
54545518 * See also:
5519+ * drm_dp_mst_atomic_check_mgr()
54555520 * drm_dp_atomic_find_time_slots()
54565521 * drm_dp_atomic_release_time_slots()
54575522 *
@@ -5466,21 +5531,11 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
54665531 int i , ret = 0 ;
54675532
54685533 for_each_new_mst_mgr_in_state (state , mgr , mst_state , i ) {
5469- if (!mgr -> mst_state )
5470- continue ;
5534+ struct drm_dp_mst_port * tmp_port ;
54715535
5472- ret = drm_dp_mst_atomic_check_payload_alloc_limits ( mgr , mst_state );
5536+ ret = drm_dp_mst_atomic_check_mgr ( state , mgr , mst_state , & tmp_port );
54735537 if (ret )
54745538 break ;
5475-
5476- mutex_lock (& mgr -> lock );
5477- ret = drm_dp_mst_atomic_check_mstb_bw_limit (mgr -> mst_primary ,
5478- mst_state );
5479- mutex_unlock (& mgr -> lock );
5480- if (ret < 0 )
5481- break ;
5482- else
5483- ret = 0 ;
54845539 }
54855540
54865541 return ret ;
0 commit comments