提交 ada7339e 编写于 作者: L Linus Torvalds

Merge tag 'drm-fixes-for-v4.17-rc8' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "A few final fixes:

  i915:
   - fix for potential Spectre vector in the new query uAPI
   - fix NULL pointer deref (FDO #106559)
   - DMI fix to hide LVDS for Radiant P845 (FDO #105468)

  amdgpu:
   - suspend/resume DC regression fix
   - underscan flicker fix on fiji
   - gamma setting fix after dpms

  omap:
   - fix oops regression

  core:
   - fix PSR timing

  dw-hdmi:
   - fix oops regression"

* tag 'drm-fixes-for-v4.17-rc8' of git://people.freedesktop.org/~airlied/linux:
  drm/amd/display: Update color props when modeset is required
  drm/amd/display: Make atomic-check validate underscan changes
  drm/bridge/synopsys: dw-hdmi: fix dw_hdmi_setup_rx_sense
  drm/amd/display: Fix BUG_ON during CRTC atomic check update
  drm/i915/query: nospec expects no more than an unsigned long
  drm/i915/query: Protect tainted function pointer lookup
  drm/i915/lvds: Move acpi lid notification registration to registration phase
  drm/i915: Disable LVDS on Radiant P845
  drm/omap: fix NULL deref crash with SDI displays
  drm/psr: Fix missed entry in PSR setup time table.
......@@ -4555,8 +4555,8 @@ static int dm_update_crtcs_state(struct dc *dc,
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_dm_connector *aconnector = NULL;
struct drm_connector_state *new_con_state = NULL;
struct dm_connector_state *dm_conn_state = NULL;
struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
struct dm_connector_state *dm_new_conn_state = NULL, *dm_old_conn_state = NULL;
struct drm_plane_state *new_plane_state = NULL;
new_stream = NULL;
......@@ -4577,19 +4577,23 @@ static int dm_update_crtcs_state(struct dc *dc,
/* TODO This hack should go away */
if (aconnector && enable) {
// Make sure fake sink is created in plug-in scenario
new_con_state = drm_atomic_get_connector_state(state,
drm_new_conn_state = drm_atomic_get_new_connector_state(state,
&aconnector->base);
drm_old_conn_state = drm_atomic_get_old_connector_state(state,
&aconnector->base);
if (IS_ERR(new_con_state)) {
ret = PTR_ERR_OR_ZERO(new_con_state);
if (IS_ERR(drm_new_conn_state)) {
ret = PTR_ERR_OR_ZERO(drm_new_conn_state);
break;
}
dm_conn_state = to_dm_connector_state(new_con_state);
dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
dm_old_conn_state = to_dm_connector_state(drm_old_conn_state);
new_stream = create_stream_for_sink(aconnector,
&new_crtc_state->mode,
dm_conn_state);
dm_new_conn_state);
/*
* we can have no stream on ACTION_SET if a display
......@@ -4695,20 +4699,30 @@ static int dm_update_crtcs_state(struct dc *dc,
* We want to do dc stream updates that do not require a
* full modeset below.
*/
if (!enable || !aconnector || modereset_required(new_crtc_state))
if (!(enable && aconnector && new_crtc_state->enable &&
new_crtc_state->active))
continue;
/*
* Given above conditions, the dc state cannot be NULL because:
* 1. We're attempting to enable a CRTC. Which has a...
* 2. Valid connector attached, and
* 3. User does not want to reset it (disable or mark inactive,
* which can happen on a CRTC that's already disabled).
* => It currently exists.
* 1. We're in the process of enabling CRTCs (just been added
* to the dc context, or already is on the context)
* 2. Has a valid connector attached, and
* 3. Is currently active and enabled.
* => The dc stream state currently exists.
*/
BUG_ON(dm_new_crtc_state->stream == NULL);
/* Color managment settings */
if (dm_new_crtc_state->base.color_mgmt_changed) {
/* Scaling or underscan settings */
if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
update_stream_scaling_settings(
&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
/*
* Color management settings. We also update color properties
* when a modeset is needed, to ensure it gets reprogrammed.
*/
if (dm_new_crtc_state->base.color_mgmt_changed ||
drm_atomic_crtc_needs_modeset(new_crtc_state)) {
ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
if (ret)
goto fail;
......
......@@ -2077,7 +2077,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
return ret;
}
void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
{
mutex_lock(&hdmi->mutex);
......@@ -2103,13 +2103,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
}
mutex_unlock(&hdmi->mutex);
}
void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
{
struct dw_hdmi *hdmi = dev_get_drvdata(dev);
__dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
}
EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
......@@ -2145,9 +2138,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
*/
if (intr_stat &
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
__dw_hdmi_setup_rx_sense(hdmi,
phy_stat & HDMI_PHY_HPD,
phy_stat & HDMI_PHY_RX_SENSE);
dw_hdmi_setup_rx_sense(hdmi,
phy_stat & HDMI_PHY_HPD,
phy_stat & HDMI_PHY_RX_SENSE);
if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
cec_notifier_set_phys_addr(hdmi->cec_notifier,
......
......@@ -1145,6 +1145,7 @@ int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE])
static const u16 psr_setup_time_us[] = {
PSR_SETUP_TIME(330),
PSR_SETUP_TIME(275),
PSR_SETUP_TIME(220),
PSR_SETUP_TIME(165),
PSR_SETUP_TIME(110),
PSR_SETUP_TIME(55),
......
......@@ -4,6 +4,8 @@
* Copyright © 2018 Intel Corporation
*/
#include <linux/nospec.h>
#include "i915_drv.h"
#include "i915_query.h"
#include <uapi/drm/i915_drm.h>
......@@ -100,7 +102,7 @@ int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
for (i = 0; i < args->num_items; i++, user_item_ptr++) {
struct drm_i915_query_item item;
u64 func_idx;
unsigned long func_idx;
int ret;
if (copy_from_user(&item, user_item_ptr, sizeof(item)))
......@@ -109,12 +111,17 @@ int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (item.query_id == 0)
return -EINVAL;
if (overflows_type(item.query_id - 1, unsigned long))
return -EINVAL;
func_idx = item.query_id - 1;
if (func_idx < ARRAY_SIZE(i915_query_funcs))
ret = -EINVAL;
if (func_idx < ARRAY_SIZE(i915_query_funcs)) {
func_idx = array_index_nospec(func_idx,
ARRAY_SIZE(i915_query_funcs));
ret = i915_query_funcs[func_idx](dev_priv, &item);
else
ret = -EINVAL;
}
/* Only write the length back to userspace if they differ. */
if (ret != item.length && put_user(ret, &user_item_ptr->length))
......
......@@ -574,6 +574,36 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
return NOTIFY_OK;
}
static int
intel_lvds_connector_register(struct drm_connector *connector)
{
struct intel_lvds_connector *lvds = to_lvds_connector(connector);
int ret;
ret = intel_connector_register(connector);
if (ret)
return ret;
lvds->lid_notifier.notifier_call = intel_lid_notify;
if (acpi_lid_notifier_register(&lvds->lid_notifier)) {
DRM_DEBUG_KMS("lid notifier registration failed\n");
lvds->lid_notifier.notifier_call = NULL;
}
return 0;
}
static void
intel_lvds_connector_unregister(struct drm_connector *connector)
{
struct intel_lvds_connector *lvds = to_lvds_connector(connector);
if (lvds->lid_notifier.notifier_call)
acpi_lid_notifier_unregister(&lvds->lid_notifier);
intel_connector_unregister(connector);
}
/**
* intel_lvds_destroy - unregister and free LVDS structures
* @connector: connector to free
......@@ -586,9 +616,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
struct intel_lvds_connector *lvds_connector =
to_lvds_connector(connector);
if (lvds_connector->lid_notifier.notifier_call)
acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
kfree(lvds_connector->base.edid);
......@@ -609,8 +636,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property,
.late_register = intel_connector_register,
.early_unregister = intel_connector_unregister,
.late_register = intel_lvds_connector_register,
.early_unregister = intel_lvds_connector_unregister,
.destroy = intel_lvds_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
......@@ -827,6 +854,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Radiant P845",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "P845"),
},
},
{ } /* terminating entry */
};
......@@ -1150,12 +1185,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
DRM_DEBUG_KMS("lid notifier registration failed\n");
lvds_connector->lid_notifier.notifier_call = NULL;
}
return;
failed:
......
......@@ -529,7 +529,7 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
if (stat & HDMITX_TOP_INTR_HPD_RISE)
hpd_connected = true;
dw_hdmi_setup_rx_sense(dw_hdmi->dev, hpd_connected,
dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
hpd_connected);
drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
......
......@@ -82,7 +82,7 @@ static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
struct dispc_clock_info *dispc_cinfo)
{
int i;
struct sdi_clk_calc_ctx ctx = { .sdi = sdi };
struct sdi_clk_calc_ctx ctx;
/*
* DSS fclk gives us very few possibilities, so finding a good pixel
......@@ -95,6 +95,9 @@ static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
bool ok;
memset(&ctx, 0, sizeof(ctx));
ctx.sdi = sdi;
if (pclk > 1000 * i * i * i)
ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
else
......
......@@ -151,7 +151,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
struct drm_encoder *encoder,
const struct dw_hdmi_plat_data *plat_data);
void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense);
void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册