mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
Factor out a helper to check the atomic state for one MST topology manager, returning the MST port where the BW limit check has failed. This will be used in a follow-up patch by the i915 driver to improve the BW sharing between MST streams. Cc: Lyude Paul <lyude@redhat.com> Cc: dri-devel@lists.freedesktop.org Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Maxime Ripard <mripard@kernel.org> Signed-off-by: Imre Deak <imre.deak@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-5-imre.deak@intel.com
This commit is contained in:
		
							parent
							
								
									9dcf67deea
								
							
						
					
					
						commit
						1cd0a5ea42
					
				
					 2 changed files with 78 additions and 19 deletions
				
			
		| 
						 | 
					@ -5180,11 +5180,13 @@ EXPORT_SYMBOL(drm_dp_mst_port_downstream_of_parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
					drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
				
			||||||
				      struct drm_dp_mst_topology_state *state);
 | 
									      struct drm_dp_mst_topology_state *state,
 | 
				
			||||||
 | 
									      struct drm_dp_mst_port **failing_port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 | 
					drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 | 
				
			||||||
				      struct drm_dp_mst_topology_state *state)
 | 
									      struct drm_dp_mst_topology_state *state,
 | 
				
			||||||
 | 
									      struct drm_dp_mst_port **failing_port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_dp_mst_atomic_payload *payload;
 | 
						struct drm_dp_mst_atomic_payload *payload;
 | 
				
			||||||
	struct drm_dp_mst_port *port;
 | 
						struct drm_dp_mst_port *port;
 | 
				
			||||||
| 
						 | 
					@ -5213,7 +5215,7 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 | 
				
			||||||
		drm_dbg_atomic(mstb->mgr->dev, "[MSTB:%p] Checking bandwidth limits\n", mstb);
 | 
							drm_dbg_atomic(mstb->mgr->dev, "[MSTB:%p] Checking bandwidth limits\n", mstb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(port, &mstb->ports, next) {
 | 
						list_for_each_entry(port, &mstb->ports, next) {
 | 
				
			||||||
		ret = drm_dp_mst_atomic_check_port_bw_limit(port, state);
 | 
							ret = drm_dp_mst_atomic_check_port_bw_limit(port, state, failing_port);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret < 0)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5225,7 +5227,8 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
					drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
				
			||||||
				      struct drm_dp_mst_topology_state *state)
 | 
									      struct drm_dp_mst_topology_state *state,
 | 
				
			||||||
 | 
									      struct drm_dp_mst_port **failing_port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_dp_mst_atomic_payload *payload;
 | 
						struct drm_dp_mst_atomic_payload *payload;
 | 
				
			||||||
	int pbn_used = 0;
 | 
						int pbn_used = 0;
 | 
				
			||||||
| 
						 | 
					@ -5246,13 +5249,15 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
				
			||||||
			drm_dbg_atomic(port->mgr->dev,
 | 
								drm_dbg_atomic(port->mgr->dev,
 | 
				
			||||||
				       "[MSTB:%p] [MST PORT:%p] no BW available for the port\n",
 | 
									       "[MSTB:%p] [MST PORT:%p] no BW available for the port\n",
 | 
				
			||||||
				       port->parent, port);
 | 
									       port->parent, port);
 | 
				
			||||||
 | 
								*failing_port = port;
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pbn_used = payload->pbn;
 | 
							pbn_used = payload->pbn;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
 | 
							pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
 | 
				
			||||||
								 state);
 | 
													 state,
 | 
				
			||||||
 | 
													 failing_port);
 | 
				
			||||||
		if (pbn_used <= 0)
 | 
							if (pbn_used <= 0)
 | 
				
			||||||
			return pbn_used;
 | 
								return pbn_used;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -5261,6 +5266,7 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 | 
				
			||||||
		drm_dbg_atomic(port->mgr->dev,
 | 
							drm_dbg_atomic(port->mgr->dev,
 | 
				
			||||||
			       "[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n",
 | 
								       "[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n",
 | 
				
			||||||
			       port->parent, port, pbn_used, port->full_pbn);
 | 
								       port->parent, port, pbn_used, port->full_pbn);
 | 
				
			||||||
 | 
							*failing_port = port;
 | 
				
			||||||
		return -ENOSPC;
 | 
							return -ENOSPC;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5438,20 +5444,79 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
 | 
					EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * drm_dp_mst_atomic_check_mgr - Check the atomic state of an MST topology manager
 | 
				
			||||||
 | 
					 * @state: The global atomic state
 | 
				
			||||||
 | 
					 * @mgr: Manager to check
 | 
				
			||||||
 | 
					 * @mst_state: The MST atomic state for @mgr
 | 
				
			||||||
 | 
					 * @failing_port: Returns the port with a BW limitation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Checks the given MST manager's topology state for an atomic update to ensure
 | 
				
			||||||
 | 
					 * that it's valid. This includes checking whether there's enough bandwidth to
 | 
				
			||||||
 | 
					 * support the new timeslot allocations in the atomic update.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Any atomic drivers supporting DP MST must make sure to call this or
 | 
				
			||||||
 | 
					 * the drm_dp_mst_atomic_check() function after checking the rest of their state
 | 
				
			||||||
 | 
					 * in their &drm_mode_config_funcs.atomic_check() callback.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See also:
 | 
				
			||||||
 | 
					 * drm_dp_mst_atomic_check()
 | 
				
			||||||
 | 
					 * drm_dp_atomic_find_time_slots()
 | 
				
			||||||
 | 
					 * drm_dp_atomic_release_time_slots()
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns:
 | 
				
			||||||
 | 
					 *   - 0 if the new state is valid
 | 
				
			||||||
 | 
					 *   - %-ENOSPC, if the new state is invalid, because of BW limitation
 | 
				
			||||||
 | 
					 *         @failing_port is set to:
 | 
				
			||||||
 | 
					 *         - The non-root port where a BW limit check failed
 | 
				
			||||||
 | 
					 *           The returned port pointer is valid until at least
 | 
				
			||||||
 | 
					 *           one payload downstream of it exists.
 | 
				
			||||||
 | 
					 *         - %NULL if the BW limit check failed at the root port
 | 
				
			||||||
 | 
					 *   - %-EINVAL, if the new state is invalid, because the root port has
 | 
				
			||||||
 | 
					 *     too many payloads.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
 | 
				
			||||||
 | 
									struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
 | 
									struct drm_dp_mst_topology_state *mst_state,
 | 
				
			||||||
 | 
									struct drm_dp_mst_port **failing_port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*failing_port = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mgr->mst_state)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&mgr->lock);
 | 
				
			||||||
 | 
						ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
 | 
				
			||||||
 | 
											    mst_state,
 | 
				
			||||||
 | 
											    failing_port);
 | 
				
			||||||
 | 
						mutex_unlock(&mgr->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret < 0 ? ret : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(drm_dp_mst_atomic_check_mgr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
 | 
					 * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
 | 
				
			||||||
 * atomic update is valid
 | 
					 * atomic update is valid
 | 
				
			||||||
 * @state: Pointer to the new &struct drm_dp_mst_topology_state
 | 
					 * @state: Pointer to the new &struct drm_dp_mst_topology_state
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Checks the given topology state for an atomic update to ensure that it's
 | 
					 * 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
 | 
					 * valid, calling drm_dp_mst_atomic_check_mgr() for all MST manager in the
 | 
				
			||||||
 * the new timeslot allocations in the atomic update.
 | 
					 * atomic state. This includes checking whether there's enough bandwidth to
 | 
				
			||||||
 | 
					 * support the new timeslot allocations in the atomic update.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Any atomic drivers supporting DP MST must make sure to call this after
 | 
					 * Any atomic drivers supporting DP MST must make sure to call this after
 | 
				
			||||||
 * checking the rest of their state in their
 | 
					 * checking the rest of their state in their
 | 
				
			||||||
 * &drm_mode_config_funcs.atomic_check() callback.
 | 
					 * &drm_mode_config_funcs.atomic_check() callback.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * See also:
 | 
					 * See also:
 | 
				
			||||||
 | 
					 * drm_dp_mst_atomic_check_mgr()
 | 
				
			||||||
 * drm_dp_atomic_find_time_slots()
 | 
					 * drm_dp_atomic_find_time_slots()
 | 
				
			||||||
 * drm_dp_atomic_release_time_slots()
 | 
					 * drm_dp_atomic_release_time_slots()
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -5466,21 +5531,11 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
 | 
				
			||||||
	int i, ret = 0;
 | 
						int i, ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
 | 
						for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
 | 
				
			||||||
		if (!mgr->mst_state)
 | 
							struct drm_dp_mst_port *tmp_port;
 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
 | 
							ret = drm_dp_mst_atomic_check_mgr(state, mgr, mst_state, &tmp_port);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		mutex_lock(&mgr->lock);
 | 
					 | 
				
			||||||
		ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
 | 
					 | 
				
			||||||
							    mst_state);
 | 
					 | 
				
			||||||
		mutex_unlock(&mgr->lock);
 | 
					 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			ret = 0;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -916,6 +916,10 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
 | 
					int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
		struct drm_dp_mst_port *port,
 | 
							struct drm_dp_mst_port *port,
 | 
				
			||||||
		struct drm_dp_query_stream_enc_status_ack_reply *status);
 | 
							struct drm_dp_query_stream_enc_status_ack_reply *status);
 | 
				
			||||||
 | 
					int __must_check drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
 | 
				
			||||||
 | 
										     struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
 | 
										     struct drm_dp_mst_topology_state *mst_state,
 | 
				
			||||||
 | 
										     struct drm_dp_mst_port **failing_port);
 | 
				
			||||||
int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
 | 
					int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
 | 
				
			||||||
int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state,
 | 
					int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state,
 | 
				
			||||||
						   struct drm_dp_mst_topology_mgr *mgr);
 | 
											   struct drm_dp_mst_topology_mgr *mgr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue