Commit 884d6147 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2014-06-17' of git://anongit.freedesktop.org/drm-intel into drm-next

First round of fixes for 3.16-rc, mostly cc: stable, and the vt/vgacon
fixes from Daniel [1] to avoid hangs and unclaimed register errors on
module load/reload.

* tag 'drm-intel-fixes-2014-06-17' of git://anongit.freedesktop.org/drm-intel:
  drm/i915/bdw: remove erroneous chv specific workarounds from bdw code
  drm/i915: fix possible refcount leak when resetting forcewake
  drm/i915: Reorder semaphore deadlock check
  drm/i95: Initialize active ring->pid to -1
  drm/i915: set backlight duty cycle after backlight enable for gen4
  drm/i915: Avoid div-by-zero when pixel_multiplier is zero
  drm/i915: Disable FBC by default also on Haswell and later
  drm/i915: Kick out vga console
  drm/i915: Fixup global gtt cleanup
  vt: Don't ignore unbind errors in vt_unbind
  vt: Fix up unregistration of vt drivers
  vt: Fix replacement console check when unbinding
parents fb54918a 223a6f2b
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/console.h>
#include <linux/vt.h>
#include <linux/vgaarb.h> #include <linux/vgaarb.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pnp.h> #include <linux/pnp.h>
...@@ -1386,7 +1388,6 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1386,7 +1388,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
i915_gem_context_fini(dev); i915_gem_context_fini(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
WARN_ON(dev_priv->mm.aliasing_ppgtt); WARN_ON(dev_priv->mm.aliasing_ppgtt);
drm_mm_takedown(&dev_priv->gtt.base.mm);
cleanup_irq: cleanup_irq:
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
cleanup_gem_stolen: cleanup_gem_stolen:
...@@ -1450,6 +1451,38 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) ...@@ -1450,6 +1451,38 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
} }
#endif #endif
#if !defined(CONFIG_VGA_CONSOLE)
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
return 0;
}
#elif !defined(CONFIG_DUMMY_CONSOLE)
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
return -ENODEV;
}
#else
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
int ret;
DRM_INFO("Replacing VGA console driver\n");
console_lock();
ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
if (ret == 0) {
ret = do_unregister_con_driver(&vga_con);
/* Ignore "already unregistered". */
if (ret == -ENODEV)
ret = 0;
}
console_unlock();
return ret;
}
#endif
static void i915_dump_device_info(struct drm_i915_private *dev_priv) static void i915_dump_device_info(struct drm_i915_private *dev_priv)
{ {
const struct intel_device_info *info = &dev_priv->info; const struct intel_device_info *info = &dev_priv->info;
...@@ -1623,8 +1656,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1623,8 +1656,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (ret) if (ret)
goto out_regs; goto out_regs;
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_kick_out_vgacon(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting VGA console\n");
goto out_gtt;
}
i915_kick_out_firmware_fb(dev_priv); i915_kick_out_firmware_fb(dev_priv);
}
pci_set_master(dev->pdev); pci_set_master(dev->pdev);
...@@ -1756,8 +1796,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1756,8 +1796,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
arch_phys_wc_del(dev_priv->gtt.mtrr); arch_phys_wc_del(dev_priv->gtt.mtrr);
io_mapping_free(dev_priv->gtt.mappable); io_mapping_free(dev_priv->gtt.mappable);
out_gtt: out_gtt:
list_del(&dev_priv->gtt.base.global_link);
drm_mm_takedown(&dev_priv->gtt.base.mm);
dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
out_regs: out_regs:
intel_uncore_fini(dev); intel_uncore_fini(dev);
...@@ -1846,7 +1884,6 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1846,7 +1884,6 @@ int i915_driver_unload(struct drm_device *dev)
i915_free_hws(dev); i915_free_hws(dev);
} }
list_del(&dev_priv->gtt.base.global_link);
WARN_ON(!list_empty(&dev_priv->vm_list)); WARN_ON(!list_empty(&dev_priv->vm_list));
drm_vblank_cleanup(dev); drm_vblank_cleanup(dev);
......
...@@ -1992,7 +1992,10 @@ static void gen6_gmch_remove(struct i915_address_space *vm) ...@@ -1992,7 +1992,10 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
drm_mm_takedown(&vm->mm); if (drm_mm_initialized(&vm->mm)) {
drm_mm_takedown(&vm->mm);
list_del(&vm->global_link);
}
iounmap(gtt->gsm); iounmap(gtt->gsm);
teardown_scratch_page(vm->dev); teardown_scratch_page(vm->dev);
} }
...@@ -2025,6 +2028,10 @@ static int i915_gmch_probe(struct drm_device *dev, ...@@ -2025,6 +2028,10 @@ static int i915_gmch_probe(struct drm_device *dev,
static void i915_gmch_remove(struct i915_address_space *vm) static void i915_gmch_remove(struct i915_address_space *vm)
{ {
if (drm_mm_initialized(&vm->mm)) {
drm_mm_takedown(&vm->mm);
list_del(&vm->global_link);
}
intel_gmch_remove(); intel_gmch_remove();
} }
......
...@@ -888,6 +888,8 @@ static void i915_gem_record_rings(struct drm_device *dev, ...@@ -888,6 +888,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
for (i = 0; i < I915_NUM_RINGS; i++) { for (i = 0; i < I915_NUM_RINGS; i++) {
struct intel_engine_cs *ring = &dev_priv->ring[i]; struct intel_engine_cs *ring = &dev_priv->ring[i];
error->ring[i].pid = -1;
if (ring->dev == NULL) if (ring->dev == NULL)
continue; continue;
...@@ -895,7 +897,6 @@ static void i915_gem_record_rings(struct drm_device *dev, ...@@ -895,7 +897,6 @@ static void i915_gem_record_rings(struct drm_device *dev,
i915_record_ring_state(dev, ring, &error->ring[i]); i915_record_ring_state(dev, ring, &error->ring[i]);
error->ring[i].pid = -1;
request = i915_gem_find_active_request(ring); request = i915_gem_find_active_request(ring);
if (request) { if (request) {
/* We need to copy these to an anonymous buffer /* We need to copy these to an anonymous buffer
......
...@@ -2847,10 +2847,14 @@ static int semaphore_passed(struct intel_engine_cs *ring) ...@@ -2847,10 +2847,14 @@ static int semaphore_passed(struct intel_engine_cs *ring)
struct intel_engine_cs *signaller; struct intel_engine_cs *signaller;
u32 seqno, ctl; u32 seqno, ctl;
ring->hangcheck.deadlock = true; ring->hangcheck.deadlock++;
signaller = semaphore_waits_for(ring, &seqno); signaller = semaphore_waits_for(ring, &seqno);
if (signaller == NULL || signaller->hangcheck.deadlock) if (signaller == NULL)
return -1;
/* Prevent pathological recursion due to driver bugs */
if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
return -1; return -1;
/* cursory check for an unkickable deadlock */ /* cursory check for an unkickable deadlock */
...@@ -2858,7 +2862,13 @@ static int semaphore_passed(struct intel_engine_cs *ring) ...@@ -2858,7 +2862,13 @@ static int semaphore_passed(struct intel_engine_cs *ring)
if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0) if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
return -1; return -1;
return i915_seqno_passed(signaller->get_seqno(signaller, false), seqno); if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
return 1;
if (signaller->hangcheck.deadlock)
return -1;
return 0;
} }
static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
...@@ -2867,7 +2877,7 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) ...@@ -2867,7 +2877,7 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
int i; int i;
for_each_ring(ring, dev_priv, i) for_each_ring(ring, dev_priv, i)
ring->hangcheck.deadlock = false; ring->hangcheck.deadlock = 0;
} }
static enum intel_ring_hangcheck_action static enum intel_ring_hangcheck_action
......
...@@ -798,9 +798,6 @@ static void i965_enable_backlight(struct intel_connector *connector) ...@@ -798,9 +798,6 @@ static void i965_enable_backlight(struct intel_connector *connector)
ctl = freq << 16; ctl = freq << 16;
I915_WRITE(BLC_PWM_CTL, ctl); I915_WRITE(BLC_PWM_CTL, ctl);
/* XXX: combine this into above write? */
intel_panel_actually_set_backlight(connector, panel->backlight.level);
ctl2 = BLM_PIPE(pipe); ctl2 = BLM_PIPE(pipe);
if (panel->backlight.combination_mode) if (panel->backlight.combination_mode)
ctl2 |= BLM_COMBINATION_MODE; ctl2 |= BLM_COMBINATION_MODE;
...@@ -809,6 +806,8 @@ static void i965_enable_backlight(struct intel_connector *connector) ...@@ -809,6 +806,8 @@ static void i965_enable_backlight(struct intel_connector *connector)
I915_WRITE(BLC_PWM_CTL2, ctl2); I915_WRITE(BLC_PWM_CTL2, ctl2);
POSTING_READ(BLC_PWM_CTL2); POSTING_READ(BLC_PWM_CTL2);
I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
intel_panel_actually_set_backlight(connector, panel->backlight.level);
} }
static void vlv_enable_backlight(struct intel_connector *connector) static void vlv_enable_backlight(struct intel_connector *connector)
......
...@@ -511,8 +511,7 @@ void intel_update_fbc(struct drm_device *dev) ...@@ -511,8 +511,7 @@ void intel_update_fbc(struct drm_device *dev)
obj = intel_fb->obj; obj = intel_fb->obj;
adjusted_mode = &intel_crtc->config.adjusted_mode; adjusted_mode = &intel_crtc->config.adjusted_mode;
if (i915.enable_fbc < 0 && if (i915.enable_fbc < 0) {
INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) {
if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT)) if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT))
DRM_DEBUG_KMS("disabled per chip default\n"); DRM_DEBUG_KMS("disabled per chip default\n");
goto out_disable; goto out_disable;
...@@ -3506,15 +3505,11 @@ static void gen8_enable_rps(struct drm_device *dev) ...@@ -3506,15 +3505,11 @@ static void gen8_enable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
/* WaDisablePwrmtrEvent:chv (pre-production hw) */
I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff);
I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00);
/* 5: Enable RPS */ /* 5: Enable RPS */
I915_WRITE(GEN6_RP_CONTROL, I915_WRITE(GEN6_RP_CONTROL,
GEN6_RP_MEDIA_TURBO | GEN6_RP_MEDIA_TURBO |
GEN6_RP_MEDIA_HW_NORMAL_MODE | GEN6_RP_MEDIA_HW_NORMAL_MODE |
GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */ GEN6_RP_MEDIA_IS_GFX |
GEN6_RP_ENABLE | GEN6_RP_ENABLE |
GEN6_RP_UP_BUSY_AVG | GEN6_RP_UP_BUSY_AVG |
GEN6_RP_DOWN_IDLE_AVG); GEN6_RP_DOWN_IDLE_AVG);
......
...@@ -55,7 +55,7 @@ struct intel_ring_hangcheck { ...@@ -55,7 +55,7 @@ struct intel_ring_hangcheck {
u32 seqno; u32 seqno;
int score; int score;
enum intel_ring_hangcheck_action action; enum intel_ring_hangcheck_action action;
bool deadlock; int deadlock;
}; };
struct intel_ringbuffer { struct intel_ringbuffer {
......
...@@ -1385,7 +1385,9 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, ...@@ -1385,7 +1385,9 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
>> SDVO_PORT_MULTIPLY_SHIFT) + 1; >> SDVO_PORT_MULTIPLY_SHIFT) + 1;
} }
dotclock = pipe_config->port_clock / pipe_config->pixel_multiplier; dotclock = pipe_config->port_clock;
if (pipe_config->pixel_multiplier)
dotclock /= pipe_config->pixel_multiplier;
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
ironlake_check_encoder_dotclock(pipe_config, dotclock); ironlake_check_encoder_dotclock(pipe_config, dotclock);
......
...@@ -320,7 +320,8 @@ static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) ...@@ -320,7 +320,8 @@ static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
del_timer_sync(&dev_priv->uncore.force_wake_timer); if (del_timer_sync(&dev_priv->uncore.force_wake_timer))
gen6_force_wake_timer((unsigned long)dev_priv);
/* Hold uncore.lock across reset to prevent any register access /* Hold uncore.lock across reset to prevent any register access
* with forcewake not set correctly * with forcewake not set correctly
......
...@@ -3226,8 +3226,7 @@ int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt ...@@ -3226,8 +3226,7 @@ int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt
for (i = 0; i < MAX_NR_CON_DRIVER; i++) { for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
con_back = &registered_con_driver[i]; con_back = &registered_con_driver[i];
if (con_back->con && if (con_back->con && con_back->con != csw) {
!(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
defcsw = con_back->con; defcsw = con_back->con;
retval = 0; retval = 0;
break; break;
...@@ -3332,6 +3331,7 @@ static int vt_unbind(struct con_driver *con) ...@@ -3332,6 +3331,7 @@ static int vt_unbind(struct con_driver *con)
{ {
const struct consw *csw = NULL; const struct consw *csw = NULL;
int i, more = 1, first = -1, last = -1, deflt = 0; int i, more = 1, first = -1, last = -1, deflt = 0;
int ret;
if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) || if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
con_is_graphics(con->con, con->first, con->last)) con_is_graphics(con->con, con->first, con->last))
...@@ -3357,8 +3357,10 @@ static int vt_unbind(struct con_driver *con) ...@@ -3357,8 +3357,10 @@ static int vt_unbind(struct con_driver *con)
if (first != -1) { if (first != -1) {
console_lock(); console_lock();
do_unbind_con_driver(csw, first, last, deflt); ret = do_unbind_con_driver(csw, first, last, deflt);
console_unlock(); console_unlock();
if (ret != 0)
return ret;
} }
first = -1; first = -1;
...@@ -3645,17 +3647,20 @@ static int do_register_con_driver(const struct consw *csw, int first, int last) ...@@ -3645,17 +3647,20 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
*/ */
int do_unregister_con_driver(const struct consw *csw) int do_unregister_con_driver(const struct consw *csw)
{ {
int i, retval = -ENODEV; int i;
/* cannot unregister a bound driver */ /* cannot unregister a bound driver */
if (con_is_bound(csw)) if (con_is_bound(csw))
goto err; return -EBUSY;
if (csw == conswitchp)
return -EINVAL;
for (i = 0; i < MAX_NR_CON_DRIVER; i++) { for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
struct con_driver *con_driver = &registered_con_driver[i]; struct con_driver *con_driver = &registered_con_driver[i];
if (con_driver->con == csw && if (con_driver->con == csw &&
con_driver->flag & CON_DRIVER_FLAG_MODULE) { con_driver->flag & CON_DRIVER_FLAG_INIT) {
vtconsole_deinit_device(con_driver); vtconsole_deinit_device(con_driver);
device_destroy(vtconsole_class, device_destroy(vtconsole_class,
MKDEV(0, con_driver->node)); MKDEV(0, con_driver->node));
...@@ -3666,12 +3671,11 @@ int do_unregister_con_driver(const struct consw *csw) ...@@ -3666,12 +3671,11 @@ int do_unregister_con_driver(const struct consw *csw)
con_driver->flag = 0; con_driver->flag = 0;
con_driver->first = 0; con_driver->first = 0;
con_driver->last = 0; con_driver->last = 0;
retval = 0; return 0;
break;
} }
} }
err:
return retval; return -ENODEV;
} }
EXPORT_SYMBOL_GPL(do_unregister_con_driver); EXPORT_SYMBOL_GPL(do_unregister_con_driver);
......
...@@ -77,3 +77,4 @@ const struct consw dummy_con = { ...@@ -77,3 +77,4 @@ const struct consw dummy_con = {
.con_set_palette = DUMMY, .con_set_palette = DUMMY,
.con_scrolldelta = DUMMY, .con_scrolldelta = DUMMY,
}; };
EXPORT_SYMBOL_GPL(dummy_con);
...@@ -1441,5 +1441,6 @@ const struct consw vga_con = { ...@@ -1441,5 +1441,6 @@ const struct consw vga_con = {
.con_build_attr = vgacon_build_attr, .con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region, .con_invert_region = vgacon_invert_region,
}; };
EXPORT_SYMBOL(vga_con);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
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