Skip to content

Commit

Permalink
drm/i915: extract hangcheck/reset/error_state state into substruct
Browse files Browse the repository at this point in the history
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: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Vetter committed Jan 20, 2013
1 parent 4b5aed6 commit 99584db
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 61 deletions.
10 changes: 5 additions & 5 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,11 +814,11 @@ static int i915_error_state_open(struct inode *inode, struct file *file)

error_priv->dev = dev;

spin_lock_irqsave(&dev_priv->error_lock, flags);
error_priv->error = dev_priv->first_error;
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error_priv->error = dev_priv->gpu_error.first_error;
if (error_priv->error)
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);
}
Expand Down Expand Up @@ -1727,7 +1727,7 @@ i915_ring_stop_read(struct file *filp,
int len;

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))
len = sizeof(buf);
Expand Down Expand Up @@ -1763,7 +1763,7 @@ i915_ring_stop_write(struct file *filp,
if (ret)
return ret;

dev_priv->stop_rings = val;
dev_priv->gpu_error.stop_rings = val;
mutex_unlock(&dev->struct_mutex);

return cnt;
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
pci_enable_msi(dev->pdev);

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);
mutex_init(&dev_priv->dpio_lock);

Expand Down Expand Up @@ -1725,8 +1725,8 @@ int i915_driver_unload(struct drm_device *dev)
}

/* Free error state after interrupts are fully disabled. */
del_timer_sync(&dev_priv->hangcheck_timer);
cancel_work_sync(&dev_priv->error_work);
del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
cancel_work_sync(&dev_priv->gpu_error.work);
i915_destroy_error_state(dev);

if (dev->pdev->msi_enabled)
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,9 @@ int intel_gpu_reset(struct drm_device *dev)
}

/* 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");
dev_priv->stop_rings = 0;
dev_priv->gpu_error.stop_rings = 0;
if (ret == -ENODEV) {
DRM_ERROR("Reset not implemented, but ignoring "
"error for simulated gpu hangs\n");
Expand Down Expand Up @@ -820,12 +820,12 @@ int i915_reset(struct drm_device *dev)
i915_gem_reset(dev);

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");
else
ret = intel_gpu_reset(dev);

dev_priv->last_gpu_reset = get_seconds();
dev_priv->gpu_error.last_reset = get_seconds();
if (ret) {
DRM_ERROR("Failed to reset chip.\n");
mutex_unlock(&dev->struct_mutex);
Expand Down
39 changes: 23 additions & 16 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,28 @@ struct i915_gem_mm {
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 {
struct drm_device *dev;
struct kmem_cache *slab;
Expand Down Expand Up @@ -829,16 +851,6 @@ typedef struct drm_i915_private {
int num_pipe;
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 int cfb_fb;
enum plane cfb_plane;
Expand Down Expand Up @@ -886,11 +898,6 @@ typedef struct drm_i915_private {

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;

/* Display functions */
Expand Down Expand Up @@ -949,7 +956,7 @@ typedef struct drm_i915_private {
struct drm_mm_node *compressed_fb;
struct drm_mm_node *compressed_llb;

unsigned long last_gpu_reset;
struct i915_gpu_error gpu_error;

/* list of fbdev register on this device */
struct intel_fbdev *fbdev;
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static int
i915_gem_wait_for_error(struct drm_device *dev)
{
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;
int ret;

Expand Down Expand Up @@ -943,7 +943,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv,
bool interruptible)
{
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;
unsigned long flags;

Expand Down Expand Up @@ -2045,7 +2045,7 @@ i915_add_request(struct intel_ring_buffer *ring,

if (!dev_priv->mm.suspended) {
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));
}
if (was_empty) {
Expand Down Expand Up @@ -3803,7 +3803,7 @@ i915_gem_idle(struct drm_device *dev)
* And not confound mm.suspended!
*/
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_gem_cleanup_ringbuffer(dev);
Expand Down Expand Up @@ -4064,7 +4064,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
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 */
if (IS_GEN3(dev)) {
Expand Down
59 changes: 32 additions & 27 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ static void notify_ring(struct drm_device *dev,

wake_up_all(&ring->irq_queue);
if (i915_enable_hangcheck) {
dev_priv->hangcheck_count = 0;
mod_timer(&dev_priv->hangcheck_timer,
dev_priv->gpu_error.hangcheck_count = 0;
mod_timer(&dev_priv->gpu_error.hangcheck_timer,
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
}
}
Expand Down Expand Up @@ -863,7 +863,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
static void i915_error_work_func(struct work_struct *work)
{
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;
char *error_event[] = { "ERROR=1", NULL };
char *reset_event[] = { "RESET=1", NULL };
Expand All @@ -878,7 +878,7 @@ static void i915_error_work_func(struct work_struct *work)
atomic_set(&dev_priv->mm.wedged, 0);
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);
}
}

Expand Down Expand Up @@ -1255,9 +1255,9 @@ static void i915_capture_error_state(struct drm_device *dev)
unsigned long flags;
int i, pipe;

spin_lock_irqsave(&dev_priv->error_lock, flags);
error = dev_priv->first_error;
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error = dev_priv->gpu_error.first_error;
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
if (error)
return;

Expand Down Expand Up @@ -1341,12 +1341,12 @@ static void i915_capture_error_state(struct drm_device *dev)
error->overlay = intel_overlay_capture_error_state(dev);
error->display = intel_display_capture_error_state(dev);

spin_lock_irqsave(&dev_priv->error_lock, flags);
if (dev_priv->first_error == NULL) {
dev_priv->first_error = error;
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
if (dev_priv->gpu_error.first_error == NULL) {
dev_priv->gpu_error.first_error = error;
error = NULL;
}
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);

if (error)
i915_error_state_free(&error->ref);
Expand All @@ -1358,10 +1358,10 @@ void i915_destroy_error_state(struct drm_device *dev)
struct drm_i915_error_state *error;
unsigned long flags;

spin_lock_irqsave(&dev_priv->error_lock, flags);
error = dev_priv->first_error;
dev_priv->first_error = NULL;
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
error = dev_priv->gpu_error.first_error;
dev_priv->gpu_error.first_error = NULL;
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);

if (error)
kref_put(&error->ref, i915_error_state_free);
Expand Down Expand Up @@ -1482,7 +1482,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
i915_report_and_clear_eir(dev);

if (wedged) {
INIT_COMPLETION(dev_priv->error_completion);
INIT_COMPLETION(dev_priv->gpu_error.completion);
atomic_set(&dev_priv->mm.wedged, 1);

/*
Expand All @@ -1492,7 +1492,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
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)
Expand Down Expand Up @@ -1723,7 +1723,7 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
{
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;

DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
Expand Down Expand Up @@ -1782,25 +1782,29 @@ void i915_hangcheck_elapsed(unsigned long data)
goto repeat;
}

dev_priv->hangcheck_count = 0;
dev_priv->gpu_error.hangcheck_count = 0;
return;
}

i915_get_extra_instdone(dev, instdone);
if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
memcmp(dev_priv->prev_instdone, instdone, sizeof(instdone)) == 0) {
if (memcmp(dev_priv->gpu_error.last_acthd, acthd,
sizeof(acthd)) == 0 &&
memcmp(dev_priv->gpu_error.prev_instdone, instdone,
sizeof(instdone)) == 0) {
if (i915_hangcheck_hung(dev))
return;
} else {
dev_priv->hangcheck_count = 0;
dev_priv->gpu_error.hangcheck_count = 0;

memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
memcpy(dev_priv->prev_instdone, instdone, sizeof(instdone));
memcpy(dev_priv->gpu_error.last_acthd, acthd,
sizeof(acthd));
memcpy(dev_priv->gpu_error.prev_instdone, instdone,
sizeof(instdone));
}

repeat:
/* 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));
}

Expand Down Expand Up @@ -2769,11 +2773,12 @@ void intel_irq_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;

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->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);

pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_ringbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring)
struct drm_i915_private *dev_priv = ring->dev->dev_private;

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;
ring->write_tail(ring, ring->tail);
}
Expand Down

0 comments on commit 99584db

Please sign in to comment.