Commit ada7339e authored by Linus Torvalds's avatar 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.
parents 4277e6b9 012cface
...@@ -4555,8 +4555,8 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -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) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
struct amdgpu_crtc *acrtc = NULL; struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_dm_connector *aconnector = NULL; struct amdgpu_dm_connector *aconnector = NULL;
struct drm_connector_state *new_con_state = NULL; struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
struct dm_connector_state *dm_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; struct drm_plane_state *new_plane_state = NULL;
new_stream = NULL; new_stream = NULL;
...@@ -4577,19 +4577,23 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4577,19 +4577,23 @@ static int dm_update_crtcs_state(struct dc *dc,
/* TODO This hack should go away */ /* TODO This hack should go away */
if (aconnector && enable) { if (aconnector && enable) {
// Make sure fake sink is created in plug-in scenario // 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); &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; 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_stream = create_stream_for_sink(aconnector,
&new_crtc_state->mode, &new_crtc_state->mode,
dm_conn_state); dm_new_conn_state);
/* /*
* we can have no stream on ACTION_SET if a display * we can have no stream on ACTION_SET if a display
...@@ -4695,20 +4699,30 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -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 * We want to do dc stream updates that do not require a
* full modeset below. * full modeset below.
*/ */
if (!enable || !aconnector || modereset_required(new_crtc_state)) if (!(enable && aconnector && new_crtc_state->enable &&
new_crtc_state->active))
continue; continue;
/* /*
* Given above conditions, the dc state cannot be NULL because: * Given above conditions, the dc state cannot be NULL because:
* 1. We're attempting to enable a CRTC. Which has a... * 1. We're in the process of enabling CRTCs (just been added
* 2. Valid connector attached, and * to the dc context, or already is on the context)
* 3. User does not want to reset it (disable or mark inactive, * 2. Has a valid connector attached, and
* which can happen on a CRTC that's already disabled). * 3. Is currently active and enabled.
* => It currently exists. * => The dc stream state currently exists.
*/ */
BUG_ON(dm_new_crtc_state->stream == NULL); BUG_ON(dm_new_crtc_state->stream == NULL);
/* Color managment settings */ /* Scaling or underscan settings */
if (dm_new_crtc_state->base.color_mgmt_changed) { 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); ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
if (ret) if (ret)
goto fail; goto fail;
......
...@@ -2077,7 +2077,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) ...@@ -2077,7 +2077,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
return ret; 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); mutex_lock(&hdmi->mutex);
...@@ -2103,13 +2103,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) ...@@ -2103,13 +2103,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
} }
mutex_unlock(&hdmi->mutex); 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); EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) 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) ...@@ -2145,9 +2138,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
*/ */
if (intr_stat & if (intr_stat &
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
__dw_hdmi_setup_rx_sense(hdmi, dw_hdmi_setup_rx_sense(hdmi,
phy_stat & HDMI_PHY_HPD, phy_stat & HDMI_PHY_HPD,
phy_stat & HDMI_PHY_RX_SENSE); phy_stat & HDMI_PHY_RX_SENSE);
if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
cec_notifier_set_phys_addr(hdmi->cec_notifier, 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]) ...@@ -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[] = { static const u16 psr_setup_time_us[] = {
PSR_SETUP_TIME(330), PSR_SETUP_TIME(330),
PSR_SETUP_TIME(275), PSR_SETUP_TIME(275),
PSR_SETUP_TIME(220),
PSR_SETUP_TIME(165), PSR_SETUP_TIME(165),
PSR_SETUP_TIME(110), PSR_SETUP_TIME(110),
PSR_SETUP_TIME(55), PSR_SETUP_TIME(55),
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* Copyright © 2018 Intel Corporation * Copyright © 2018 Intel Corporation
*/ */
#include <linux/nospec.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_query.h" #include "i915_query.h"
#include <uapi/drm/i915_drm.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) ...@@ -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++) { for (i = 0; i < args->num_items; i++, user_item_ptr++) {
struct drm_i915_query_item item; struct drm_i915_query_item item;
u64 func_idx; unsigned long func_idx;
int ret; int ret;
if (copy_from_user(&item, user_item_ptr, sizeof(item))) 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) ...@@ -109,12 +111,17 @@ int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (item.query_id == 0) if (item.query_id == 0)
return -EINVAL; return -EINVAL;
if (overflows_type(item.query_id - 1, unsigned long))
return -EINVAL;
func_idx = item.query_id - 1; 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); ret = i915_query_funcs[func_idx](dev_priv, &item);
else }
ret = -EINVAL;
/* Only write the length back to userspace if they differ. */ /* Only write the length back to userspace if they differ. */
if (ret != item.length && put_user(ret, &user_item_ptr->length)) 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, ...@@ -574,6 +574,36 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
return NOTIFY_OK; 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 * intel_lvds_destroy - unregister and free LVDS structures
* @connector: connector to free * @connector: connector to free
...@@ -586,9 +616,6 @@ static void intel_lvds_destroy(struct drm_connector *connector) ...@@ -586,9 +616,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
struct intel_lvds_connector *lvds_connector = struct intel_lvds_connector *lvds_connector =
to_lvds_connector(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)) if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
kfree(lvds_connector->base.edid); kfree(lvds_connector->base.edid);
...@@ -609,8 +636,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { ...@@ -609,8 +636,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property, .atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property, .atomic_set_property = intel_digital_connector_atomic_set_property,
.late_register = intel_connector_register, .late_register = intel_lvds_connector_register,
.early_unregister = intel_connector_unregister, .early_unregister = intel_lvds_connector_unregister,
.destroy = intel_lvds_destroy, .destroy = intel_lvds_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state,
...@@ -827,6 +854,14 @@ static const struct dmi_system_id intel_no_lvds[] = { ...@@ -827,6 +854,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"), 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 */ { } /* terminating entry */
}; };
...@@ -1150,12 +1185,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) ...@@ -1150,12 +1185,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK; 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; return;
failed: failed:
......
...@@ -529,7 +529,7 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) ...@@ -529,7 +529,7 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
if (stat & HDMITX_TOP_INTR_HPD_RISE) if (stat & HDMITX_TOP_INTR_HPD_RISE)
hpd_connected = true; 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); hpd_connected);
drm_helper_hpd_irq_event(dw_hdmi->encoder.dev); 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, ...@@ -82,7 +82,7 @@ static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
struct dispc_clock_info *dispc_cinfo) struct dispc_clock_info *dispc_cinfo)
{ {
int i; 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 * 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, ...@@ -95,6 +95,9 @@ static int sdi_calc_clock_div(struct sdi_device *sdi, unsigned long pclk,
bool ok; bool ok;
memset(&ctx, 0, sizeof(ctx)); memset(&ctx, 0, sizeof(ctx));
ctx.sdi = sdi;
if (pclk > 1000 * i * i * i) if (pclk > 1000 * i * i * i)
ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu); ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
else else
......
...@@ -151,7 +151,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, ...@@ -151,7 +151,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
struct drm_encoder *encoder, struct drm_encoder *encoder,
const struct dw_hdmi_plat_data *plat_data); 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_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment