Commit 99584db3 authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: extract hangcheck/reset/error_state state into substruct

This has been sprinkled all over the place in dev_priv. I think
it'd be good to also move all the code into a separate file like
i915_gem_error.c, but that's for another patch.
Reviewed-by: default avatarDamien Lespiau <damien.lespiau@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 4b5aed62
...@@ -814,11 +814,11 @@ static int i915_error_state_open(struct inode *inode, struct file *file) ...@@ -814,11 +814,11 @@ static int i915_error_state_open(struct inode *inode, struct file *file)
error_priv->dev = dev; error_priv->dev = dev;
spin_lock_irqsave(&dev_priv->error_lock, flags); spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error_priv->error = dev_priv->first_error; error_priv->error = dev_priv->gpu_error.first_error;
if (error_priv->error) if (error_priv->error)
kref_get(&error_priv->error->ref); kref_get(&error_priv->error->ref);
spin_unlock_irqrestore(&dev_priv->error_lock, flags); spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
return single_open(file, i915_error_state, error_priv); return single_open(file, i915_error_state, error_priv);
} }
...@@ -1727,7 +1727,7 @@ i915_ring_stop_read(struct file *filp, ...@@ -1727,7 +1727,7 @@ i915_ring_stop_read(struct file *filp,
int len; int len;
len = snprintf(buf, sizeof(buf), len = snprintf(buf, sizeof(buf),
"0x%08x\n", dev_priv->stop_rings); "0x%08x\n", dev_priv->gpu_error.stop_rings);
if (len > sizeof(buf)) if (len > sizeof(buf))
len = sizeof(buf); len = sizeof(buf);
...@@ -1763,7 +1763,7 @@ i915_ring_stop_write(struct file *filp, ...@@ -1763,7 +1763,7 @@ i915_ring_stop_write(struct file *filp,
if (ret) if (ret)
return ret; return ret;
dev_priv->stop_rings = val; dev_priv->gpu_error.stop_rings = val;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return cnt; return cnt;
......
...@@ -1605,7 +1605,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1605,7 +1605,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
pci_enable_msi(dev->pdev); pci_enable_msi(dev->pdev);
spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->gpu_error.lock);
spin_lock_init(&dev_priv->rps.lock); spin_lock_init(&dev_priv->rps.lock);
mutex_init(&dev_priv->dpio_lock); mutex_init(&dev_priv->dpio_lock);
...@@ -1725,8 +1725,8 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1725,8 +1725,8 @@ int i915_driver_unload(struct drm_device *dev)
} }
/* Free error state after interrupts are fully disabled. */ /* Free error state after interrupts are fully disabled. */
del_timer_sync(&dev_priv->hangcheck_timer); del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
cancel_work_sync(&dev_priv->error_work); cancel_work_sync(&dev_priv->gpu_error.work);
i915_destroy_error_state(dev); i915_destroy_error_state(dev);
if (dev->pdev->msi_enabled) if (dev->pdev->msi_enabled)
......
...@@ -779,9 +779,9 @@ int intel_gpu_reset(struct drm_device *dev) ...@@ -779,9 +779,9 @@ int intel_gpu_reset(struct drm_device *dev)
} }
/* Also reset the gpu hangman. */ /* Also reset the gpu hangman. */
if (dev_priv->stop_rings) { if (dev_priv->gpu_error.stop_rings) {
DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n"); DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
dev_priv->stop_rings = 0; dev_priv->gpu_error.stop_rings = 0;
if (ret == -ENODEV) { if (ret == -ENODEV) {
DRM_ERROR("Reset not implemented, but ignoring " DRM_ERROR("Reset not implemented, but ignoring "
"error for simulated gpu hangs\n"); "error for simulated gpu hangs\n");
...@@ -820,12 +820,12 @@ int i915_reset(struct drm_device *dev) ...@@ -820,12 +820,12 @@ int i915_reset(struct drm_device *dev)
i915_gem_reset(dev); i915_gem_reset(dev);
ret = -ENODEV; ret = -ENODEV;
if (get_seconds() - dev_priv->last_gpu_reset < 5) if (get_seconds() - dev_priv->gpu_error.last_reset < 5)
DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
else else
ret = intel_gpu_reset(dev); ret = intel_gpu_reset(dev);
dev_priv->last_gpu_reset = get_seconds(); dev_priv->gpu_error.last_reset = get_seconds();
if (ret) { if (ret) {
DRM_ERROR("Failed to reset chip.\n"); DRM_ERROR("Failed to reset chip.\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
...@@ -766,6 +766,28 @@ struct i915_gem_mm { ...@@ -766,6 +766,28 @@ struct i915_gem_mm {
u32 object_count; u32 object_count;
}; };
struct i915_gpu_error {
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
#define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
struct timer_list hangcheck_timer;
int hangcheck_count;
uint32_t last_acthd[I915_NUM_RINGS];
uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
/* For reset and error_state handling. */
spinlock_t lock;
/* Protected by the above dev->gpu_error.lock. */
struct drm_i915_error_state *first_error;
struct work_struct work;
struct completion completion;
unsigned long last_reset;
/* For gpu hang simulation. */
unsigned int stop_rings;
};
typedef struct drm_i915_private { typedef struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
struct kmem_cache *slab; struct kmem_cache *slab;
...@@ -829,16 +851,6 @@ typedef struct drm_i915_private { ...@@ -829,16 +851,6 @@ typedef struct drm_i915_private {
int num_pipe; int num_pipe;
int num_pch_pll; int num_pch_pll;
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
#define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
struct timer_list hangcheck_timer;
int hangcheck_count;
uint32_t last_acthd[I915_NUM_RINGS];
uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
unsigned int stop_rings;
unsigned long cfb_size; unsigned long cfb_size;
unsigned int cfb_fb; unsigned int cfb_fb;
enum plane cfb_plane; enum plane cfb_plane;
...@@ -886,11 +898,6 @@ typedef struct drm_i915_private { ...@@ -886,11 +898,6 @@ typedef struct drm_i915_private {
unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int fsb_freq, mem_freq, is_ddr3;
spinlock_t error_lock;
/* Protected by dev->error_lock. */
struct drm_i915_error_state *first_error;
struct work_struct error_work;
struct completion error_completion;
struct workqueue_struct *wq; struct workqueue_struct *wq;
/* Display functions */ /* Display functions */
...@@ -949,7 +956,7 @@ typedef struct drm_i915_private { ...@@ -949,7 +956,7 @@ typedef struct drm_i915_private {
struct drm_mm_node *compressed_fb; struct drm_mm_node *compressed_fb;
struct drm_mm_node *compressed_llb; struct drm_mm_node *compressed_llb;
unsigned long last_gpu_reset; struct i915_gpu_error gpu_error;
/* list of fbdev register on this device */ /* list of fbdev register on this device */
struct intel_fbdev *fbdev; struct intel_fbdev *fbdev;
......
...@@ -90,7 +90,7 @@ static int ...@@ -90,7 +90,7 @@ static int
i915_gem_wait_for_error(struct drm_device *dev) i915_gem_wait_for_error(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct completion *x = &dev_priv->error_completion; struct completion *x = &dev_priv->gpu_error.completion;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -943,7 +943,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv, ...@@ -943,7 +943,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv,
bool interruptible) bool interruptible)
{ {
if (atomic_read(&dev_priv->mm.wedged)) { if (atomic_read(&dev_priv->mm.wedged)) {
struct completion *x = &dev_priv->error_completion; struct completion *x = &dev_priv->gpu_error.completion;
bool recovery_complete; bool recovery_complete;
unsigned long flags; unsigned long flags;
...@@ -2045,7 +2045,7 @@ i915_add_request(struct intel_ring_buffer *ring, ...@@ -2045,7 +2045,7 @@ i915_add_request(struct intel_ring_buffer *ring,
if (!dev_priv->mm.suspended) { if (!dev_priv->mm.suspended) {
if (i915_enable_hangcheck) { if (i915_enable_hangcheck) {
mod_timer(&dev_priv->hangcheck_timer, mod_timer(&dev_priv->gpu_error.hangcheck_timer,
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES)); round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
} }
if (was_empty) { if (was_empty) {
...@@ -3803,7 +3803,7 @@ i915_gem_idle(struct drm_device *dev) ...@@ -3803,7 +3803,7 @@ i915_gem_idle(struct drm_device *dev)
* And not confound mm.suspended! * And not confound mm.suspended!
*/ */
dev_priv->mm.suspended = 1; dev_priv->mm.suspended = 1;
del_timer_sync(&dev_priv->hangcheck_timer); del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
i915_kernel_lost_context(dev); i915_kernel_lost_context(dev);
i915_gem_cleanup_ringbuffer(dev); i915_gem_cleanup_ringbuffer(dev);
...@@ -4064,7 +4064,7 @@ i915_gem_load(struct drm_device *dev) ...@@ -4064,7 +4064,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work, INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler); i915_gem_retire_work_handler);
init_completion(&dev_priv->error_completion); init_completion(&dev_priv->gpu_error.completion);
/* On GEN3 we really need to make sure the ARB C3 LP bit is set */ /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
if (IS_GEN3(dev)) { if (IS_GEN3(dev)) {
......
...@@ -356,8 +356,8 @@ static void notify_ring(struct drm_device *dev, ...@@ -356,8 +356,8 @@ static void notify_ring(struct drm_device *dev,
wake_up_all(&ring->irq_queue); wake_up_all(&ring->irq_queue);
if (i915_enable_hangcheck) { if (i915_enable_hangcheck) {
dev_priv->hangcheck_count = 0; dev_priv->gpu_error.hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer, mod_timer(&dev_priv->gpu_error.hangcheck_timer,
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES)); round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
} }
} }
...@@ -863,7 +863,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) ...@@ -863,7 +863,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
static void i915_error_work_func(struct work_struct *work) static void i915_error_work_func(struct work_struct *work)
{ {
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
error_work); gpu_error.work);
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
char *error_event[] = { "ERROR=1", NULL }; char *error_event[] = { "ERROR=1", NULL };
char *reset_event[] = { "RESET=1", NULL }; char *reset_event[] = { "RESET=1", NULL };
...@@ -878,7 +878,7 @@ static void i915_error_work_func(struct work_struct *work) ...@@ -878,7 +878,7 @@ static void i915_error_work_func(struct work_struct *work)
atomic_set(&dev_priv->mm.wedged, 0); atomic_set(&dev_priv->mm.wedged, 0);
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
} }
complete_all(&dev_priv->error_completion); complete_all(&dev_priv->gpu_error.completion);
} }
} }
...@@ -1255,9 +1255,9 @@ static void i915_capture_error_state(struct drm_device *dev) ...@@ -1255,9 +1255,9 @@ static void i915_capture_error_state(struct drm_device *dev)
unsigned long flags; unsigned long flags;
int i, pipe; int i, pipe;
spin_lock_irqsave(&dev_priv->error_lock, flags); spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error = dev_priv->first_error; error = dev_priv->gpu_error.first_error;
spin_unlock_irqrestore(&dev_priv->error_lock, flags); spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
if (error) if (error)
return; return;
...@@ -1341,12 +1341,12 @@ static void i915_capture_error_state(struct drm_device *dev) ...@@ -1341,12 +1341,12 @@ static void i915_capture_error_state(struct drm_device *dev)
error->overlay = intel_overlay_capture_error_state(dev); error->overlay = intel_overlay_capture_error_state(dev);
error->display = intel_display_capture_error_state(dev); error->display = intel_display_capture_error_state(dev);
spin_lock_irqsave(&dev_priv->error_lock, flags); spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
if (dev_priv->first_error == NULL) { if (dev_priv->gpu_error.first_error == NULL) {
dev_priv->first_error = error; dev_priv->gpu_error.first_error = error;
error = NULL; error = NULL;
} }
spin_unlock_irqrestore(&dev_priv->error_lock, flags); spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
if (error) if (error)
i915_error_state_free(&error->ref); i915_error_state_free(&error->ref);
...@@ -1358,10 +1358,10 @@ void i915_destroy_error_state(struct drm_device *dev) ...@@ -1358,10 +1358,10 @@ void i915_destroy_error_state(struct drm_device *dev)
struct drm_i915_error_state *error; struct drm_i915_error_state *error;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->error_lock, flags); spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error = dev_priv->first_error; error = dev_priv->gpu_error.first_error;
dev_priv->first_error = NULL; dev_priv->gpu_error.first_error = NULL;
spin_unlock_irqrestore(&dev_priv->error_lock, flags); spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
if (error) if (error)
kref_put(&error->ref, i915_error_state_free); kref_put(&error->ref, i915_error_state_free);
...@@ -1482,7 +1482,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged) ...@@ -1482,7 +1482,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
i915_report_and_clear_eir(dev); i915_report_and_clear_eir(dev);
if (wedged) { if (wedged) {
INIT_COMPLETION(dev_priv->error_completion); INIT_COMPLETION(dev_priv->gpu_error.completion);
atomic_set(&dev_priv->mm.wedged, 1); atomic_set(&dev_priv->mm.wedged, 1);
/* /*
...@@ -1492,7 +1492,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged) ...@@ -1492,7 +1492,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
wake_up_all(&ring->irq_queue); wake_up_all(&ring->irq_queue);
} }
queue_work(dev_priv->wq, &dev_priv->error_work); queue_work(dev_priv->wq, &dev_priv->gpu_error.work);
} }
static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
...@@ -1723,7 +1723,7 @@ static bool i915_hangcheck_hung(struct drm_device *dev) ...@@ -1723,7 +1723,7 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
if (dev_priv->hangcheck_count++ > 1) { if (dev_priv->gpu_error.hangcheck_count++ > 1) {
bool hung = true; bool hung = true;
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
...@@ -1782,25 +1782,29 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1782,25 +1782,29 @@ void i915_hangcheck_elapsed(unsigned long data)
goto repeat; goto repeat;
} }
dev_priv->hangcheck_count = 0; dev_priv->gpu_error.hangcheck_count = 0;
return; return;
} }
i915_get_extra_instdone(dev, instdone); i915_get_extra_instdone(dev, instdone);
if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 && if (memcmp(dev_priv->gpu_error.last_acthd, acthd,
memcmp(dev_priv->prev_instdone, instdone, sizeof(instdone)) == 0) { sizeof(acthd)) == 0 &&
memcmp(dev_priv->gpu_error.prev_instdone, instdone,
sizeof(instdone)) == 0) {
if (i915_hangcheck_hung(dev)) if (i915_hangcheck_hung(dev))
return; return;
} else { } else {
dev_priv->hangcheck_count = 0; dev_priv->gpu_error.hangcheck_count = 0;
memcpy(dev_priv->last_acthd, acthd, sizeof(acthd)); memcpy(dev_priv->gpu_error.last_acthd, acthd,
memcpy(dev_priv->prev_instdone, instdone, sizeof(instdone)); sizeof(acthd));
memcpy(dev_priv->gpu_error.prev_instdone, instdone,
sizeof(instdone));
} }
repeat: repeat:
/* Reset timer case chip hangs without another request being added */ /* Reset timer case chip hangs without another request being added */
mod_timer(&dev_priv->hangcheck_timer, mod_timer(&dev_priv->gpu_error.hangcheck_timer,
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES)); round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
} }
...@@ -2769,11 +2773,12 @@ void intel_irq_init(struct drm_device *dev) ...@@ -2769,11 +2773,12 @@ void intel_irq_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
INIT_WORK(&dev_priv->error_work, i915_error_work_func); INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);
INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work); INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, setup_timer(&dev_priv->gpu_error.hangcheck_timer,
i915_hangcheck_elapsed,
(unsigned long) dev); (unsigned long) dev);
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
......
...@@ -1491,7 +1491,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring) ...@@ -1491,7 +1491,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring)
struct drm_i915_private *dev_priv = ring->dev->dev_private; struct drm_i915_private *dev_priv = ring->dev->dev_private;
ring->tail &= ring->size - 1; ring->tail &= ring->size - 1;
if (dev_priv->stop_rings & intel_ring_flag(ring)) if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring))
return; return;
ring->write_tail(ring, ring->tail); ring->write_tail(ring, ring->tail);
} }
......
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