drm/i915: Implement proper fallback training for MST
Subsystems (6)
Lyude Paul
maintainerv8 cover drm/i915: Implement proper fallback training for MST
Next version of https://patchwork.freedesktop.org/series/41576/
Only changes are removing duplicate SoBs that git send-email annoyingly added. Sorry about that :(
Lyude Paul (10):
drm/atomic: Print debug message on atomic check failure drm/i915: Move DP modeset retry work into intel_dp drm/dp_mst: Fix naming on drm_atomic_get_mst_topology_state() drm/dp_mst: Remove all evil duplicate state pointers drm/dp_mst: Make drm_dp_mst_topology_state subclassable drm/dp_mst: Add reset_state callback to topology mgr drm/i915: Only use one link bw config for MST topologies drm/i915: Make intel_dp_mst_atomic_check() idempotent drm/dp_mst: Add MST fallback retraining helpers drm/i915: Implement proper fallback training for MST
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 46 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 4 +- drivers/gpu/drm/drm_atomic.c | 5 +- drivers/gpu/drm/drm_dp_mst_topology.c | 550 ++++++++++++++++++++- drivers/gpu/drm/i915/intel_ddi.c | 10 +- drivers/gpu/drm/i915/intel_display.c | 14 +- drivers/gpu/drm/i915/intel_dp.c | 376 ++++++++++---- drivers/gpu/drm/i915/intel_dp_link_training.c | 6 +- drivers/gpu/drm/i915/intel_dp_mst.c | 186 +++++-- drivers/gpu/drm/i915/intel_drv.h | 20 +- drivers/gpu/drm/nouveau/nv50_display.c | 17 +- drivers/gpu/drm/radeon/radeon_dp_mst.c | 13 +- include/drm/drm_dp_mst_helper.h | 43 +- 14 files changed, 1120 insertions(+), 184 deletions(-)
Signature · 6 lines
2.14.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Lyude Paul
maintainerPATCH v8 1/10 drm/atomic: Print debug message on atomic check failure
Does what it says on the label, it's a little confusing debugging atomic check failures otherwise.
--- drivers/gpu/drm/drm_atomic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_atomic.c +4 -1
@@ -1705,8 +1705,11 @@ int drm_atomic_check_only(struct drm_atomic_state *state)if (config->funcs->atomic_check) ret = config->funcs->atomic_check (state->dev, state); -if (ret) +if (ret) { +DRM_DEBUG_ATOMIC ("atomic driver check for %p failed: %d\n" , + state, ret);return ret; + }if (!state->allow_modeset) {for_each_new_crtc_in_state (state, crtc, crtc_state, i) {
Signature · 6 lines
2.14.3 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v8 01/10] drm/atomic: Print debug message on atomic check failure
Quoted 15 lines · Lyude Paul
Does what it says on the label, it's a little confusing debugging atomic check failures otherwise.
Cc Manasi Navare <[email protected]>Cc Ville Syrjälä <[email protected]>Signed-off-by Lyude Paul <[email protected]>--- drivers/gpu/drm/drm_atomic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)drivers/gpu/drm/drm_atomic.c +0
-0
drivers/gpu/drm/drm_atomic.c int drm_atomic_check_only(struct drm_atomic_state *state) · line 1713
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +4
-1@@ -1705,8 +1705,11 @@ int drm_atomic_check_only(struct drm_atomic_state *state)if (config->funcs->atomic_check) ret = config->funcs->atomic_check (state->dev, state); -if (ret) +if (ret) { +DRM_DEBUG_ATOMIC ("atomic driver check for %p failed: %d\n" , + state, ret);return ret; + }
nit: Would have slightly looked better if the 'ret' check was moved inside the branch for funcs->atomic_check.
Quoted 2 lines
drivers/gpu/drm/drm_atomic.c +0
-0if (!state->allow_modeset) {for_each_new_crtc_in_state (state, crtc, crtc_state, i) {
Lyude Paul
maintainerPATCH v8 2/10 drm/i915: Move DP modeset retry work into intel_dp
In reply to Lyude PaulWhile having the modeset_retry_work in intel_connector makes sense with SST, this paradigm doesn't make a whole ton of sense when it comes to MST since we have to deal with multiple connectors. In most cases, it's more useful to just use the intel_dp struct since it indicates whether or not we're dealing with an MST device, along with being able to easily trace the intel_dp struct back to it's respective connector (if there is any). So, move the modeset_retry_work function out of the intel_connector struct and into intel_dp.
V2:
- Remove accidental duplicate modeset_retry_work in intel_connector
V3:
- Also check against eDP in intel_hpd_poll_fini() - mdnavare
V4:
- Don't bother looping over connectors for canceling modeset rety work, just encoders.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/i915/intel_display.c | 14 +++++++++++--- drivers/gpu/drm/i915/intel_dp.c | 10 ++++------ drivers/gpu/drm/i915/intel_dp_link_training.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 6 +++--- 4 files changed, 19 insertions(+), 13 deletions(-)
drivers/gpu/drm/i915/intel_display.c +11 -3
@@ -15471,20 +15471,28 @@ void intel_connector_unregister(struct drm_connector *connector)static void intel_hpd_poll_fini (struct drm_device *dev) { -struct intel_connector *connector;struct drm_connector_list_iter conn_iter; +struct intel_connector *connector; +struct intel_encoder *encoder; +struct intel_dp *intel_dp;/* Kill all the work that may have been queued by hpd. */ drm_connector_list_iter_begin (dev, &conn_iter);for_each_intel_connector_iter (connector, &conn_iter) { -if (connector->modeset_retry_work.func) -cancel_work_sync (&connector->modeset_retry_work);if (connector->hdcp_shim) {cancel_delayed_work_sync (&connector->hdcp_check_work);cancel_work_sync (&connector->hdcp_prop_work); } }drm_connector_list_iter_end (&conn_iter); + +for_each_intel_encoder (dev, encoder) { +if (encoder->type ==INTEL_OUTPUT_DP || + encoder->type ==INTEL_OUTPUT_EDP ) { + intel_dp =enc_to_intel_dp (&encoder->base); +cancel_work_sync (&intel_dp->modeset_retry_work); + } + } }void intel_modeset_cleanup (struct drm_device *dev)
drivers/gpu/drm/i915/intel_dp.c +4 -6
@@ -6249,12 +6249,10 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,static void intel_dp_modeset_retry_work_fn (struct work_struct *work) { -struct intel_connector *intel_connector; -struct drm_connector *connector; +struct intel_dp *intel_dp =container_of (work,typeof (*intel_dp), + modeset_retry_work); +struct drm_connector *connector = &intel_dp->attached_connector->base; - intel_connector =container_of (work,typeof (*intel_connector), - modeset_retry_work); - connector = &intel_connector->base;DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id, connector->name);
@@ -6283,7 +6281,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,int type;/* Initialize the work for modeset in case of link train failure */ -INIT_WORK (&intel_connector->modeset_retry_work, +INIT_WORK (&intel_dp->modeset_retry_work, intel_dp_modeset_retry_work_fn); if (WARN(intel_dig_port->max_lanes < 1,
drivers/gpu/drm/i915/intel_dp_link_training.c +1 -1
@@ -340,7 +340,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) intel_dp->link_rate, intel_dp->lane_count))/* Schedule a Hotplug Uevent to userspace to start modeset */ -schedule_work (&intel_connector->modeset_retry_work); +schedule_work (&intel_dp->modeset_retry_work); }else { DRM_ERROR("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", intel_connector->base.base.id,
drivers/gpu/drm/i915/intel_drv.h +3 -3
@@ -406,9 +406,6 @@ struct intel_connector {struct intel_dp *mst_port; -/* Work struct to schedule a uevent on link train failure */ -struct work_struct modeset_retry_work; -const struct intel_hdcp_shim *hdcp_shim;struct mutex hdcp_mutex;uint64_t hdcp_value;/* protected by hdcp_mutex */
@@ -1143,6 +1140,9 @@ struct intel_dp {/* Displayport compliance testing */ struct intel_dp_compliance compliance; + +/* Work struct to schedule a uevent on link train failure */ +struct work_struct modeset_retry_work; };struct intel_lspcon {
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Lyude Paul
maintainerPATCH v8 3/10 drm/dp_mst: Fix naming on drm_atomic_get_mst_topology_state()
In reply to Lyude PaulSince these functions are dealing with an atomic state that needs to be modified during atomic check and commit, change the naming on this function to drm_atomic_dp_mst_get_topology_state() since we're the only one using the function, and it's more consistent with the naming scheme used in drm_atomic.c/drm_atomic_helper.c.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/drm_dp_mst_topology.c | 13 +++++++------ include/drm/drm_dp_mst_helper.h | 6 ++++-- 2 files changed, 11 insertions(+), 8 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +7 -6
@@ -2622,7 +2622,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,struct drm_dp_mst_topology_state *topology_state;int req_slots; - topology_state =drm_atomic_get_mst_topology_state (state, mgr); + topology_state =drm_atomic_dp_mst_get_topology_state (state, mgr);if (IS_ERR (topology_state))return PTR_ERR (topology_state);
@@ -2662,7 +2662,7 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, {struct drm_dp_mst_topology_state *topology_state; - topology_state =drm_atomic_get_mst_topology_state (state, mgr); + topology_state =drm_atomic_dp_mst_get_topology_state (state, mgr);if (IS_ERR (topology_state))return PTR_ERR (topology_state);
@@ -3129,7 +3129,7 @@ static const struct drm_private_state_funcs mst_state_funcs = { };/** -* drm_atomic_get_mst_topology_state: get MST topology state +* drm_atomic_dp_mst_get_topology_state: get MST topology state * * @state: global atomic state * @mgr: MST topology manager, also the private object in this case
@@ -3143,15 +3143,16 @@ static const struct drm_private_state_funcs mst_state_funcs = {* * The MST topology state or error pointer. */ -struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state (struct drm_atomic_state *state, -struct drm_dp_mst_topology_mgr *mgr) +struct drm_dp_mst_topology_state * +drm_atomic_dp_mst_get_topology_state (struct drm_atomic_state *state, +struct drm_dp_mst_topology_mgr *mgr) {struct drm_device *dev = mgr->dev;WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));return to_dp_mst_topology_state (drm_atomic_get_private_obj_state (state, &mgr->base)); } -EXPORT_SYMBOL (drm_atomic_get_mst_topology_state); +EXPORT_SYMBOL (drm_atomic_dp_mst_get_topology_state);/** * drm_dp_mst_topology_mgr_init - initialise a topology manager
include/drm/drm_dp_mst_helper.h +4 -2
@@ -623,8 +623,10 @@ void drm_dp_mst_dump_topology(struct seq_file *m,void drm_dp_mst_topology_mgr_suspend (struct drm_dp_mst_topology_mgr *mgr);int drm_dp_mst_topology_mgr_resume (struct drm_dp_mst_topology_mgr *mgr); -struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state (struct drm_atomic_state *state, -struct drm_dp_mst_topology_mgr *mgr); + +struct drm_dp_mst_topology_state * +drm_atomic_dp_mst_get_topology_state (struct drm_atomic_state *state, +struct drm_dp_mst_topology_mgr *mgr);int drm_dp_atomic_find_vcpi_slots (struct drm_atomic_state *state,struct drm_dp_mst_topology_mgr *mgr,struct drm_dp_mst_port *port,int pbn);
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Lyude Paul
maintainerPATCH v8 4/10 drm/dp_mst: Remove all evil duplicate state pointers
In reply to Lyude PaulThere's no reason to track the atomic state three times. Unfortunately, this is currently what we're doing, and even worse is that there is only one actually correct state pointer: the one in mst_state->base.state. mgr->state never seems to be used, along with the one in mst_state->state.
This confused me for over 4 hours until I realized there was no magic behind these pointers. So, let's save everyone else from the trouble.
--- include/drm/drm_dp_mst_helper.h | 6 ------ 1 file changed, 6 deletions(-)
include/drm/drm_dp_mst_helper.h +0 -6
@@ -409,7 +409,6 @@ struct drm_dp_payload {struct drm_dp_mst_topology_state {struct drm_private_state base;int avail_slots; -struct drm_atomic_state *state;struct drm_dp_mst_topology_mgr *mgr; };
@@ -497,11 +496,6 @@ struct drm_dp_mst_topology_mgr {*/ int pbn_div; -/** -* @state: State information for topology manager -*/ -struct drm_dp_mst_topology_state *state; -/** * @funcs: Atomic helper callbacks */
Signature · 6 lines
2.14.3 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Lyude Paul
maintainerPATCH v8 5/10 drm/dp_mst: Make drm_dp_mst_topology_state subclassable
In reply to Lyude PaulThis is useful for drivers (which will probably be all of them soon) which need to track state that is exclusive to the topology, and not a specific connector on said topology. This includes things such as the link rate and lane count that are shared by all of the connectors on the topology.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 46 ++++++++--- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 4 +- drivers/gpu/drm/drm_dp_mst_topology.c | 95 +++++++++++++++++----- drivers/gpu/drm/i915/intel_dp_mst.c | 13 ++- drivers/gpu/drm/nouveau/nv50_display.c | 17 +++- drivers/gpu/drm/radeon/radeon_dp_mst.c | 13 ++- include/drm/drm_dp_mst_helper.h | 8 ++ 8 files changed, 173 insertions(+), 37 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +11 -3
@@ -3626,9 +3626,17 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,drm_connector_register (&aconnector->base); -if (connector_type == DRM_MODE_CONNECTOR_DisplayPort - || connector_type == DRM_MODE_CONNECTOR_eDP) -amdgpu_dm_initialize_dp_connector (dm, aconnector); +if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector_type == DRM_MODE_CONNECTOR_eDP) { + res =amdgpu_dm_initialize_dp_connector (dm, aconnector); +if (res) { +drm_connector_unregister (&aconnector->base); +drm_connector_cleanup (&aconnector->base); + aconnector->connector_id =-1 ; + + goto out_free; + } + }#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE ) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE )
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +36 -10
58 lines not on this page · raw message
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +2 -2
@@ -29,8 +29,8 @@struct amdgpu_display_manager ;struct amdgpu_dm_connector ; -void amdgpu_dm_initialize_dp_connector (struct amdgpu_display_manager *dm, -struct amdgpu_dm_connector *aconnector); +int amdgpu_dm_initialize_dp_connector (struct amdgpu_display_manager *dm, +struct amdgpu_dm_connector *aconnector);void dm_dp_mst_dc_sink_create (struct drm_connector *connector);#endif
drivers/gpu/drm/drm_dp_mst_topology.c +76 -19
148 lines not on this page · raw message
drivers/gpu/drm/i915/intel_dp_mst.c +12 -1
@@ -587,19 +587,30 @@ intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port)return true; } +static const struct drm_private_state_funcs mst_state_funcs = { + .atomic_destroy_state = drm_atomic_dp_mst_destroy_topology_state, + .atomic_duplicate_state = drm_atomic_dp_mst_duplicate_topology_state, +}; +int intel_dp_mst_encoder_init (struct intel_digital_port *intel_dig_port,int conn_base_id) {struct intel_dp *intel_dp = &intel_dig_port->dp; +struct drm_dp_mst_topology_state *mst_state;struct drm_device *dev = intel_dig_port->base.base.dev;int ret; + mst_state =kzalloc (sizeof (*mst_state),GFP_KERNEL ); +if (!mst_state) +return -ENOMEM ; + intel_dp->can_mst = true; intel_dp->mst_mgr.cbs = &mst_cbs; + intel_dp->mst_mgr.funcs = &mst_state_funcs;/* create encoders */ intel_dp_create_fake_mst_encoders (intel_dig_port); - ret =drm_dp_mst_topology_mgr_init (&intel_dp->mst_mgr, dev, + ret =drm_dp_mst_topology_mgr_init (&intel_dp->mst_mgr, mst_state, dev, &intel_dp->aux,16 ,3 , conn_base_id);if (ret) { intel_dp->can_mst = false;
drivers/gpu/drm/nouveau/nv50_display.c +16 -1
@@ -3310,6 +3310,12 @@ nv50_mstm = { .hotplug = nv50_mstm_hotplug, }; +static const struct drm_private_state_funcs +nv50_mst_state_funcs = { + .atomic_duplicate_state = drm_atomic_dp_mst_duplicate_topology_state, + .atomic_destroy_state = drm_atomic_dp_mst_destroy_topology_state, +}; +void nv50_mstm_service (struct nv50_mstm *mstm) {
@@ -3438,6 +3444,7 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, {const int max_payloads =hweight8 (outp->dcb->heads);struct drm_device *dev = outp->base.base.dev; +struct drm_dp_mst_topology_state *state;struct nv50_mstm *mstm;int ret, i;u8 dpcd;
@@ -3454,10 +3461,18 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max,if (!(mstm = *pmstm =kzalloc (sizeof (*mstm),GFP_KERNEL )))return -ENOMEM ; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state) { +kfree (mstm); +return -ENOMEM ; + } mstm->outp = outp; mstm->mgr.cbs = &nv50_mstm; + mstm->mgr.funcs = &nv50_mst_state_funcs; - ret =drm_dp_mst_topology_mgr_init (&mstm->mgr, dev, aux, aux_max, + ret =drm_dp_mst_topology_mgr_init (&mstm->mgr, state, dev, + aux, aux_max, max_payloads, conn_base_id);if (ret)return ret;
drivers/gpu/drm/radeon/radeon_dp_mst.c +12 -1
@@ -335,6 +335,11 @@ static const struct drm_dp_mst_topology_cbs mst_cbs = { .hotplug = radeon_dp_mst_hotplug, }; +static const struct drm_private_state_funcs mst_state_funcs = { + .atomic_duplicate_state = drm_atomic_dp_mst_duplicate_topology_state, + .atomic_destroy_state = drm_atomic_dp_mst_destroy_topology_state, +}; +static struct radeon_connector *radeon_mst_find_connector (struct drm_encoder *encoder) {
@@ -657,12 +662,18 @@ int radeon_dp_mst_init(struct radeon_connector *radeon_connector) {struct drm_device *dev = radeon_connector->base.dev; +struct drm_dp_mst_topology_state *state = +kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state) +return -ENOMEM ;if (!radeon_connector->ddc_bus->has_aux)return 0 ; radeon_connector->mst_mgr.cbs = &mst_cbs; -return drm_dp_mst_topology_mgr_init (&radeon_connector->mst_mgr, dev, + radeon_connector->mst_mgr.funcs = &mst_state_funcs; +return drm_dp_mst_topology_mgr_init (&radeon_connector->mst_mgr, + state, dev, &radeon_connector->ddc_bus->aux,16 ,6 , radeon_connector->base.base.id); }
include/drm/drm_dp_mst_helper.h +8 -0
@@ -565,6 +565,7 @@ struct drm_dp_mst_topology_mgr { };int drm_dp_mst_topology_mgr_init (struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_topology_state *state,struct drm_device *dev,struct drm_dp_aux *aux,int max_dpcd_transaction_bytes,int max_payloads,int conn_base_id);
@@ -621,6 +622,13 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);struct drm_dp_mst_topology_state *drm_atomic_dp_mst_get_topology_state (struct drm_atomic_state *state,struct drm_dp_mst_topology_mgr *mgr); +struct drm_private_state *drm_atomic_dp_mst_duplicate_topology_state (struct drm_private_obj *obj); +int __drm_atomic_dp_mst_duplicate_topology_state (struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_topology_state *state); +void drm_atomic_dp_mst_destroy_topology_state (struct drm_private_obj *obj, +struct drm_private_state *state); +void __drm_atomic_dp_mst_destroy_topology_state (struct drm_dp_mst_topology_state *state); +int drm_dp_atomic_find_vcpi_slots (struct drm_atomic_state *state,struct drm_dp_mst_topology_mgr *mgr,struct drm_dp_mst_port *port,int pbn);
Signature · 6 lines
2.14.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Lyude Paul
maintainerPATCH v8 6/10 drm/dp_mst: Add reset_state callback to topology mgr
In reply to Lyude PaulThis gives drivers subclassing drm_dp_mst_topology_state the ability to prepare their topology states for a new hub to be connected whenever it's detected that the currently connected topology has been disconnected from the system. We'll need this in order to correctly track RX capabilities in i915 from the topology's atomic state.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/drm_dp_mst_topology.c | 10 ++++++++++ include/drm/drm_dp_mst_helper.h | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_dp_mst_topology.c +10 -0
@@ -2096,6 +2096,15 @@ static bool drm_dp_get_vc_payload_bw(int dp_link_bw,return true; } +static void drm_dp_mst_topology_reset_state (struct drm_dp_mst_topology_mgr *mgr) +{ +struct drm_dp_mst_topology_state *state = +to_dp_mst_topology_state (mgr->base.state); + +if (mgr->cbs->reset_state) + mgr->cbs->reset_state (state); +} +/** * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager * @mgr: manager to set state for
@@ -2171,6 +2180,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms mgr->payload_mask =0 ;set_bit (0 , &mgr->payload_mask); mgr->vcpi_mask =0 ; +drm_dp_mst_topology_reset_state (mgr); } out_unlock:
include/drm/drm_dp_mst_helper.h +2 -1
@@ -381,6 +381,7 @@ struct drm_dp_sideband_msg_tx {/* sideband msg handler */ struct drm_dp_mst_topology_mgr ; +struct drm_dp_mst_topology_state ;struct drm_dp_mst_topology_cbs {/* create a connector for a port */ struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr,struct drm_dp_mst_port *port,const char *path);
@@ -388,7 +389,7 @@ struct drm_dp_mst_topology_cbs {void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,struct drm_connector *connector);void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr); - +void (*reset_state)(struct drm_dp_mst_topology_state *state); };#define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8)
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Lyude Paul
maintainerPATCH v8 7/10 drm/i915: Only use one link bw config for MST topologies
In reply to Lyude PaulWhen a DP MST link needs retraining, sometimes the hub will detect that the current link bw config is impossible and will update it's RX caps in the DPCD to reflect the new maximum link rate. Currently, we make the assumption that the RX caps in the dpcd will never change like this. This means if the sink changes it's RX caps after we've already set up an MST link and we attempt to add or remove another sink from the topology, we could put ourselves into an invalid state where we've tried to configure different sinks on the same MST topology with different link rates. We could also run into this situation if a sink reports a higher link rate after suspend, usually from us having trained it with a fallback bw configuration before suspending.
So: keep the link rate consistent by subclassing drm_dp_mst_topology_state, and tracking it there. For the time being, we only allow the link rate to change when the entire topology has been disconnected.
V4:
- Track link rate/lane count in the atomic topology state instead of in intel_dp.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/i915/intel_dp_mst.c | 79 +++++++++++++++++++++++++++++-------- drivers/gpu/drm/i915/intel_drv.h | 7 ++++ 2 files changed, 70 insertions(+), 16 deletions(-)
drivers/gpu/drm/i915/intel_dp_mst.c +63 -16
@@ -41,8 +41,11 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,struct intel_connector *connector =to_intel_connector (conn_state->connector);struct drm_atomic_state *state = pipe_config->base.state; +struct drm_dp_mst_topology_state *mst_state = +drm_atomic_dp_mst_get_topology_state (state, &intel_dp->mst_mgr); +struct intel_dp_mst_topology_state *intel_mst_state;int bpp; -int lane_count, slots; +int slots;const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;int mst_pbn; bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
@@ -55,18 +58,22 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,DRM_DEBUG_KMS ("Setting pipe bpp to %d\n" , bpp); } + + intel_mst_state = +to_intel_dp_mst_topology_state (mst_state);/* * for MST we always configure max link bw - the spec doesn't * seem to suggest we should do otherwise. */ - lane_count =intel_dp_max_lane_count (intel_dp); - - pipe_config->lane_count = lane_count; +if (!intel_mst_state->link_rate || !intel_mst_state->lane_count) { + intel_mst_state->link_rate =intel_dp_max_link_rate (intel_dp); + intel_mst_state->lane_count =intel_dp_max_lane_count (intel_dp); + } + pipe_config->lane_count = intel_mst_state->lane_count; + pipe_config->port_clock = intel_mst_state->link_rate; pipe_config->pipe_bpp = bpp; - pipe_config->port_clock =intel_dp_max_link_rate (intel_dp); -if (drm_dp_mst_port_has_audio (&intel_dp->mst_mgr, connector->port)) pipe_config->has_audio = true;
@@ -80,7 +87,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,return false; } - intel_link_compute_m_n(bpp, lane_count, + intel_link_compute_m_n(bpp, intel_mst_state->lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, &pipe_config->dp_m_n,
@@ -530,11 +537,55 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)drm_kms_helper_hotplug_event (dev); } +static void intel_mst_reset_state (struct drm_dp_mst_topology_state *state) +{ +struct intel_dp_mst_topology_state *intel_mst_state = +to_intel_dp_mst_topology_state (state); + + intel_mst_state->link_rate =0 ; + intel_mst_state->lane_count =0 ; +} +static const struct drm_dp_mst_topology_cbs mst_cbs = { .add_connector = intel_dp_add_mst_connector, .register_connector = intel_dp_register_mst_connector, .destroy_connector = intel_dp_destroy_mst_connector, .hotplug = intel_dp_mst_hotplug, + .reset_state = intel_mst_reset_state, +}; + +static struct drm_private_state * +intel_dp_mst_duplicate_state (struct drm_private_obj *obj) +{ +struct intel_dp_mst_topology_state *state; +struct drm_dp_mst_topology_mgr *mgr =to_dp_mst_topology_mgr (obj); + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + +__drm_atomic_dp_mst_duplicate_topology_state (mgr, &state->base); + +return &state->base.base; +} + +static void +intel_dp_mst_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ +struct drm_dp_mst_topology_state *mst_state = +to_dp_mst_topology_state (state); +struct intel_dp_mst_topology_state *intel_mst_state = +to_intel_dp_mst_topology_state (mst_state); + +__drm_atomic_dp_mst_destroy_topology_state (mst_state); + +kfree (intel_mst_state); +} + +static const struct drm_private_state_funcs mst_state_funcs = { + .atomic_duplicate_state = intel_dp_mst_duplicate_state, + .atomic_destroy_state = intel_dp_mst_destroy_state, }; static struct intel_dp_mst_encoder *
@@ -587,21 +638,16 @@ intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port)return true; } -static const struct drm_private_state_funcs mst_state_funcs = { - .atomic_destroy_state = drm_atomic_dp_mst_destroy_topology_state, - .atomic_duplicate_state = drm_atomic_dp_mst_duplicate_topology_state, -}; -int intel_dp_mst_encoder_init (struct intel_digital_port *intel_dig_port,int conn_base_id) {struct intel_dp *intel_dp = &intel_dig_port->dp; -struct drm_dp_mst_topology_state *mst_state; +struct intel_dp_mst_topology_state *intel_mst_state;struct drm_device *dev = intel_dig_port->base.base.dev;int ret; - mst_state =kzalloc (sizeof (*mst_state),GFP_KERNEL ); -if (!mst_state) + intel_mst_state =kzalloc (sizeof (*intel_mst_state),GFP_KERNEL ); +if (!intel_mst_state)return -ENOMEM ; intel_dp->can_mst = true;
@@ -610,7 +656,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_ba/* create encoders */ intel_dp_create_fake_mst_encoders (intel_dig_port); - ret =drm_dp_mst_topology_mgr_init (&intel_dp->mst_mgr, mst_state, dev, + ret =drm_dp_mst_topology_mgr_init (&intel_dp->mst_mgr, + &intel_mst_state->base, dev, &intel_dp->aux,16 ,3 , conn_base_id);if (ret) { intel_dp->can_mst = false;
drivers/gpu/drm/i915/intel_drv.h +7 -0
@@ -985,6 +985,12 @@ struct cxsr_latency {u16 cursor_hpll_disable; }; +struct intel_dp_mst_topology_state { +struct drm_dp_mst_topology_state base; +int link_rate; +int lane_count; +}; +#define to_intel_atomic_state (x) container_of(x, struct intel_atomic_state, base)#define to_intel_crtc (x) container_of(x, struct intel_crtc, base)#define to_intel_crtc_state (x) container_of(x, struct intel_crtc_state, base)
@@ -993,6 +999,7 @@ struct cxsr_latency {#define to_intel_framebuffer (x) container_of(x, struct intel_framebuffer, base)#define to_intel_plane (x) container_of(x, struct intel_plane, base)#define to_intel_plane_state (x) container_of(x, struct intel_plane_state, base) +#define to_intel_dp_mst_topology_state (x) container_of(x, struct intel_dp_mst_topology_state, base)#define intel_fb_obj (x) (x ? to_intel_framebuffer(x)->obj : NULL)struct intel_hdmi {
Signature · 6 lines
2.14.3 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Lyude Paul
maintainerPATCH v8 8/10 drm/i915: Make intel_dp_mst_atomic_check() idempotent
In reply to Lyude PaulThe current way of handling changing VCPI allocations doesn't make a whole ton of sense. Since drm_atomic_helper_check_modeset() can be called multiple times which means that intel_dp_mst_atomic_check() can also be called multiple times. However, since we make the silly mistake of trying to free VCPI slots based off the /new/ atomic state instead of the old atomic state, we'll end up potentially double freeing the vcpi slots for the ports.
This also has another unintended consequence that came back up while implementing MST fallback retraining: if a modeset is forced on a connector that's already part of the state, but it's atomic_check() has already been run once and doesn't get run again, we'll end up not freeing the VCPI allocations on the connector at all.
The easiest way to solve this is to be clever and, with the exception of connectors that are being disabled and thus will never have compute_config() ran on them, move vcpi freeing out of the atomic check and into compute_config().
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/i915/intel_dp_mst.c | 84 +++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 21 deletions(-)
drivers/gpu/drm/i915/intel_dp_mst.c +63 -21
@@ -30,6 +30,38 @@#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +static int +intel_dp_mst_atomic_release_vcpi_slots (struct drm_atomic_state *state, +struct drm_crtc_state *crtc_state, +struct drm_connector_state *conn_state) +{ +struct drm_crtc_state *new_crtc_state; +struct intel_crtc_state *intel_crtc_state = +to_intel_crtc_state (crtc_state); +struct drm_encoder *encoder; +struct drm_dp_mst_topology_mgr *mgr; +int slots, ret; + + slots = intel_crtc_state->dp_m_n.tu; +if (slots <=0 ) +return 0 ; + + encoder = conn_state->best_encoder; + mgr = &enc_to_mst (encoder)->primary->dp.mst_mgr; + + ret =drm_dp_atomic_release_vcpi_slots (state, mgr, slots); +if (ret) { +DRM_DEBUG_KMS ("failed releasing %d vcpi slots:%d\n" , + slots, ret); + }else { + new_crtc_state =drm_atomic_get_crtc_state (state, + crtc_state->crtc); +to_intel_crtc_state (new_crtc_state)->dp_m_n.tu =0 ; + } + +return ret; +} +static bool intel_dp_mst_compute_config (struct intel_encoder *encoder,struct intel_crtc_state *pipe_config,struct drm_connector_state *conn_state)
@@ -44,10 +76,14 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,struct drm_dp_mst_topology_state *mst_state =drm_atomic_dp_mst_get_topology_state (state, &intel_dp->mst_mgr);struct intel_dp_mst_topology_state *intel_mst_state; +struct drm_connector_state *old_conn_state = +drm_atomic_get_old_connector_state (state, &connector->base); +struct drm_crtc *old_crtc;int bpp;int slots;const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;int mst_pbn; +int ret;bool reduce_m_n =drm_dp_has_quirk (&intel_dp->desc,DP_DPCD_QUIRK_LIMITED_M_N );
@@ -80,6 +116,21 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, mst_pbn =drm_dp_calc_pbn_mode (adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; +/* Free any VCPI allocations on this connector from the previous +* state +*/ + old_crtc = old_conn_state->crtc; +if (old_crtc) { +struct drm_crtc_state *old_crtc_state = +drm_atomic_get_old_crtc_state (state, old_crtc); + + ret =intel_dp_mst_atomic_release_vcpi_slots (state, + old_crtc_state, + old_conn_state); +if (ret) +return ret; + } + slots =drm_dp_atomic_find_vcpi_slots (state, &intel_dp->mst_mgr, connector->port, mst_pbn);if (slots <0 ) {
@@ -109,31 +160,22 @@ static int intel_dp_mst_atomic_check(struct drm_connector *connector, {struct drm_atomic_state *state = new_conn_state->state;struct drm_connector_state *old_conn_state; -struct drm_crtc *old_crtc; -struct drm_crtc_state *crtc_state; -int slots, ret =0 ; +struct drm_crtc_state *new_crtc_state; +int ret =0 ; old_conn_state =drm_atomic_get_old_connector_state (state, connector); - old_crtc = old_conn_state->crtc; -if (!old_crtc) -return ret; - crtc_state =drm_atomic_get_new_crtc_state (state, old_crtc); - slots =to_intel_crtc_state (crtc_state)->dp_m_n.tu; -if (drm_atomic_crtc_needs_modeset (crtc_state) && slots >0 ) { -struct drm_dp_mst_topology_mgr *mgr; -struct drm_encoder *old_encoder; - - old_encoder = old_conn_state->best_encoder; - mgr = &enc_to_mst (old_encoder)->primary->dp.mst_mgr; +/* Only free VCPI here if we're not going to be detaching the +* connector's current CRTC, since no config will be computed +*/ +if (new_conn_state->crtc || !old_conn_state->crtc) +return ret; - ret =drm_dp_atomic_release_vcpi_slots (state, mgr, slots); -if (ret) -DRM_DEBUG_KMS ("failed releasing %d vcpi slots:%d\n" , slots, ret); -else -to_intel_crtc_state (crtc_state)->dp_m_n.tu =0 ; - } -return ret; + new_crtc_state =drm_atomic_get_new_crtc_state (state, + old_conn_state->crtc); +return intel_dp_mst_atomic_release_vcpi_slots (state, + new_crtc_state, + old_conn_state); } static void intel_mst_disable_dp(struct intel_encoder *encoder,
Signature · 1 line
2.14.3
Lyude Paul
maintainerPATCH v8 9/10 drm/dp_mst: Add MST fallback retraining helpers
In reply to Lyude PaulUnlike SST, MST can have far more then a single display hooked up on a single port. What this also means however, is that if the DisplayPort link to the top-level MST branch device becomes unstable then every single branch device also has an unstable link. Additionally, MST has a few more steps that must be taken in order to properly retrain the entire topology under a lower link rate. Since the VCPI allocations for each mstb is determined based off the link rate for the top of the topology, we also have to recalculate all of the VCPI allocations for the downstream ports as well to ensure that we still have enough link bandwidth to drive each mstb.
Additionally, since we have multiple downstream connectors per port, setting the link status of the parent mstb's port to bad isn't enough:
all of the downstream mstb ports have to have their link status set to bad.
This basically follows the same paradigm that our DP link status logic in DRM does, in that we simply tell userspace that all of the mstb ports need retraining and additionally applying the new lower bandwidth constraints to all of the atomic commits on the topology that follow. Additionally; we add helpers that handle automatically checking whether or not a new atomic commit would perform the modesets required to retrain a link and if so, additionally handles updating the link status of each connector on the MST topology.
V4:
- clarify slightly confusing message in drm_dp_mst_topology_mgr_lower_link_rate()
- Fix argument naming
- Squash this with the other retrain helper, because now they're intertwined with one another
- Track which connectors with CRTCs need modesets in order to retrain a topology in the topology's atomic state. This lets us greatly simplify the helpers, along with alleviating drivers of the responsibility of figuring out when to call the retrain helpers during atomic checks. It also ensures that we can keep zombie connectors that a retrain is dependent on alive until the topology either disappears, or they are disabled. We needed to do most of this anyway, since our original helpers didn't take into account that we need to invoke retraining when the link status prop changes, regardless of whether or not a modeset has been initiated yet.
- Handle situation we completely forgot about: adding new connectors to an MST topology that needs fallback retraining (solution: new connectors on a topology inherit the link status of the rest of the topology)
- Also make sure to handle connectors that are orphaned due to their MST topology disappearing. Solution: remove from topology state, reset link status to good
- Write more docs on the retraining procedure.
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/drm_dp_mst_topology.c | 440 +++++++++++++++++++++++++++++++++- include/drm/drm_dp_mst_helper.h | 20 ++ 2 files changed, 455 insertions(+), 5 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +435 -5
@@ -1199,6 +1199,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,if (created && !port->input) {char proppath[255 ]; +struct drm_dp_mst_topology_state *state;build_mst_prop_path (mstb, port->port_num, proppath,sizeof (proppath)); port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
@@ -1217,6 +1218,11 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, port->cached_edid =drm_get_edid (port->connector, &port->aux.ddc);drm_mode_connector_set_tile_property (port->connector); } + state =to_dp_mst_topology_state (port->mgr->base.state); +if (!list_empty (&state->bad_ports)) { + port->connector->state->link_status = +DRM_LINK_STATUS_BAD ; + } (*mstb->mgr->cbs->register_connector)(port->connector); }
@@ -2076,7 +2082,7 @@ static bool drm_dp_get_vc_payload_bw(int dp_link_bw, {switch (dp_link_bw) {default : -DRM_DEBUG_KMS ("invalid link bandwidth in DPCD: %x (link count: %d)\n" , +DRM_DEBUG_KMS ("invalid link bandwidth: %x (link count: %d)\n" , dp_link_bw, dp_link_count);return false;
@@ -2096,10 +2102,409 @@ static bool drm_dp_get_vc_payload_bw(int dp_link_bw,return true; } +static int drm_dp_set_mstb_link_status (struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_branch *mstb, +enum drm_link_status status) +{ +struct drm_dp_mst_topology_state *state = +to_dp_mst_topology_state (mgr->base.state); +struct drm_dp_mst_branch *rmstb; +struct drm_dp_mst_port *port; +struct drm_connector *connector; +struct drm_dp_mst_retrain_dep *retrain_dep; +int ret; + +list_for_each_entry (port, &mstb->ports, next) { + rmstb =drm_dp_get_validated_mstb_ref (mgr, port->mstb); +if (rmstb) { + ret =drm_dp_set_mstb_link_status (mgr, rmstb, status); +drm_dp_put_mst_branch_device (rmstb); + +if (ret) +return ret; + } + + connector = port->connector; +if (!connector) +continue ; + +DRM_DEBUG_ATOMIC ("[CONNECTOR:%d:%s] link status good -> bad\n" , + connector->base.id, connector->name); + connector->state->link_status = status; + +if (!connector->state->crtc) +continue ; + + retrain_dep =kmalloc (sizeof (*retrain_dep),GFP_KERNEL ); +if (!retrain_dep) { +DRM_ERROR ("Not enough memory to update atomic state\n" ); +return -ENOMEM ; + } + + retrain_dep->connector = connector; +drm_connector_get (connector); +list_add (&retrain_dep->entry, &state->bad_ports); + } + +return 0 ; +} + +static void drm_dp_mst_destroy_retrain_dep (struct drm_dp_mst_retrain_dep *dep) +{ +drm_connector_put (dep->connector); +list_del (&dep->entry); +kfree (dep); +} + +/** +* DOC: handling link retraining on MST topologies +* +* DisplayPort MST hubs work by allowing multiple connections on a single +* physical DisplayPort link. Because of this, any changes in the link status +* affect all connectors on the shared link. This has quite a number of +* important implications. +* +* When an MST topology requires that it be retrained at a lower link rate, +* the new link rate must be applied to all active connectors at the same +* time, since they share the same link. This means that if a connector has +* it's link status set to &DRM_MODE_LINK_STATUS_BAD and it's on an MST +* topology, changing the property to &DRM_MODE_LINK_STATUS_GOOD will result +* in adding every other connector that resides on the same topology into the +* new atomic state. Additionally, any MST connectors that were added to the +* state with CRTCs attached to them will automatically have a modeset forced +* on them in the atomic state, and have their link status updated to +* &DRM_MODE_LINK_STATUS_GOOD. If userspace has not set a new mode on these +* connectors, the kernel will attempt to reuse the same modes that are +* currently active on said CRTCs. All modes set on said connectors within +* this state are then checked against the new lowered link configuration to +* ensure that there is still enough bandwidth to support them. If there is +* not enough bandwidth, the atomic check will fail. +* +* Detaching CRTCs from MST connectors that have their link status set to +* &DRM_MODE_LINK_STATUS_BAD has a different effect however. Because disabling +* a CRTC on an MST connector only requires that the driver free the bandwidth +* allocated to a connector and does not require the driver to allocate more +* bandwidth, states which disable CRTCs on an MST topology but do not enable +* new CRTCs or apply new modes to CRTCs on the topology will not implicitly +* pull in the state of other CRTCs attached to connectors on the topology. +* This allows userspace to disable CRTCs on a topology that requires +* retraining in any order it chooses, so long as it doesn't try to apply new +* modes to the topology. +* +* If an atomic state would put an MST topology into a state where it has no +* connectors present that are attached to CRTCs, the kernel will +* automatically add each connector on the topology to the state and update +* their respective link statuses to &DRM_MODE_LINK_STATUS_GOOD. This is +* because when there are no active VC channels allocated on a hub, there is +* nothing which prevents the driver from immediately changing the maximum +* link rate/lane count, as the updated link configuration can simply be +* applied the next time a CRTC is attached to a connector on the topology. +* +* When an MST topology requires link retraining at a lower link rate, any new +* connectors that appear on the topology will automatically inherit the link +* status value of other connectors on the topology. This is to ensure that +* the shared link status remains consistent across the topology, and to +* prevent new modesets from occurring on the topology without first requiring +* a full retrain. +*/ + +/** +* drm_dp_mst_topology_mgr_lower_link_rate() - Override the DP link rate/count +* for all connectors in a given MST topology +* @mgr: manager to set state for +* @link_rate: The new DP link bandwidth +* @lane_count: The new DP lane count +* +* This is called by the driver when it detects that the current DP link for +* the given topology manager is unstable, and needs to be retrained at a +* lower link rate/lane count. +* +* This takes care of updating the link status on all downstream connectors, +* the mst topology's atomic state, and VC payloads for each port. +* The driver should send a hotplug event after calling this function to +* notify userspace of the link status change. +* +* RETURNS: +* +* True for success, or negative error code on failure. +*/ +int drm_dp_mst_topology_mgr_lower_link_rate (struct drm_dp_mst_topology_mgr *mgr, +int link_rate,int lane_count) +{ +struct drm_device *dev = mgr->dev; +struct drm_dp_mst_topology_state *state; +struct drm_dp_mst_branch *mst_primary; +struct drm_dp_mst_retrain_dep *retrain_dep, *retrain_tmp; +struct drm_connector *connector; +int new_pbn_div; +int ret =0 ; + +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); + + state =to_dp_mst_topology_state (mgr->base.state); + +if (!drm_dp_get_vc_payload_bw (drm_dp_link_rate_to_bw_code (link_rate), + lane_count, &new_pbn_div)) { + ret = -EINVAL ; + goto out; + } + + mst_primary =drm_dp_get_validated_mstb_ref (mgr, mgr->mst_primary); +if (!mst_primary) + goto out; + +DRM_DEBUG_KMS ("MST link impossible to retrain at current params, lowering pbn_div to %d\n" , + new_pbn_div); + mgr->pbn_div = new_pbn_div; + + ret =drm_dp_set_mstb_link_status (mgr, mst_primary, +DRM_LINK_STATUS_BAD ); +if (ret) { +DRM_DEBUG_KMS ("Failed to update link status, rolling back\n" ); + +list_for_each_entry_safe (retrain_dep, retrain_tmp, + &state->bad_ports, entry) { + connector = retrain_dep->connector; + connector->state->link_status =DRM_LINK_STATUS_GOOD ; + +drm_dp_mst_destroy_retrain_dep (retrain_dep); + } + } + +drm_dp_put_mst_branch_device (mst_primary); +out: +drm_modeset_unlock (&dev->mode_config.connection_mutex); +return ret; +} +EXPORT_SYMBOL (drm_dp_mst_topology_mgr_lower_link_rate); + +static void +drm_atomic_dp_mst_satisfy_retrain_dep (struct drm_dp_mst_topology_state *mst_state, +struct drm_connector *connector) +{ +struct drm_dp_mst_retrain_dep *dep; + +list_for_each_entry (dep, &mst_state->bad_ports, entry) { +if (dep->connector != connector) +continue ; + +drm_dp_mst_destroy_retrain_dep (dep); +break ; + } +} + +static int +drm_atomic_dp_mst_retrain_connector (struct drm_atomic_state *state, +struct drm_dp_mst_topology_state *mst_state, +struct drm_connector *connector) +{ +struct drm_connector_state *conn_state = +drm_atomic_get_connector_state (state, connector); +struct drm_crtc *crtc; +struct drm_crtc_state *crtc_state; + +if (IS_ERR (conn_state)) +return PTR_ERR (conn_state); + +if (conn_state->link_status ==DRM_LINK_STATUS_BAD ) { +DRM_DEBUG_ATOMIC ("[CONNECTOR:%d:%s] link status bad -> good\n" , + connector->base.id, connector->name); + conn_state->link_status =DRM_LINK_STATUS_GOOD ; + } + +drm_atomic_dp_mst_satisfy_retrain_dep (mst_state, connector); + + crtc = conn_state->crtc; +if (!crtc) +return 0 ; + + crtc_state =drm_atomic_get_crtc_state (state, crtc); +if (IS_ERR (crtc_state)) +return PTR_ERR (crtc_state); + +if (!drm_atomic_crtc_needs_modeset (crtc_state)) +DRM_DEBUG_ATOMIC ("[CRTC:%d:%s] needs full modeset\n" , + crtc->base.id, crtc->name); + + crtc_state->mode_changed = true; +return 0 ; +} + +static int +drm_atomic_dp_mst_retrain_mstb (struct drm_atomic_state *state, +struct drm_dp_mst_topology_state *mst_state, +struct drm_dp_mst_branch *mstb) +{ +struct drm_dp_mst_branch *rmstb; +struct drm_dp_mst_port *port; +struct drm_connector *connector; +int ret; + +list_for_each_entry (port, &mstb->ports, next) { + rmstb =drm_dp_get_validated_mstb_ref (mstb->mgr, port->mstb); +if (rmstb) { + ret =drm_atomic_dp_mst_retrain_mstb (state, mst_state, + rmstb); +drm_dp_put_mst_branch_device (rmstb); +if (ret) +return ret; + } + + connector = port->connector; +if (!connector) +continue ; + + ret =drm_atomic_dp_mst_retrain_connector (state, mst_state, + connector); +if (ret) +return ret; + } + +return 0 ; +} + +/** +* drm_dp_atomic_mst_check_retrain() - Prepare the topology's state to be +* retrained during this atomic commit, if required +* @new_conn_state: the new connector state possibly triggering a retrain +* @mgr: The DP MST topology to retrain +* +* When the link status of an MST topology goes from +* &DRM_MODE_LINK_STATUS_GOOD to &DRM_MODE_LINK_STATUS_BAD, the entire +* topology is considered to be in a state where a retrain at a lower link +* rate is required. Because each connector on an MST topology shares the same +* DP link, each connector must have it's link rate lowered and be retrained +* at the same time. Additionally, drivers must take care to update the link +* status of a connector on an MST topology themselves if userspace attempts +* to set a new mode to the connector regardless of whether or not it properly +* updates the connector's link status property from +* &DRM_MODE_LINK_STATUS_BAD to &DRM_MODE_LINK_STATUS_GOOD. In this case, the +* driver must take care of updating this link status property on it's own. +* +* This function takes care of handling all of the above requirements, and +* should be called during the start of the atomic check phase for an MST +* connector if the driver properly implements MST fallback retraining. +* +* Additionally; drivers are recommended to check the return value of this +* function in order to determine whether or not a full retrain of the MST +* topology would be performed by the new atomic state. This gives the +* driver a chance to update any private portions of the topology state that +* must be reset before a retrain, such as the link rate and lane count being +* shared by the topology. +* +* RETURNS: 1 if the given atomic state retrains the MST topology, 0 if the +* atomic state doesn't retrain the topology. On error, a negative error code +* is returned. +*/ +int drm_dp_atomic_mst_check_retrain (struct drm_connector_state *new_conn_state, +struct drm_dp_mst_topology_mgr *mgr) +{ +struct drm_atomic_state *state = new_conn_state->state; +struct drm_dp_mst_topology_state *mst_state; +struct drm_dp_mst_branch *mstb; +struct drm_dp_mst_retrain_dep *retrain_dep, *retrain_tmp; +struct drm_connector *connector = new_conn_state->connector; +struct drm_connector_state *old_conn_state = +drm_atomic_get_old_connector_state (state, connector); +struct drm_crtc_state *crtc_state; +struct drm_crtc *crtc; +int ret; + +if (old_conn_state->link_status !=DRM_LINK_STATUS_BAD ) +return 0 ; + + mst_state =drm_atomic_dp_mst_get_topology_state (state, mgr); +if (list_empty (&mst_state->bad_ports)) +return 0 ; + +/* Check if the new state requires us to update the link status +* prop +*/ +if (new_conn_state->link_status ==DRM_LINK_STATUS_BAD ) { +/* Any modesets that leave a CRTC enabled must update link +* status +*/ +if (new_conn_state->crtc) { + crtc = new_conn_state->crtc; + crtc_state =drm_atomic_get_new_crtc_state (state, + crtc); +if (crtc_state && +drm_atomic_crtc_needs_modeset (crtc_state)) { +DRM_DEBUG_ATOMIC ("[CRTC:%d:%s] modeset requires link retrain\n" , + crtc->base.id, crtc->name); + new_conn_state->link_status = +DRM_LINK_STATUS_GOOD ; + } + }else if (old_conn_state->crtc) { +drm_atomic_dp_mst_satisfy_retrain_dep (mst_state, + connector); +/* If all CRTCs on this hub would be disabled by this +* state, link status can be updated to GOOD +*/ +if (list_empty (&mst_state->bad_ports)) { +DRM_DEBUG_ATOMIC ("state %p disables all CRTCs on %p, link would be retrained\n" , + state, mgr); + new_conn_state->link_status = +DRM_LINK_STATUS_GOOD ; + } + } +if (new_conn_state->link_status ==DRM_LINK_STATUS_BAD ) +return 0 ; + } + +DRM_DEBUG_ATOMIC ("[CONNECTOR:%d:%s] link status bad -> good\n" , + connector->base.id, connector->name); + ret =drm_atomic_dp_mst_retrain_connector (state, mst_state, + connector); +if (ret) +return ret; + +/* Retrain whole topology */ + mstb =drm_dp_get_validated_mstb_ref (mgr, mgr->mst_primary); +if (!mstb) +return -EIO ; + ret =drm_atomic_dp_mst_retrain_mstb (state, mst_state, mstb); +drm_dp_put_mst_branch_device (mstb); +if (ret) +return ret; + +/* Additionally, it's possible that the topology connector state may +* have changed between the time the topology's link status went to +* BAD. As a result, it's possible that there's still leftover retrain +* dependencies that refer to connectors that no longer exist on the +* hub. Ensure these are added to the state as well +*/ +list_for_each_entry_safe (retrain_dep, retrain_tmp, + &mst_state->bad_ports, entry) { + ret =drm_atomic_dp_mst_retrain_connector (state, mst_state, + connector); +if (ret) +return ret; + } + +return 1 ; +} +EXPORT_SYMBOL (drm_dp_atomic_mst_check_retrain); +static void drm_dp_mst_topology_reset_state (struct drm_dp_mst_topology_mgr *mgr) { +struct drm_dp_mst_retrain_dep *retrain_dep, *retrain_tmp;struct drm_dp_mst_topology_state *state =to_dp_mst_topology_state (mgr->base.state); +struct drm_connector *connector; + +list_for_each_entry_safe (retrain_dep, retrain_tmp, &state->bad_ports, + entry) { +/* Reset the connector link state, since there's no way to +* retrain something that no longer exists +*/ + connector = retrain_dep->connector; + +DRM_DEBUG_KMS ("[CONNECTOR:%d:%s] loses parent MST topology mgr %p, link status bad -> good\n" , + connector->base.id, connector->name, mgr); + connector->state->link_status =DRM_LINK_STATUS_GOOD ; +drm_dp_mst_destroy_retrain_dep (retrain_dep); + }if (mgr->cbs->reset_state) mgr->cbs->reset_state (state);
@@ -3110,7 +3515,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) (*mgr->cbs->hotplug)(mgr); } -/** +/* * drm_atomic_dp_mst_duplicate_topology_state - default * drm_dp_mst_topology_state duplicate handler *
@@ -3153,9 +3558,26 @@ int __drm_atomic_dp_mst_duplicate_topology_state(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_topology_state *state) { + struct drm_dp_mst_retrain_dep *retrain_dep, *new_retrain_dep;struct drm_private_obj *obj = &mgr->base; +struct drm_dp_mst_topology_state *src_state = +to_dp_mst_topology_state (obj->state);memcpy (state, obj->state,sizeof (*state)); +INIT_LIST_HEAD (&state->bad_ports); + +/* Copy the bad ports list to the new state */ +list_for_each_entry (retrain_dep, &src_state->bad_ports, entry) { + new_retrain_dep =kmalloc (sizeof (*retrain_dep),GFP_KERNEL ); +if (!new_retrain_dep) { +__drm_atomic_dp_mst_destroy_topology_state (state); +return -ENOMEM ; + } + + new_retrain_dep->connector = retrain_dep->connector; +drm_connector_get (retrain_dep->connector); +list_add (&new_retrain_dep->entry, &state->bad_ports); + }__drm_atomic_helper_private_obj_duplicate_state (&mgr->base, &state->base);
@@ -3169,9 +3591,8 @@ EXPORT_SYMBOL(__drm_atomic_dp_mst_duplicate_topology_state);* * For drivers which don't yet subclass drm_dp_mst_topology_state. */ -void -drm_atomic_dp_mst_destroy_topology_state (struct drm_private_obj *obj, -struct drm_private_state *state) +void drm_atomic_dp_mst_destroy_topology_state (struct drm_private_obj *obj, +struct drm_private_state *state) {struct drm_dp_mst_topology_state *mst_state =to_dp_mst_topology_state (state);
@@ -3192,6 +3613,13 @@ EXPORT_SYMBOL(drm_atomic_dp_mst_destroy_topology_state);void __drm_atomic_dp_mst_destroy_topology_state (struct drm_dp_mst_topology_state *state) { +struct drm_dp_mst_retrain_dep *retrain_dep, *retrain_tmp; + +list_for_each_entry_safe (retrain_dep, retrain_tmp, &state->bad_ports, + entry) { +drm_connector_put (retrain_dep->connector); +kfree (retrain_dep); + } }EXPORT_SYMBOL (__drm_atomic_dp_mst_destroy_topology_state);
@@ -3276,6 +3704,8 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,/* max. time slots - one slot for MTP header */ state->avail_slots =63 ; +INIT_LIST_HEAD (&state->bad_ports); +drm_atomic_private_obj_init (&mgr->base, &state->base, mgr->funcs);
include/drm/drm_dp_mst_helper.h +20 -0
@@ -407,9 +407,24 @@ struct drm_dp_payload {#define to_dp_mst_topology_state (x) container_of(x, struct drm_dp_mst_topology_state, base) +/* Represents a connector with an MST port whose mstb had a mode programmed +* when the link rate of the topology was lowered. As long as a topology state +* has these, no mstbs may be activated +*/ +struct drm_dp_mst_retrain_dep { +struct drm_connector *connector; +struct list_head entry; +}; +struct drm_dp_mst_topology_state {struct drm_private_state base;int avail_slots; +/** +* @bad_ports: DRM connectors that must have their mode changed before +* the link status of each connector on the MST hub can be updated +* from BAD to GOOD +*/ +struct list_head bad_ports;struct drm_dp_mst_topology_mgr *mgr; };
@@ -639,4 +654,9 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,int drm_dp_send_power_updown_phy (struct drm_dp_mst_topology_mgr *mgr,struct drm_dp_mst_port *port,bool power_up); +int drm_dp_mst_topology_mgr_lower_link_rate (struct drm_dp_mst_topology_mgr *mgr, +int link_rate,int lane_count); +int drm_dp_atomic_mst_check_retrain (struct drm_connector_state *new_conn_state, +struct drm_dp_mst_topology_mgr *mgr); +#endif
Signature · 1 line
2.14.3
Lyude Paul
maintainerPATCH v8 10/10 drm/i915: Implement proper fallback training for MST
In reply to Lyude PaulFor a while we actually haven't had any way of retraining MST links with fallback link parameters like we do with SST. While uncommon, certain setups such as my Caldigit TS3 + EVGA MST hub require this since otherwise, they end up getting stuck in an infinite MST retraining loop.
MST retraining is somewhat different then SST retraining. While it's possible during the normal link retraining sequence for a hub to indicate bad link status, it's also possible for a hub to only indicate this status through ESI messages and it's possible for this to happen after the initial link training succeeds. This can lead to a pattern that looks like this:
- Train MST link
- Training completes successfully
- MST hub sets Channel EQ failed bit in ESI
- Retraining starts
- Retraining completes successfully
- MST hub sets Channel EQ failed bit in ESI again
- Rinse and repeat
In these situations, we need to be able to actually trigger fallback link training from the ESI handler as well, along with using the ESI handler during retraining to figure out whether or not our retraining actually succeeded.
This gets a bit more complicated since we have to ensure that we don't block the ESI handler at all while doing retraining. If we do, due to DisplayPort's general issues with being sensitive to IRQ latency most MST hubs will just stop responding to us if their interrupts aren't handled in a timely manner.
So: move retraining into it's own separate handler. Running in a separate handler allows us to avoid stalling the ESI during link retraining, and we can have the ESI signal that the channel EQ bit was cleared through a simple completion struct. Additionally, we take care to stick as much of this into the SST retraining path as possible since sharing is caring.
V4:
- Move all MST retraining work into hotplug_work
- Grab the correct power wells when retraining.
- Loop through MST encoders in intel_dp_get_crtc_mask(), quicker/easier than connectors
V7:
- Fix CHECKPATCH errors
--- drivers/gpu/drm/i915/intel_ddi.c | 10 +- drivers/gpu/drm/i915/intel_dp.c | 370 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_dp_link_training.c | 6 +- drivers/gpu/drm/i915/intel_dp_mst.c | 28 +- drivers/gpu/drm/i915/intel_drv.h | 7 + 5 files changed, 329 insertions(+), 92 deletions(-)
drivers/gpu/drm/i915/intel_ddi.c +9 -1
@@ -3042,6 +3042,7 @@ static bool intel_ddi_hotplug(struct intel_encoder *encoder, struct intel_connector *connector) {struct drm_modeset_acquire_ctx ctx; +struct intel_dp *intel_dp =enc_to_intel_dp (&encoder->base);bool changed;int ret;
@@ -3063,9 +3064,16 @@ static bool intel_ddi_hotplug(struct intel_encoder *encoder,break ; } +if (ret == -EINVAL ) + ret =intel_dp_handle_train_failure (intel_dp); +drm_modeset_drop_locks (&ctx);drm_modeset_acquire_fini (&ctx); -WARN (ret,"Acquiring modeset locks failed with %i\n" , ret); + +if (ret == -EIO ) + changed = true; +else +WARN (ret,"Acquiring modeset locks failed with %i\n" , ret);return changed; }
drivers/gpu/drm/i915/intel_dp.c +285 -85
499 lines not on this page · raw message
drivers/gpu/drm/i915/intel_dp_link_training.c +1 -5
@@ -336,11 +336,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) intel_connector->base.base.id, intel_connector->base.name, intel_dp->link_rate, intel_dp->lane_count); -if (!intel_dp_get_link_train_fallback_values (intel_dp, - intel_dp->link_rate, - intel_dp->lane_count)) -/* Schedule a Hotplug Uevent to userspace to start modeset */ -schedule_work (&intel_dp->modeset_retry_work); +intel_dp_handle_train_failure (intel_dp); }else { DRM_ERROR("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", intel_connector->base.base.id,
drivers/gpu/drm/i915/intel_dp_mst.c +27 -1
@@ -156,13 +156,37 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, }static int intel_dp_mst_atomic_check (struct drm_connector *connector, -struct drm_connector_state *new_conn_state) +struct drm_connector_state *new_conn_state) {struct drm_atomic_state *state = new_conn_state->state;struct drm_connector_state *old_conn_state;struct drm_crtc_state *new_crtc_state; +struct intel_dp *intel_dp =to_intel_connector (connector)->mst_port; +struct drm_dp_mst_topology_state *mst_state; +struct intel_dp_mst_topology_state *intel_mst_state;int ret =0 ; +/* We can't retrain anything if the hub isn't there anymore */ +if (intel_dp) { + ret =drm_dp_atomic_mst_check_retrain (new_conn_state, + &intel_dp->mst_mgr); + +/* This commit invokes a retrain, reset the link rate */ +if (ret ==1 ) { + mst_state = +drm_atomic_dp_mst_get_topology_state (state, + &intel_dp->mst_mgr); + intel_mst_state = +to_intel_dp_mst_topology_state (mst_state); + + intel_mst_state->link_rate =0 ; + intel_mst_state->lane_count =0 ; + ret =0 ; + }else if (ret <0 ) { +return ret; + } + } + old_conn_state =drm_atomic_get_old_connector_state (state, connector);/* Only free VCPI here if we're not going to be detaching the
@@ -230,7 +254,9 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, intel_mst->connector =NULL ;if (intel_dp->active_mst_links ==0 ) { + intel_dp->link_is_bad = false;intel_dp_sink_dpms (intel_dp,DRM_MODE_DPMS_OFF ); + intel_dig_port->base.post_disable (&intel_dig_port->base, old_crtc_state,NULL ); }
drivers/gpu/drm/i915/intel_drv.h +7 -0
@@ -1128,6 +1128,11 @@ struct intel_dp {/* mst connector list */ struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES ];struct drm_dp_mst_topology_mgr mst_mgr; +struct completion mst_retrain_completion; +/* Set when retraining the link at the current parameters is +* impossible +*/ +bool link_is_bad;uint32_t (*get_aux_clock_divider)(struct intel_dp *dp,int index);/*
@@ -1649,6 +1654,7 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp);void intel_dp_stop_link_train (struct intel_dp *intel_dp);int intel_dp_retrain_link (struct intel_encoder *encoder,struct drm_modeset_acquire_ctx *ctx); +int intel_dp_handle_train_failure (struct intel_dp *intel_dp);void intel_dp_sink_dpms (struct intel_dp *intel_dp,int mode);void intel_dp_encoder_reset (struct drm_encoder *encoder);void intel_dp_encoder_suspend (struct intel_encoder *intel_encoder);
@@ -1701,6 +1707,7 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,bool intel_dp_source_supports_hbr2 (struct intel_dp *intel_dp);bool intel_dp_get_link_status (struct intel_dp *intel_dp,uint8_t link_status[DP_LINK_STATUS_SIZE ]); +int intel_dp_get_crtc_mask (struct intel_dp *intel_dp);static inline unsigned int intel_dp_unused_lane_mask (int lane_count) {
Signature · 1 line
2.14.3
Patchwork
CI✓ Fi.CI.BAT: success for drm/i915: Implement proper fallback training for MST (rev3)
In reply to Lyude Paul== Series Details ==
== Series Details ==
Series: drm/i915: Implement proper fallback training for MST (rev3)
URL : https://patchwork.freedesktop.org/series/41576/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4047 -> Patchwork_8677 =
== Summary - SUCCESS ==
No regressions found.
External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8677/
== Known issues ==
Here are the changes found in Patchwork_8677 that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
fi-snb-2520m: PASS -> INCOMPLETE (fdo#103713)fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
== Participating hosts (35 -> 31) ==
Missing (4): fi-ctg-p8600 fi-ilk-m540 fi-skl-6700hq fi-pnv-d510
== Build changes ==
* Linux: CI_DRM_4047 -> Patchwork_8677
CI_DRM_4047: b21f4ebec3a255026a780ee4a35ec5f8d9ede6cd @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4423: d502f055ac4500cada758876a512ac4f14b34851 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_8677: 88bd769db904f7cef7a7bd84f18dbb888e877f0b @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4423: 45e115f293fd6acc0c9647cf2d3b76be78819ba5 @ git://anongit.freedesktop.org/piglit
== Linux commits ==
88bd769db904 drm/i915: Implement proper fallback training for MST e90617f089bb drm/dp_mst: Add MST fallback retraining helpers d98833048074 drm/i915: Make intel_dp_mst_atomic_check() idempotent db5a00aa82a5 drm/i915: Only use one link bw config for MST topologies e6acd981c2d1 drm/dp_mst: Add reset_state callback to topology mgr 5da4ec1ce3d3 drm/dp_mst: Make drm_dp_mst_topology_state subclassable a280b47b272d drm/dp_mst: Remove all evil duplicate state pointers 759d35707723 drm/dp_mst: Fix naming on drm_atomic_get_mst_topology_state() ea6ee1670e74 drm/i915: Move DP modeset retry work into intel_dp 7d0088ea4e77 drm/atomic: Print debug message on atomic check failure
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8677/issues.html
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Patchwork
CI✓ Fi.CI.IGT: success for drm/i915: Implement proper fallback training for MST (rev3)
In reply to Lyude Paul== Series Details ==
== Series Details ==
Series: drm/i915: Implement proper fallback training for MST (rev3)
URL : https://patchwork.freedesktop.org/series/41576/
State : success
== Summary ==
= CI Bug Log - changes from CI_DRM_4047_full -> Patchwork_8677_full =
== Summary - WARNING ==
Minor unknown changes coming with Patchwork_8677_full need to be verified manually.
If you think the reported changes have nothing to do with the changes introduced in Patchwork_8677_full, please notify your bug team to allow them to document this new failure mode, which will reduce false positives in CI.
External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8677/
== Possible new issues ==
Here are the unknown changes that may have been introduced in Patchwork_8677_full:
=== IGT changes ===
==== Warnings ====
igt@gem_mocs_settings@mocs-rc6-blt:
shard-kbl: SKIP -> PASS== Known issues ==
Here are the changes found in Patchwork_8677_full that come from known issues:
=== IGT changes ===
==== Issues hit ====
igt@drv_selftest@live_gtt:
shard-apl: PASS -> INCOMPLETE (fdo#103927)
igt@gem_ppgtt@blt-vs-render-ctxn:
shard-hsw: PASS -> INCOMPLETE (fdo#103540)
igt@kms_flip@2x-flip-vs-expired-vblank-interruptible:
shard-hsw: PASS -> FAIL (fdo#102887)
igt@kms_flip@flip-vs-modeset-vs-hang-interruptible:
shard-snb: PASS -> DMESG-WARN (fdo#104311)
igt@kms_flip@modeset-vs-vblank-race-interruptible:
shard-hsw: PASS -> FAIL (fdo#103060)
==== Possible fixes ====
igt@kms_flip@2x-plain-flip-fb-recreate-interruptible:
shard-hsw: FAIL (fdo#100368) -> PASS
igt@kms_setmode@basic:
shard-apl: FAIL (fdo#99912) -> PASS
igt@perf_pmu@rc6-runtime-pm-long:
shard-kbl: FAIL (fdo#105010) -> PASS fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
fdo#103540 https://bugs.freedesktop.org/show_bug.cgi?id=103540
fdo#103927 https://bugs.freedesktop.org/show_bug.cgi?id=103927
fdo#104311 https://bugs.freedesktop.org/show_bug.cgi?id=104311
fdo#105010 https://bugs.freedesktop.org/show_bug.cgi?id=105010
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
== Participating hosts (6 -> 4) ==
Missing (2): shard-glk shard-glkb
== Build changes ==
* Linux: CI_DRM_4047 -> Patchwork_8677
CI_DRM_4047: b21f4ebec3a255026a780ee4a35ec5f8d9ede6cd @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_4423: d502f055ac4500cada758876a512ac4f14b34851 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
Patchwork_8677: 88bd769db904f7cef7a7bd84f18dbb888e877f0b @ git://anongit.freedesktop.org/gfx-ci/linux
piglit_4423: 45e115f293fd6acc0c9647cf2d3b76be78819ba5 @ git://anongit.freedesktop.org/piglit
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8677/shards.html
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx