提交 7ae61368 编写于 作者: I Imre Deak 提交者: Zheng Zengkai

drm/i915/dp: Ensure sink rate values are always valid

stable inclusion
form stable-v5.10.82
commit 47901b77bf7dc801a084a0b377aee5974d9bc4ce
bugzilla: 185877 https://gitee.com/openeuler/kernel/issues/I4QU6V

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=47901b77bf7dc801a084a0b377aee5974d9bc4ce

--------------------------------

commit 6c34bd45 upstream.

Atm, there are no sink rate values set for DP (vs. eDP) sinks until the
DPCD capabilities are successfully read from the sink. During this time
intel_dp->num_common_rates is 0 which can lead to a

intel_dp->common_rates[-1]    (*)

access, which is an undefined behaviour, in the following cases:

- In intel_dp_sync_state(), if the encoder is enabled without a sink
  connected to the encoder's connector (BIOS enabled a monitor, but the
  user unplugged the monitor until the driver loaded).
- In intel_dp_sync_state() if the encoder is enabled with a sink
  connected, but for some reason the DPCD read has failed.
- In intel_dp_compute_link_config() if modesetting a connector without
  a sink connected on it.
- In intel_dp_compute_link_config() if modesetting a connector with a
  a sink connected on it, but before probing the connector first.

To avoid the (*) access in all the above cases, make sure that the sink
rate table - and hence the common rate table - is always valid, by
setting a default minimum sink rate when registering the connector
before anything could use it.

I also considered setting all the DP link rates by default, so that
modesetting with higher resolution modes also succeeds in the last two
cases above. However in case a sink is not connected that would stop
working after the first modeset, due to the LT fallback logic. So this
would need more work, beyond the scope of this fix.

As I mentioned in the previous patch, I don't think the issue this patch
fixes is user visible, however it is an undefined behaviour by
definition and triggers a BUG() in CONFIG_UBSAN builds, hence CC:stable.

v2: Clear the default sink rates, before initializing these for eDP.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4297
References: https://gitlab.freedesktop.org/drm/intel/-/issues/4298Suggested-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: NImre Deak <imre.deak@intel.com>
Reviewed-by: NVille Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: NJani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211018143417.1452632-1-imre.deak@intel.com
(cherry picked from commit 3f61ef97)
Signed-off-by: NRodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 fc4752a5
...@@ -154,6 +154,12 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, ...@@ -154,6 +154,12 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
enum pipe pipe); enum pipe pipe);
static void intel_dp_unset_edid(struct intel_dp *intel_dp); static void intel_dp_unset_edid(struct intel_dp *intel_dp);
static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
{
intel_dp->sink_rates[0] = 162000;
intel_dp->num_sink_rates = 1;
}
/* update sink rates from dpcd */ /* update sink rates from dpcd */
static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
{ {
...@@ -4678,6 +4684,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) ...@@ -4678,6 +4684,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
*/ */
intel_psr_init_dpcd(intel_dp); intel_psr_init_dpcd(intel_dp);
/* Clear the default sink rates */
intel_dp->num_sink_rates = 0;
/* Read the eDP 1.4+ supported link rates. */ /* Read the eDP 1.4+ supported link rates. */
if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
__le16 sink_rates[DP_MAX_SUPPORTED_RATES]; __le16 sink_rates[DP_MAX_SUPPORTED_RATES];
...@@ -7779,6 +7788,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, ...@@ -7779,6 +7788,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
return false; return false;
intel_dp_set_source_rates(intel_dp); intel_dp_set_source_rates(intel_dp);
intel_dp_set_default_sink_rates(intel_dp);
intel_dp_set_common_rates(intel_dp);
intel_dp->reset_link_params = true; intel_dp->reset_link_params = true;
intel_dp->pps_pipe = INVALID_PIPE; intel_dp->pps_pipe = INVALID_PIPE;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册