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…
Add table
Reference in a new issue