summaryrefslogtreecommitdiff
path: root/shared-core/i915_irq.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-06-14 11:32:31 -0700
committerJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-06-14 11:32:31 -0700
commitb06268294afb47e62949984d73905344dd160262 (patch)
treea940aa9f4e2e9c55d4bc924176bad970958eee55 /shared-core/i915_irq.c
parent1a4b9294a29379ea6e9fd6fb315317f391232d4b (diff)
Comment new vblank routines and fixup several issues:
- use correct refcount variable in get/put routines - extract counter update from drm_vblank_get - make signal handling callback per-crtc - update interrupt handling logic, drivers should use drm_handle_vblank - move wakeup and counter update logic to new drm_handle_vblank routine - fixup usage of get/put in light of counter update extraction - fix longstanding bug in signal code, update pending counter only *after* we're sure we'll setup signal handling
Diffstat (limited to 'shared-core/i915_irq.c')
-rw-r--r--shared-core/i915_irq.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index 46b97e39..e91add9d 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -92,8 +92,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
unsigned long irqflags;
struct list_head *list, *tmp, hits, *hit;
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
- unsigned counter[2] = { atomic_read(&dev->vblank_count[0]),
- atomic_read(&dev->vblank_count[1]) };
+ unsigned counter[2];
drm_drawable_info_t *drw;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
u32 cpp = dev_priv->cpp, offsets[3];
@@ -105,6 +104,9 @@ static void i915_vblank_tasklet(drm_device_t *dev)
(cpp << 23) | (1 << 24);
RING_LOCALS;
+ counter[0] = drm_vblank_count(dev, 0);
+ counter[1] = drm_vblank_count(dev, 1);
+
DRM_DEBUG("\n");
INIT_LIST_HEAD(&hits);
@@ -333,16 +335,17 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
#endif
}
+ /*
+ * Use drm_update_vblank_counter here to deal with potential lost
+ * interrupts
+ */
if (temp & VSYNC_PIPEA_FLAG)
- atomic_add(i915_get_vblank_counter(dev, 0),
- &dev->vblank_count[0]);
+ drm_handle_vblank(dev, 0);
if (temp & VSYNC_PIPEB_FLAG)
- atomic_add(i915_get_vblank_counter(dev, 1),
- &dev->vblank_count[1]);
+ drm_handle_vblank(dev, 1);
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet);
@@ -477,12 +480,12 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
return i915_wait_irq(dev, irqwait.irq_seq);
}
-void i915_enable_vblank(drm_device_t *dev, int crtc)
+int i915_enable_vblank(drm_device_t *dev, int crtc)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- if (crtc > dev_priv->vblank_pipe)
- return;
+ if (dev_priv->vblank_pipe != (1 << crtc))
+ return -EINVAL;
switch (crtc) {
case 0:
@@ -498,6 +501,8 @@ void i915_enable_vblank(drm_device_t *dev, int crtc)
}
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+
+ return 0;
}
void i915_disable_vblank(drm_device_t *dev, int crtc)
@@ -597,6 +602,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
unsigned int pipe, seqtype, curseq;
unsigned long irqflags;
struct list_head *list;
+ int ret;
if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __func__);
@@ -637,8 +643,8 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- drm_vblank_get(dev, pipe);
- curseq = atomic_read(&dev->vblank_count[pipe]);
+ drm_update_vblank_count(dev, pipe);
+ curseq = drm_vblank_count(dev, pipe);
if (seqtype == _DRM_VBLANK_RELATIVE)
swap.sequence += curseq;
@@ -648,7 +654,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
swap.sequence = curseq + 1;
} else {
DRM_DEBUG("Missed target sequence\n");
- drm_vblank_put(dev, pipe);
return DRM_ERR(EINVAL);
}
}
@@ -669,7 +674,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("Invalid drawable ID %d\n",
swap.drawable);
- drm_vblank_put(dev, pipe);
return DRM_ERR(EINVAL);
}
@@ -677,7 +681,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- drm_vblank_put(dev, pipe);
return 0;
}
}
@@ -693,7 +696,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP);
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
DRM_DEBUG("Already scheduled\n");
- drm_vblank_put(dev, pipe);
return 0;
}
}
@@ -702,7 +704,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
if (dev_priv->swaps_pending >= 100) {
DRM_DEBUG("Too many swaps queued\n");
- drm_vblank_put(dev, pipe);
return DRM_ERR(EBUSY);
}
@@ -710,12 +711,15 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
if (!vbl_swap) {
DRM_ERROR("Failed to allocate memory to queue swap\n");
- drm_vblank_put(dev, pipe);
return DRM_ERR(ENOMEM);
}
DRM_DEBUG("\n");
+ ret = drm_vblank_get(dev, pipe);
+ if (ret)
+ return ret;
+
vbl_swap->drw_id = swap.drawable;
vbl_swap->pipe = pipe;
vbl_swap->sequence = swap.sequence;