aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <dumbbell@FreeBSD.org>2015-10-25 14:42:56 +0000
committerJean-Sébastien Pédron <dumbbell@FreeBSD.org>2015-10-25 14:42:56 +0000
commit170a938721f0372732404f002ca93a8e53aa055b (patch)
tree59379120b67ece35c09890547440be769c03591c /sys/dev
parentb5d5037b6cf355a3dcd3356dff1536cb78b6eabf (diff)
downloadsrc-170a938721f0372732404f002ca93a8e53aa055b.tar.gz
src-170a938721f0372732404f002ca93a8e53aa055b.zip
drm/i915: Reduce diff with Linux 3.8
There is no functional change. The goal is to ease the future update to Linux 3.8's i915 driver. MFC after: 2 months
Notes
Notes: svn path=/head/; revision=289934
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/drm2/i915/i915_irq.c1000
-rw-r--r--sys/dev/drm2/i915/intel_display.c161
2 files changed, 563 insertions, 598 deletions
diff --git a/sys/dev/drm2/i915/i915_irq.c b/sys/dev/drm2/i915/i915_irq.c
index ac89032994dc..d0b7e6205fa4 100644
--- a/sys/dev/drm2/i915/i915_irq.c
+++ b/sys/dev/drm2/i915/i915_irq.c
@@ -132,8 +132,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed a 'crtc', which
* we use as a pipe index
*/
-static u32
-i915_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long high_frame;
@@ -141,7 +140,7 @@ i915_get_vblank_counter(struct drm_device *dev, int pipe)
u32 high1, high2, low;
if (!i915_pipe_enabled(dev, pipe)) {
- DRM_DEBUG("trying to get vblank count for disabled "
+ DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
"pipe %c\n", pipe_name(pipe));
return 0;
}
@@ -165,14 +164,13 @@ i915_get_vblank_counter(struct drm_device *dev, int pipe)
return (high1 << 8) | low;
}
-static u32
-gm45_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int reg = PIPE_FRMCOUNT_GM45(pipe);
if (!i915_pipe_enabled(dev, pipe)) {
- DRM_DEBUG("i915: trying to get vblank count for disabled "
+ DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
"pipe %c\n", pipe_name(pipe));
return 0;
}
@@ -180,9 +178,8 @@ gm45_get_vblank_counter(struct drm_device *dev, int pipe)
return I915_READ(reg);
}
-static int
-i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
- int *vpos, int *hpos)
+static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+ int *vpos, int *hpos)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 vbl = 0, position = 0;
@@ -191,7 +188,7 @@ i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
int ret = 0;
if (!i915_pipe_enabled(dev, pipe)) {
- DRM_DEBUG("i915: trying to get scanoutpos for disabled "
+ DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
"pipe %c\n", pipe_name(pipe));
return 0;
}
@@ -247,9 +244,10 @@ i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
return ret;
}
-static int
-i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error,
- struct timeval *vblank_time, unsigned flags)
+static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
+ int *max_error,
+ struct timeval *vblank_time,
+ unsigned flags)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
@@ -268,7 +266,7 @@ i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error,
if (!crtc->enabled) {
#if 0
- DRM_DEBUG("crtc %d is disabled\n", pipe);
+ DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
#endif
return -EBUSY;
}
@@ -282,19 +280,14 @@ i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error,
/*
* Handle hotplug events outside the interrupt handler proper.
*/
-static void
-i915_hotplug_work_func(void *context, int pending)
+static void i915_hotplug_work_func(void *context, int pending)
{
drm_i915_private_t *dev_priv = context;
struct drm_device *dev = dev_priv->dev;
- struct drm_mode_config *mode_config;
+ struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *encoder;
DRM_DEBUG("running encoder hotplug functions\n");
- dev_priv = context;
- dev = dev_priv->dev;
-
- mode_config = &dev->mode_config;
sx_xlock(&mode_config->mutex);
DRM_DEBUG_KMS("running encoder hotplug functions\n");
@@ -350,29 +343,25 @@ static void notify_ring(struct drm_device *dev,
if (ring->obj == NULL)
return;
- CTR2(KTR_DRM, "request_complete %s %d", ring->name,
- ring->get_seqno(ring));
+ CTR2(KTR_DRM, "request_complete %s %d", ring->name, ring->get_seqno(ring));
mtx_lock(&dev_priv->irq_lock);
wakeup(ring);
mtx_unlock(&dev_priv->irq_lock);
-
if (i915_enable_hangcheck) {
dev_priv->hangcheck_count = 0;
callout_schedule(&dev_priv->hangcheck_timer,
- DRM_I915_HANGCHECK_PERIOD);
+ DRM_I915_HANGCHECK_PERIOD);
}
}
-static void
-gen6_pm_rps_work_func(void *arg, int pending)
+static void gen6_pm_rps_work(void *context, int pending)
{
struct drm_device *dev;
- drm_i915_private_t *dev_priv;
- u8 new_delay;
+ drm_i915_private_t *dev_priv = context;
u32 pm_iir, pm_imr;
+ u8 new_delay;
- dev_priv = (drm_i915_private_t *)arg;
dev = dev_priv->dev;
new_delay = dev_priv->cur_delay;
@@ -467,7 +456,7 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
taskqueue_enqueue(dev_priv->tq, &dev_priv->rps_task);
}
-static void valleyview_irq_handler(void *arg)
+static void valleyview_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -518,7 +507,7 @@ static void valleyview_irq_handler(void *arg)
hotplug_status);
if (hotplug_status & dev_priv->hotplug_supported_mask)
taskqueue_enqueue(dev_priv->tq,
- &dev_priv->hotplug_task);
+ &dev_priv->hotplug_task);
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
@@ -548,7 +537,8 @@ static void valleyview_irq_handler(void *arg)
I915_WRITE(VLV_IIR, iir);
}
-out:;
+out:
+ return;
}
static void pch_irq_handler(struct drm_device *dev, u32 pch_iir)
@@ -557,42 +547,41 @@ static void pch_irq_handler(struct drm_device *dev, u32 pch_iir)
int pipe;
if (pch_iir & SDE_AUDIO_POWER_MASK)
- DRM_DEBUG("i915: PCH audio power change on port %d\n",
+ DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK) >>
SDE_AUDIO_POWER_SHIFT);
if (pch_iir & SDE_GMBUS)
- DRM_DEBUG("i915: PCH GMBUS interrupt\n");
+ DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n");
if (pch_iir & SDE_AUDIO_HDCP_MASK)
- DRM_DEBUG("i915: PCH HDCP audio interrupt\n");
+ DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n");
if (pch_iir & SDE_AUDIO_TRANS_MASK)
- DRM_DEBUG("i915: PCH transcoder audio interrupt\n");
+ DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n");
if (pch_iir & SDE_POISON)
- DRM_ERROR("i915: PCH poison interrupt\n");
+ DRM_ERROR("PCH poison interrupt\n");
if (pch_iir & SDE_FDI_MASK)
for_each_pipe(pipe)
- DRM_DEBUG(" pipe %c FDI IIR: 0x%08x\n",
+ DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n",
pipe_name(pipe),
I915_READ(FDI_RX_IIR(pipe)));
if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
- DRM_DEBUG("i915: PCH transcoder CRC done interrupt\n");
+ DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
- DRM_DEBUG("i915: PCH transcoder CRC error interrupt\n");
+ DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
if (pch_iir & SDE_TRANSB_FIFO_UNDER)
- DRM_DEBUG("i915: PCH transcoder B underrun interrupt\n");
+ DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n");
if (pch_iir & SDE_TRANSA_FIFO_UNDER)
- DRM_DEBUG("PCH transcoder A underrun interrupt\n");
+ DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
}
-static void
-ivybridge_irq_handler(void *arg)
+static void ivybridge_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -606,7 +595,7 @@ ivybridge_irq_handler(void *arg)
I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
POSTING_READ(DEIER);
- gt_iir = I915_READ(GTIIR);
+ gt_iir = I915_READ(GTIIR);
if (gt_iir) {
snb_gt_irq_handler(dev, dev_priv, gt_iir);
I915_WRITE(GTIIR, gt_iir);
@@ -666,10 +655,9 @@ static void ilk_gt_irq_handler(struct drm_device *dev,
notify_ring(dev, &dev_priv->rings[VCS]);
}
-static void
-ironlake_irq_handler(void *arg)
+static void ironlake_irq_handler(DRM_IRQ_ARGS)
{
- struct drm_device *dev = arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
u32 hotplug_mask;
@@ -703,9 +691,8 @@ ironlake_irq_handler(void *arg)
else
snb_gt_irq_handler(dev, dev_priv, gt_iir);
- if (de_iir & DE_GSE) {
+ if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev);
- }
if (de_iir & DE_PLANEA_FLIP_DONE) {
intel_prepare_page_flip(dev, 0);
@@ -757,8 +744,7 @@ done:
* Fire an error uevent so userspace can see that a hang or error
* was detected.
*/
-static void
-i915_error_work_func(void *context, int pending)
+static void i915_error_work_func(void *context, int pending)
{
drm_i915_private_t *dev_priv = context;
struct drm_device *dev = dev_priv->dev;
@@ -766,7 +752,7 @@ i915_error_work_func(void *context, int pending)
/* kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); */
if (atomic_load_acq_int(&dev_priv->mm.wedged)) {
- DRM_DEBUG("i915: resetting chip\n");
+ DRM_DEBUG_DRIVER("resetting chip\n");
/* kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); */
if (!i915_reset(dev)) {
atomic_store_rel_int(&dev_priv->mm.wedged, 0);
@@ -779,6 +765,420 @@ i915_error_work_func(void *context, int pending)
}
}
+static struct drm_i915_error_object *
+i915_error_object_create(struct drm_i915_private *dev_priv,
+ struct drm_i915_gem_object *src)
+{
+ struct drm_i915_error_object *dst;
+ struct sf_buf *sf;
+ void *d, *s;
+ int page, page_count;
+ u32 reloc_offset;
+
+ if (src == NULL || src->pages == NULL)
+ return NULL;
+
+ page_count = src->base.size / PAGE_SIZE;
+
+ dst = malloc(sizeof(*dst) + page_count * sizeof(u32 *), DRM_I915_GEM,
+ M_NOWAIT);
+ if (dst == NULL)
+ return (NULL);
+
+ reloc_offset = src->gtt_offset;
+ for (page = 0; page < page_count; page++) {
+ d = malloc(PAGE_SIZE, DRM_I915_GEM, M_NOWAIT);
+ if (d == NULL)
+ goto unwind;
+
+ if (reloc_offset < dev_priv->mm.gtt_mappable_end &&
+ src->has_global_gtt_mapping) {
+ /* Simply ignore tiling or any overlapping fence.
+ * It's part of the error state, and this hopefully
+ * captures what the GPU read.
+ */
+ s = pmap_mapdev_attr(src->base.dev->agp->base +
+ reloc_offset, PAGE_SIZE, PAT_WRITE_COMBINING);
+ memcpy(d, s, PAGE_SIZE);
+ pmap_unmapdev((vm_offset_t)s, PAGE_SIZE);
+ } else {
+ drm_clflush_pages(&src->pages[page], 1);
+
+ sched_pin();
+ sf = sf_buf_alloc(src->pages[page], SFB_CPUPRIVATE |
+ SFB_NOWAIT);
+ if (sf != NULL) {
+ s = (void *)(uintptr_t)sf_buf_kva(sf);
+ memcpy(d, s, PAGE_SIZE);
+ sf_buf_free(sf);
+ } else {
+ bzero(d, PAGE_SIZE);
+ strcpy(d, "XXXKIB");
+ }
+ sched_unpin();
+
+ drm_clflush_pages(&src->pages[page], 1);
+ }
+
+ dst->pages[page] = d;
+
+ reloc_offset += PAGE_SIZE;
+ }
+ dst->page_count = page_count;
+ dst->gtt_offset = src->gtt_offset;
+
+ return dst;
+
+unwind:
+ while (page--)
+ free(dst->pages[page], DRM_I915_GEM);
+ free(dst, DRM_I915_GEM);
+ return NULL;
+}
+
+static void
+i915_error_object_free(struct drm_i915_error_object *obj)
+{
+ int page;
+
+ if (obj == NULL)
+ return;
+
+ for (page = 0; page < obj->page_count; page++)
+ free(obj->pages[page], DRM_I915_GEM);
+
+ free(obj, DRM_I915_GEM);
+}
+
+void
+i915_error_state_free(struct drm_i915_error_state *error)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
+ i915_error_object_free(error->ring[i].batchbuffer);
+ i915_error_object_free(error->ring[i].ringbuffer);
+ free(error->ring[i].requests, DRM_I915_GEM);
+ }
+
+ free(error->active_bo, DRM_I915_GEM);
+ free(error->overlay, DRM_I915_GEM);
+ free(error, DRM_I915_GEM);
+}
+
+static void capture_bo(struct drm_i915_error_buffer *err,
+ struct drm_i915_gem_object *obj)
+{
+ err->size = obj->base.size;
+ err->name = obj->base.name;
+ err->seqno = obj->last_rendering_seqno;
+ err->gtt_offset = obj->gtt_offset;
+ err->read_domains = obj->base.read_domains;
+ err->write_domain = obj->base.write_domain;
+ err->fence_reg = obj->fence_reg;
+ err->pinned = 0;
+ if (obj->pin_count > 0)
+ err->pinned = 1;
+ if (obj->user_pin_count > 0)
+ err->pinned = -1;
+ err->tiling = obj->tiling_mode;
+ err->dirty = obj->dirty;
+ err->purgeable = obj->madv != I915_MADV_WILLNEED;
+ err->ring = obj->ring ? obj->ring->id : -1;
+ err->cache_level = obj->cache_level;
+}
+
+static u32 capture_active_bo(struct drm_i915_error_buffer *err,
+ int count, struct list_head *head)
+{
+ struct drm_i915_gem_object *obj;
+ int i = 0;
+
+ list_for_each_entry(obj, head, mm_list) {
+ capture_bo(err++, obj);
+ if (++i == count)
+ break;
+ }
+
+ return i;
+}
+
+static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
+ int count, struct list_head *head)
+{
+ struct drm_i915_gem_object *obj;
+ int i = 0;
+
+ list_for_each_entry(obj, head, gtt_list) {
+ if (obj->pin_count == 0)
+ continue;
+
+ capture_bo(err++, obj);
+ if (++i == count)
+ break;
+ }
+
+ return i;
+}
+
+static void i915_gem_record_fences(struct drm_device *dev,
+ struct drm_i915_error_state *error)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ /* Fences */
+ switch (INTEL_INFO(dev)->gen) {
+ case 7:
+ case 6:
+ for (i = 0; i < 16; i++)
+ error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+ break;
+ case 5:
+ case 4:
+ for (i = 0; i < 16; i++)
+ error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+ break;
+ case 3:
+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+ for (i = 0; i < 8; i++)
+ error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+ case 2:
+ for (i = 0; i < 8; i++)
+ error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+ break;
+
+ }
+}
+
+static struct drm_i915_error_object *
+i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
+ struct intel_ring_buffer *ring)
+{
+ struct drm_i915_gem_object *obj;
+ u32 seqno;
+
+ if (!ring->get_seqno)
+ return NULL;
+
+ seqno = ring->get_seqno(ring);
+ list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
+ if (obj->ring != ring)
+ continue;
+
+ if (i915_seqno_passed(seqno, obj->last_rendering_seqno))
+ continue;
+
+ if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
+ continue;
+
+ /* We need to copy these to an anonymous buffer as the simplest
+ * method to avoid being overwritten by userspace.
+ */
+ return i915_error_object_create(dev_priv, obj);
+ }
+
+ return NULL;
+}
+
+static void i915_record_ring_state(struct drm_device *dev,
+ struct drm_i915_error_state *error,
+ struct intel_ring_buffer *ring)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (INTEL_INFO(dev)->gen >= 6) {
+ error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
+ error->semaphore_mboxes[ring->id][0]
+ = I915_READ(RING_SYNC_0(ring->mmio_base));
+ error->semaphore_mboxes[ring->id][1]
+ = I915_READ(RING_SYNC_1(ring->mmio_base));
+ }
+
+ if (INTEL_INFO(dev)->gen >= 4) {
+ error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
+ error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
+ error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
+ error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
+ error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
+ if (ring->id == RCS) {
+ error->instdone1 = I915_READ(INSTDONE1);
+ error->bbaddr = I915_READ64(BB_ADDR);
+ }
+ } else {
+ error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
+ error->ipeir[ring->id] = I915_READ(IPEIR);
+ error->ipehr[ring->id] = I915_READ(IPEHR);
+ error->instdone[ring->id] = I915_READ(INSTDONE);
+ }
+
+ sleepq_lock(ring);
+ error->waiting[ring->id] = sleepq_sleepcnt(ring, 0) != 0;
+ sleepq_release(ring);
+ error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
+ error->seqno[ring->id] = ring->get_seqno(ring);
+ error->acthd[ring->id] = intel_ring_get_active_head(ring);
+ error->head[ring->id] = I915_READ_HEAD(ring);
+ error->tail[ring->id] = I915_READ_TAIL(ring);
+
+ error->cpu_ring_head[ring->id] = ring->head;
+ error->cpu_ring_tail[ring->id] = ring->tail;
+}
+
+static void i915_gem_record_rings(struct drm_device *dev,
+ struct drm_i915_error_state *error)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring;
+ struct drm_i915_gem_request *request;
+ int i, count;
+
+ for_each_ring(ring, dev_priv, i) {
+ i915_record_ring_state(dev, error, ring);
+
+ error->ring[i].batchbuffer =
+ i915_error_first_batchbuffer(dev_priv, ring);
+
+ error->ring[i].ringbuffer =
+ i915_error_object_create(dev_priv, ring->obj);
+
+ count = 0;
+ list_for_each_entry(request, &ring->request_list, list)
+ count++;
+
+ error->ring[i].num_requests = count;
+ error->ring[i].requests =
+ malloc(count*sizeof(struct drm_i915_error_request),
+ DRM_I915_GEM, M_WAITOK);
+ if (error->ring[i].requests == NULL) {
+ error->ring[i].num_requests = 0;
+ continue;
+ }
+
+ count = 0;
+ list_for_each_entry(request, &ring->request_list, list) {
+ struct drm_i915_error_request *erq;
+
+ erq = &error->ring[i].requests[count++];
+ erq->seqno = request->seqno;
+ erq->jiffies = request->emitted_jiffies;
+ erq->tail = request->tail;
+ }
+ }
+}
+
+static void i915_capture_error_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj;
+ struct drm_i915_error_state *error;
+ int i, pipe;
+
+ mtx_lock(&dev_priv->error_lock);
+ error = dev_priv->first_error;
+ mtx_unlock(&dev_priv->error_lock);
+ if (error)
+ return;
+
+ /* Account for pipe specific data like PIPE*STAT */
+ error = malloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT | M_ZERO);
+ if (!error) {
+ DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
+ return;
+ }
+
+ DRM_INFO("capturing error event; look for more information in sysctl hw.dri.%d.info.i915_error_state\n",
+ dev->sysctl_node_idx);
+
+ refcount_init(&error->ref, 1);
+ error->eir = I915_READ(EIR);
+ error->pgtbl_er = I915_READ(PGTBL_ER);
+
+ if (HAS_PCH_SPLIT(dev))
+ error->ier = I915_READ(DEIER) | I915_READ(GTIER);
+ else if (IS_VALLEYVIEW(dev))
+ error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+ else if (IS_GEN2(dev))
+ error->ier = I915_READ16(IER);
+ else
+ error->ier = I915_READ(IER);
+
+ for_each_pipe(pipe)
+ error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
+
+ if (INTEL_INFO(dev)->gen >= 6) {
+ error->error = I915_READ(ERROR_GEN6);
+ error->done_reg = I915_READ(DONE_REG);
+ }
+
+ i915_gem_record_fences(dev, error);
+ i915_gem_record_rings(dev, error);
+
+ /* Record buffers on the active and pinned lists. */
+ error->active_bo = NULL;
+ error->pinned_bo = NULL;
+
+ i = 0;
+ list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
+ i++;
+ error->active_bo_count = i;
+ list_for_each_entry(obj, &dev_priv->mm.gtt_list, mm_list)
+ if (obj->pin_count)
+ i++;
+ error->pinned_bo_count = i - error->active_bo_count;
+
+ error->active_bo = NULL;
+ error->pinned_bo = NULL;
+ if (i) {
+ error->active_bo = malloc(sizeof(*error->active_bo)*i,
+ DRM_I915_GEM, M_NOWAIT);
+ if (error->active_bo)
+ error->pinned_bo =
+ error->active_bo + error->active_bo_count;
+ }
+
+ if (error->active_bo)
+ error->active_bo_count =
+ capture_active_bo(error->active_bo,
+ error->active_bo_count,
+ &dev_priv->mm.active_list);
+
+ if (error->pinned_bo)
+ error->pinned_bo_count =
+ capture_pinned_bo(error->pinned_bo,
+ error->pinned_bo_count,
+ &dev_priv->mm.gtt_list);
+
+ microtime(&error->time);
+
+ error->overlay = intel_overlay_capture_error_state(dev);
+ error->display = intel_display_capture_error_state(dev);
+
+ mtx_lock(&dev_priv->error_lock);
+ if (dev_priv->first_error == NULL) {
+ dev_priv->first_error = error;
+ error = NULL;
+ }
+ mtx_unlock(&dev_priv->error_lock);
+
+ if (error)
+ i915_error_state_free(error);
+}
+
+void i915_destroy_error_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_error_state *error;
+
+ mtx_lock(&dev_priv->error_lock);
+ error = dev_priv->first_error;
+ dev_priv->first_error = NULL;
+ mtx_unlock(&dev_priv->error_lock);
+
+ if (error && refcount_release(&error->ref))
+ i915_error_state_free(error);
+}
+
#define pr_err(...) printf(__VA_ARGS__)
static void i915_report_and_clear_eir(struct drm_device *dev)
@@ -928,7 +1328,9 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
mtx_lock(&dev->event_lock);
work = intel_crtc->unpin_work;
- if (work == NULL || work->pending || !work->enable_stall_check) {
+ if (work == NULL ||
+ work->pending ||
+ !work->enable_stall_check) {
/* Either the pending flip IRQ arrived, or we're too early. Don't check */
mtx_unlock(&dev->event_lock);
return;
@@ -950,7 +1352,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
mtx_unlock(&dev->event_lock);
if (stall_detected) {
- DRM_DEBUG("Pageflip stall detected\n");
+ DRM_DEBUG_DRIVER("Pageflip stall detected\n");
intel_prepare_page_flip(dev, intel_crtc->plane);
}
}
@@ -958,8 +1360,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
-static int
-i915_enable_vblank(struct drm_device *dev, int pipe)
+static int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -983,8 +1384,7 @@ i915_enable_vblank(struct drm_device *dev, int pipe)
return 0;
}
-static int
-ironlake_enable_vblank(struct drm_device *dev, int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -993,15 +1393,14 @@ ironlake_enable_vblank(struct drm_device *dev, int pipe)
mtx_lock(&dev_priv->irq_lock);
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
- DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
+ DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
mtx_unlock(&dev_priv->irq_lock);
CTR1(KTR_DRM, "ironlake_enable_vblank %d", pipe);
return 0;
}
-static int
-ivybridge_enable_vblank(struct drm_device *dev, int pipe)
+static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1045,8 +1444,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
-static void
-i915_disable_vblank(struct drm_device *dev, int pipe)
+static void i915_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1055,26 +1453,24 @@ i915_disable_vblank(struct drm_device *dev, int pipe)
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
i915_disable_pipestat(dev_priv, pipe,
- PIPE_VBLANK_INTERRUPT_ENABLE |
- PIPE_START_VBLANK_INTERRUPT_ENABLE);
+ PIPE_VBLANK_INTERRUPT_ENABLE |
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
mtx_unlock(&dev_priv->irq_lock);
CTR1(KTR_DRM, "i915_disable_vblank %d", pipe);
}
-static void
-ironlake_disable_vblank(struct drm_device *dev, int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
mtx_lock(&dev_priv->irq_lock);
ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
- DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
+ DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
mtx_unlock(&dev_priv->irq_lock);
CTR1(KTR_DRM, "ironlake_disable_vblank %d", pipe);
}
-static void
-ivybridge_disable_vblank(struct drm_device *dev, int pipe)
+static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1119,7 +1515,8 @@ ring_last_seqno(struct intel_ring_buffer *ring)
static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
{
if (list_empty(&ring->request_list) ||
- i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
+ i915_seqno_passed(ring->get_seqno(ring),
+ ring_last_seqno(ring))) {
/* Issue a wake-up to catch stuck h/w. */
sleepq_lock(ring);
if (sleepq_sleepcnt(ring, 0) != 0) {
@@ -1184,10 +1581,9 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
* ACTHD. If ACTHD hasn't changed by the time the hangcheck timer elapses
* again, we assume the chip is wedged and try to fix it.
*/
-void
-i915_hangcheck_elapsed(void *context)
+void i915_hangcheck_elapsed(void *data)
{
- struct drm_device *dev = (struct drm_device *)context;
+ struct drm_device *dev = (struct drm_device *)data;
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
struct intel_ring_buffer *ring;
@@ -1244,8 +1640,7 @@ repeat:
/* drm_dma.h hooks
*/
-static void
-ironlake_irq_preinstall(struct drm_device *dev)
+static void ironlake_irq_preinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1389,8 +1784,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
return 0;
}
-static int
-ivybridge_irq_postinstall(struct drm_device *dev)
+static int ivybridge_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
/* enable kind of interrupts always enabled */
@@ -1545,12 +1939,11 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
POSTING_READ(VLV_IER);
}
-static void
-ironlake_irq_uninstall(struct drm_device *dev)
+static void ironlake_irq_uninstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- if (dev_priv == NULL)
+ if (!dev_priv)
return;
I915_WRITE(HWSTAM, 0xffffffff);
@@ -1572,11 +1965,11 @@ static void i8xx_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int pipe;
-
+
atomic_set(&dev_priv->irq_received, 0);
-
- for_each_pipe(pipe)
- I915_WRITE(PIPESTAT(pipe), 0);
+
+ for_each_pipe(pipe)
+ I915_WRITE(PIPESTAT(pipe), 0);
I915_WRITE16(IMR, 0xffff);
I915_WRITE16(IER, 0x0);
POSTING_READ16(IER);
@@ -1611,7 +2004,7 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
return 0;
}
-static void i8xx_irq_handler(void *arg)
+static void i8xx_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1786,7 +2179,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
return 0;
}
-static void i915_irq_handler(void *arg)
+static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1843,7 +2236,7 @@ static void i915_irq_handler(void *arg)
hotplug_status);
if (hotplug_status & dev_priv->hotplug_supported_mask)
taskqueue_enqueue(dev_priv->tq,
- &dev_priv->hotplug_task);
+ &dev_priv->hotplug_task);
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
POSTING_READ(PORT_HOTPLUG_STAT);
@@ -2027,7 +2420,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
return 0;
}
-static void i965_irq_handler(void *arg)
+static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2083,7 +2476,7 @@ static void i965_irq_handler(void *arg)
hotplug_status);
if (hotplug_status & dev_priv->hotplug_supported_mask)
taskqueue_enqueue(dev_priv->tq,
- &dev_priv->hotplug_task);
+ &dev_priv->hotplug_task);
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
@@ -2169,7 +2562,7 @@ void intel_irq_init(struct drm_device *dev)
dev->dev_private);
TASK_INIT(&dev_priv->error_task, 0, i915_error_work_func,
dev->dev_private);
- TASK_INIT(&dev_priv->rps_task, 0, gen6_pm_rps_work_func,
+ TASK_INIT(&dev_priv->rps_task, 0, gen6_pm_rps_work,
dev->dev_private);
dev->driver->get_vblank_counter = i915_get_vblank_counter;
@@ -2238,424 +2631,3 @@ void intel_irq_init(struct drm_device *dev)
dev->driver->disable_vblank = i915_disable_vblank;
}
}
-
-static struct drm_i915_error_object *
-i915_error_object_create(struct drm_i915_private *dev_priv,
- struct drm_i915_gem_object *src)
-{
- struct drm_i915_error_object *dst;
- struct sf_buf *sf;
- void *d, *s;
- int page, page_count;
- u32 reloc_offset;
-
- if (src == NULL || src->pages == NULL)
- return NULL;
-
- page_count = src->base.size / PAGE_SIZE;
-
- dst = malloc(sizeof(*dst) + page_count * sizeof(u32 *), DRM_I915_GEM,
- M_NOWAIT);
- if (dst == NULL)
- return (NULL);
-
- reloc_offset = src->gtt_offset;
- for (page = 0; page < page_count; page++) {
- d = malloc(PAGE_SIZE, DRM_I915_GEM, M_NOWAIT);
- if (d == NULL)
- goto unwind;
-
- if (reloc_offset < dev_priv->mm.gtt_mappable_end &&
- src->has_global_gtt_mapping) {
- /* Simply ignore tiling or any overlapping fence.
- * It's part of the error state, and this hopefully
- * captures what the GPU read.
- */
- s = pmap_mapdev_attr(src->base.dev->agp->base +
- reloc_offset, PAGE_SIZE, PAT_WRITE_COMBINING);
- memcpy(d, s, PAGE_SIZE);
- pmap_unmapdev((vm_offset_t)s, PAGE_SIZE);
- } else {
- drm_clflush_pages(&src->pages[page], 1);
-
- sched_pin();
- sf = sf_buf_alloc(src->pages[page], SFB_CPUPRIVATE |
- SFB_NOWAIT);
- if (sf != NULL) {
- s = (void *)(uintptr_t)sf_buf_kva(sf);
- memcpy(d, s, PAGE_SIZE);
- sf_buf_free(sf);
- } else {
- bzero(d, PAGE_SIZE);
- strcpy(d, "XXXKIB");
- }
- sched_unpin();
-
- drm_clflush_pages(&src->pages[page], 1);
- }
-
- dst->pages[page] = d;
-
- reloc_offset += PAGE_SIZE;
- }
- dst->page_count = page_count;
- dst->gtt_offset = src->gtt_offset;
-
- return (dst);
-
-unwind:
- while (page--)
- free(dst->pages[page], DRM_I915_GEM);
- free(dst, DRM_I915_GEM);
- return (NULL);
-}
-
-static void
-i915_error_object_free(struct drm_i915_error_object *obj)
-{
- int page;
-
- if (obj == NULL)
- return;
-
- for (page = 0; page < obj->page_count; page++)
- free(obj->pages[page], DRM_I915_GEM);
-
- free(obj, DRM_I915_GEM);
-}
-
-void
-i915_error_state_free(struct drm_i915_error_state *error)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
- i915_error_object_free(error->ring[i].batchbuffer);
- i915_error_object_free(error->ring[i].ringbuffer);
- free(error->ring[i].requests, DRM_I915_GEM);
- }
-
- free(error->active_bo, DRM_I915_GEM);
- free(error->overlay, DRM_I915_GEM);
- free(error, DRM_I915_GEM);
-}
-
-static void capture_bo(struct drm_i915_error_buffer *err,
- struct drm_i915_gem_object *obj)
-{
- err->size = obj->base.size;
- err->name = obj->base.name;
- err->seqno = obj->last_rendering_seqno;
- err->gtt_offset = obj->gtt_offset;
- err->read_domains = obj->base.read_domains;
- err->write_domain = obj->base.write_domain;
- err->fence_reg = obj->fence_reg;
- err->pinned = 0;
- if (obj->pin_count > 0)
- err->pinned = 1;
- if (obj->user_pin_count > 0)
- err->pinned = -1;
- err->tiling = obj->tiling_mode;
- err->dirty = obj->dirty;
- err->purgeable = obj->madv != I915_MADV_WILLNEED;
- err->ring = obj->ring ? obj->ring->id : -1;
- err->cache_level = obj->cache_level;
-}
-
-static u32 capture_active_bo(struct drm_i915_error_buffer *err,
- int count, struct list_head *head)
-{
- struct drm_i915_gem_object *obj;
- int i = 0;
-
- list_for_each_entry(obj, head, mm_list) {
- capture_bo(err++, obj);
- if (++i == count)
- break;
- }
-
- return i;
-}
-
-static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
- int count, struct list_head *head)
-{
- struct drm_i915_gem_object *obj;
- int i = 0;
-
- list_for_each_entry(obj, head, gtt_list) {
- if (obj->pin_count == 0)
- continue;
-
- capture_bo(err++, obj);
- if (++i == count)
- break;
- }
-
- return i;
-}
-
-static void
-i915_gem_record_fences(struct drm_device *dev,
- struct drm_i915_error_state *error)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int i;
-
- /* Fences */
- switch (INTEL_INFO(dev)->gen) {
- case 7:
- case 6:
- for (i = 0; i < 16; i++)
- error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
- break;
- case 5:
- case 4:
- for (i = 0; i < 16; i++)
- error->fence[i] = I915_READ64(FENCE_REG_965_0 +
- (i * 8));
- break;
- case 3:
- if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
- for (i = 0; i < 8; i++)
- error->fence[i+8] = I915_READ(FENCE_REG_945_8 +
- (i * 4));
- case 2:
- for (i = 0; i < 8; i++)
- error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
- break;
-
- }
-}
-
-static struct drm_i915_error_object *
-i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
- struct intel_ring_buffer *ring)
-{
- struct drm_i915_gem_object *obj;
- u32 seqno;
-
- if (!ring->get_seqno)
- return (NULL);
-
- seqno = ring->get_seqno(ring);
- list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
- if (obj->ring != ring)
- continue;
-
- if (i915_seqno_passed(seqno, obj->last_rendering_seqno))
- continue;
-
- if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
- continue;
-
- /* We need to copy these to an anonymous buffer as the simplest
- * method to avoid being overwritten by userspace.
- */
- return (i915_error_object_create(dev_priv, obj));
- }
-
- return NULL;
-}
-
-static void
-i915_record_ring_state(struct drm_device *dev,
- struct drm_i915_error_state *error,
- struct intel_ring_buffer *ring)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (INTEL_INFO(dev)->gen >= 6) {
- error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
- error->semaphore_mboxes[ring->id][0]
- = I915_READ(RING_SYNC_0(ring->mmio_base));
- error->semaphore_mboxes[ring->id][1]
- = I915_READ(RING_SYNC_1(ring->mmio_base));
- }
-
- if (INTEL_INFO(dev)->gen >= 4) {
- error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
- error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
- error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
- error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
- error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
- if (ring->id == RCS) {
- error->instdone1 = I915_READ(INSTDONE1);
- error->bbaddr = I915_READ64(BB_ADDR);
- }
- } else {
- error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
- error->ipeir[ring->id] = I915_READ(IPEIR);
- error->ipehr[ring->id] = I915_READ(IPEHR);
- error->instdone[ring->id] = I915_READ(INSTDONE);
- }
-
- sleepq_lock(ring);
- error->waiting[ring->id] = sleepq_sleepcnt(ring, 0) != 0;
- sleepq_release(ring);
- error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
- error->seqno[ring->id] = ring->get_seqno(ring);
- error->acthd[ring->id] = intel_ring_get_active_head(ring);
- error->head[ring->id] = I915_READ_HEAD(ring);
- error->tail[ring->id] = I915_READ_TAIL(ring);
-
- error->cpu_ring_head[ring->id] = ring->head;
- error->cpu_ring_tail[ring->id] = ring->tail;
-}
-
-static void
-i915_gem_record_rings(struct drm_device *dev,
- struct drm_i915_error_state *error)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_ring_buffer *ring;
- struct drm_i915_gem_request *request;
- int i, count;
-
- for_each_ring(ring, dev_priv, i) {
- i915_record_ring_state(dev, error, ring);
-
- error->ring[i].batchbuffer =
- i915_error_first_batchbuffer(dev_priv, ring);
-
- error->ring[i].ringbuffer =
- i915_error_object_create(dev_priv, ring->obj);
-
- count = 0;
- list_for_each_entry(request, &ring->request_list, list)
- count++;
-
- error->ring[i].num_requests = count;
- error->ring[i].requests = malloc(count *
- sizeof(struct drm_i915_error_request), DRM_I915_GEM,
- M_WAITOK);
- if (error->ring[i].requests == NULL) {
- error->ring[i].num_requests = 0;
- continue;
- }
-
- count = 0;
- list_for_each_entry(request, &ring->request_list, list) {
- struct drm_i915_error_request *erq;
-
- erq = &error->ring[i].requests[count++];
- erq->seqno = request->seqno;
- erq->jiffies = request->emitted_jiffies;
- erq->tail = request->tail;
- }
- }
-}
-
-static void
-i915_capture_error_state(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_i915_gem_object *obj;
- struct drm_i915_error_state *error;
- int i, pipe;
-
- mtx_lock(&dev_priv->error_lock);
- error = dev_priv->first_error;
- mtx_unlock(&dev_priv->error_lock);
- if (error != NULL)
- return;
-
- /* Account for pipe specific data like PIPE*STAT */
- error = malloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT | M_ZERO);
- if (error == NULL) {
- DRM_DEBUG("out of memory, not capturing error state\n");
- return;
- }
-
- DRM_INFO("capturing error event; look for more information in "
- "sysctl hw.dri.%d.info.i915_error_state\n", dev->sysctl_node_idx);
-
- refcount_init(&error->ref, 1);
- error->eir = I915_READ(EIR);
- error->pgtbl_er = I915_READ(PGTBL_ER);
-
- if (HAS_PCH_SPLIT(dev))
- error->ier = I915_READ(DEIER) | I915_READ(GTIER);
- else if (IS_VALLEYVIEW(dev))
- error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
- else if (IS_GEN2(dev))
- error->ier = I915_READ16(IER);
- else
- error->ier = I915_READ(IER);
-
- for_each_pipe(pipe)
- error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
-
- if (INTEL_INFO(dev)->gen >= 6) {
- error->error = I915_READ(ERROR_GEN6);
- error->done_reg = I915_READ(DONE_REG);
- }
-
- i915_gem_record_fences(dev, error);
- i915_gem_record_rings(dev, error);
-
- /* Record buffers on the active and pinned lists. */
- error->active_bo = NULL;
- error->pinned_bo = NULL;
-
- i = 0;
- list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
- i++;
- error->active_bo_count = i;
- list_for_each_entry(obj, &dev_priv->mm.gtt_list, mm_list)
- if (obj->pin_count)
- i++;
- error->pinned_bo_count = i - error->active_bo_count;
-
- error->active_bo = NULL;
- error->pinned_bo = NULL;
- if (i) {
- error->active_bo = malloc(sizeof(*error->active_bo) * i,
- DRM_I915_GEM, M_NOWAIT);
- if (error->active_bo)
- error->pinned_bo = error->active_bo +
- error->active_bo_count;
- }
-
- if (error->active_bo)
- error->active_bo_count =
- capture_active_bo(error->active_bo,
- error->active_bo_count,
- &dev_priv->mm.active_list);
-
- if (error->pinned_bo)
- error->pinned_bo_count =
- capture_pinned_bo(error->pinned_bo,
- error->pinned_bo_count,
- &dev_priv->mm.gtt_list);
-
- microtime(&error->time);
-
- error->overlay = intel_overlay_capture_error_state(dev);
- error->display = intel_display_capture_error_state(dev);
-
- mtx_lock(&dev_priv->error_lock);
- if (dev_priv->first_error == NULL) {
- dev_priv->first_error = error;
- error = NULL;
- }
- mtx_unlock(&dev_priv->error_lock);
-
- if (error != NULL)
- i915_error_state_free(error);
-}
-
-void
-i915_destroy_error_state(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_i915_error_state *error;
-
- mtx_lock(&dev_priv->error_lock);
- error = dev_priv->first_error;
- dev_priv->first_error = NULL;
- mtx_unlock(&dev_priv->error_lock);
-
- if (error != NULL && refcount_release(&error->ref))
- i915_error_state_free(error);
-}
diff --git a/sys/dev/drm2/i915/intel_display.c b/sys/dev/drm2/i915/intel_display.c
index 93b94be4b0c3..b360380d67f3 100644
--- a/sys/dev/drm2/i915/intel_display.c
+++ b/sys/dev/drm2/i915/intel_display.c
@@ -929,7 +929,8 @@ static void assert_pll(struct drm_i915_private *dev_priv,
/* For ILK+ */
static void assert_pch_pll(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc, bool state)
+ struct intel_crtc *intel_crtc,
+ bool state)
{
int reg;
u32 val;
@@ -1174,6 +1175,24 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
pipe_name(pipe));
}
+static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
+ enum pipe pipe, u32 port_sel, u32 val)
+{
+ if ((val & DP_PORT_EN) == 0)
+ return false;
+
+ if (HAS_PCH_CPT(dev_priv->dev)) {
+ u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
+ u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
+ if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
+ return false;
+ } else {
+ if ((val & DP_PIPE_MASK) != (pipe << 30))
+ return false;
+ }
+ return true;
+}
+
static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv,
enum pipe pipe, u32 val)
{
@@ -1221,24 +1240,6 @@ static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
return true;
}
-static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
- enum pipe pipe, u32 port_sel, u32 val)
-{
- if ((val & DP_PORT_EN) == 0)
- return false;
-
- if (HAS_PCH_CPT(dev_priv->dev)) {
- u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
- u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
- if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
- return false;
- } else {
- if ((val & DP_PIPE_MASK) != (pipe << 30))
- return false;
- }
- return true;
-}
-
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe, int reg, u32 port_sel)
{
@@ -1357,16 +1358,13 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value)
{
mtx_lock(&dev_priv->dpio_lock);
- if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
- 100)) {
+ if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, 100)) {
DRM_ERROR("timeout waiting for SBI to become ready\n");
goto out_unlock;
}
- I915_WRITE(SBI_ADDR,
- (reg << 16));
- I915_WRITE(SBI_DATA,
- value);
+ I915_WRITE(SBI_ADDR, (reg << 16));
+ I915_WRITE(SBI_DATA, value);
I915_WRITE(SBI_CTL_STAT,
SBI_BUSY |
SBI_CTL_OP_CRWR);
@@ -1388,14 +1386,12 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg)
value = 0;
mtx_lock(&dev_priv->dpio_lock);
- if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
- 100)) {
+ if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, 100)) {
DRM_ERROR("timeout waiting for SBI to become ready\n");
goto out_unlock;
}
- I915_WRITE(SBI_ADDR,
- (reg << 16));
+ I915_WRITE(SBI_ADDR, (reg << 16));
I915_WRITE(SBI_CTL_STAT,
SBI_BUSY |
SBI_CTL_OP_CRRD);
@@ -1913,7 +1909,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
I915_WRITE(DSPADDR(plane), Start + Offset);
POSTING_READ(reg);
- return (0);
+ return 0;
}
static int ironlake_update_plane(struct drm_crtc *crtc,
@@ -2029,7 +2025,7 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
msleep(&obj->pending_flip, &dev->event_lock,
0, "915flp", 0);
}
- mtx_unlock(&dev->event_lock);
+ mtx_unlock(&dev->event_lock);
/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
@@ -2042,6 +2038,7 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
dev_priv->mm.interruptible = false;
ret = i915_gem_object_finish_gpu(obj);
dev_priv->mm.interruptible = was_interruptible;
+
return ret;
}
@@ -2738,8 +2735,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
/* Disable SSCCTL */
intel_sbi_write(dev_priv, SBI_SSCCTL6,
- intel_sbi_read(dev_priv, SBI_SSCCTL6) |
- SBI_SSCCTL_DISABLE);
+ intel_sbi_read(dev_priv, SBI_SSCCTL6) |
+ SBI_SSCCTL_DISABLE);
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
if (crtc->mode.clock == 20000) {
@@ -2790,25 +2787,18 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
- intel_sbi_write(dev_priv,
- SBI_SSCDIVINTPHASE6,
- temp);
+ intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp);
/* Program SSCAUXDIV */
temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6);
temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
- intel_sbi_write(dev_priv,
- SBI_SSCAUXDIV6,
- temp);
-
+ intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp);
/* Enable modulator and associated divider */
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6);
temp &= ~SBI_SSCCTL_DISABLE;
- intel_sbi_write(dev_priv,
- SBI_SSCCTL6,
- temp);
+ intel_sbi_write(dev_priv, SBI_SSCCTL6, temp);
/* Wait for initialization time */
DELAY(24);
@@ -3053,10 +3043,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
is_pch_port = intel_crtc_driving_pch(crtc);
- if (is_pch_port)
+ if (is_pch_port) {
ironlake_fdi_pll_enable(crtc);
- else
+ } else {
ironlake_fdi_disable(crtc);
+ }
/* Enable panel fitting for LVDS */
if (dev_priv->pch_pf_size &&
@@ -3687,7 +3678,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
display_bpc = min(display_bpc, bpc);
DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
- bpc, display_bpc);
+ bpc, display_bpc);
*pipe_bpp = display_bpc * 3;
@@ -4609,8 +4600,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
pipe);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
} else
intel_put_pch_pll(intel_crtc);
@@ -5309,8 +5300,9 @@ static struct drm_display_mode load_detect_mode = {
static int
intel_framebuffer_create(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj,
- struct drm_framebuffer **res)
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_i915_gem_object *obj,
+ struct drm_framebuffer **res)
{
struct intel_framebuffer *intel_fb;
int ret;
@@ -5320,11 +5312,11 @@ intel_framebuffer_create(struct drm_device *dev,
if (ret) {
drm_gem_object_unreference_unlocked(&obj->base);
free(intel_fb, DRM_MEM_KMS);
- return (ret);
+ return ret;
}
*res = &intel_fb->base;
- return (0);
+ return 0;
}
static u32
@@ -5343,16 +5335,17 @@ intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
static int
intel_framebuffer_create_for_mode(struct drm_device *dev,
- struct drm_display_mode *mode, int depth, int bpp,
- struct drm_framebuffer **res)
+ struct drm_display_mode *mode,
+ int depth, int bpp,
+ struct drm_framebuffer **res)
{
struct drm_i915_gem_object *obj;
- struct drm_mode_fb_cmd2 mode_cmd;
+ struct drm_mode_fb_cmd2 mode_cmd = { 0 };
obj = i915_gem_alloc_object(dev,
intel_framebuffer_size_for_mode(mode, bpp));
if (obj == NULL)
- return (-ENOMEM);
+ return -ENOMEM;
mode_cmd.width = mode->hdisplay;
mode_cmd.height = mode->vdisplay;
@@ -5360,12 +5353,13 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
bpp);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
- return (intel_framebuffer_create(dev, &mode_cmd, obj, res));
+ return intel_framebuffer_create(dev, &mode_cmd, obj, res);
}
static int
mode_fits_in_fbdev(struct drm_device *dev,
- struct drm_display_mode *mode, struct drm_framebuffer **res)
+ struct drm_display_mode *mode,
+ struct drm_framebuffer **res)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
@@ -5373,29 +5367,29 @@ mode_fits_in_fbdev(struct drm_device *dev,
if (dev_priv->fbdev == NULL) {
*res = NULL;
- return (0);
+ return 0;
}
obj = dev_priv->fbdev->ifb.obj;
if (obj == NULL) {
*res = NULL;
- return (0);
+ return 0;
}
fb = &dev_priv->fbdev->ifb.base;
if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
fb->bits_per_pixel)) {
*res = NULL;
- return (0);
+ return 0;
}
if (obj->base.size < mode->vdisplay * fb->pitches[0]) {
*res = NULL;
- return (0);
+ return 0;
}
*res = fb;
- return (0);
+ return 0;
}
bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
@@ -5409,7 +5403,8 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
struct drm_crtc *crtc = NULL;
struct drm_device *dev = encoder->dev;
struct drm_framebuffer *old_fb;
- int i = -1, r;
+ int i = -1;
+ int ret;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
connector->base.id, drm_get_connector_name(connector),
@@ -5487,15 +5482,15 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
* not even exist) or that it is large enough to satisfy the
* requested mode.
*/
- r = mode_fits_in_fbdev(dev, mode, &crtc->fb);
+ ret = mode_fits_in_fbdev(dev, mode, &crtc->fb);
if (crtc->fb == NULL) {
DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
- r = intel_framebuffer_create_for_mode(dev, mode, 24, 32,
+ ret = intel_framebuffer_create_for_mode(dev, mode, 24, 32,
&crtc->fb);
old->release_fb = crtc->fb;
} else
DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
- if (r != 0) {
+ if (ret) {
DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
crtc->fb = old_fb;
return false;
@@ -5511,7 +5506,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
/* let the connector get through one full cycle before testing */
intel_wait_for_vblank(dev, intel_crtc->pipe);
-
return true;
}
@@ -5755,7 +5749,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
int pipe = intel_crtc->pipe;
int dpll_reg = DPLL(pipe);
- u32 dpll;
+ int dpll;
DRM_DEBUG_DRIVER("downclocking LVDS\n");
@@ -5769,6 +5763,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
}
+
}
/**
@@ -5881,16 +5876,16 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
static void intel_unpin_work_fn(void *arg, int pending)
{
- struct intel_unpin_work *work = arg;
- struct drm_device *dev;
+ struct intel_unpin_work *work =
+ arg;
+ struct drm_device *dev = work->dev;
- dev = work->dev;
DRM_LOCK(dev);
intel_unpin_fb_obj(work->old_fb_obj);
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
- intel_update_fbc(work->dev);
+ intel_update_fbc(dev);
DRM_UNLOCK(dev);
free(work, DRM_MEM_KMS);
}
@@ -6250,7 +6245,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
free(work, DRM_MEM_KMS);
drm_vblank_put(dev, intel_crtc->pipe);
- DRM_DEBUG("flip queue: crtc already busy\n");
+ DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
return -EBUSY;
}
intel_crtc->unpin_work = work;
@@ -6705,8 +6700,7 @@ int intel_framebuffer_init(struct drm_device *dev,
case DRM_FORMAT_VYUY:
break;
default:
- DRM_DEBUG_KMS("unsupported pixel format %u\n",
- mode_cmd->pixel_format);
+ DRM_DEBUG("unsupported pixel format %u\n", mode_cmd->pixel_format);
return -EINVAL;
}
@@ -6723,17 +6717,18 @@ int intel_framebuffer_init(struct drm_device *dev,
static int
intel_user_framebuffer_create(struct drm_device *dev,
- struct drm_file *filp, struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_framebuffer **res)
+ struct drm_file *filp,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_framebuffer **res)
{
struct drm_i915_gem_object *obj;
obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
mode_cmd->handles[0]));
if (&obj->base == NULL)
- return (-ENOENT);
+ return -ENOENT;
- return (intel_framebuffer_create(dev, mode_cmd, obj, res));
+ return intel_framebuffer_create(dev, mode_cmd, obj, res);
}
static const struct drm_mode_config_funcs intel_mode_funcs = {
@@ -6942,7 +6937,7 @@ static void i915_disable_vga(struct drm_device *dev)
#endif
outb(VGA_SR_INDEX, SR01);
sr1 = inb(VGA_SR_DATA);
- outb(VGA_SR_DATA, sr1 | 1 << 5);
+ outb(VGA_SR_DATA, sr1 | 1<<5);
#if 0
vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
#endif
@@ -7061,6 +7056,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_unregister_dsm_handler();
#endif
+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
/* Skip inactive CRTCs */
if (!crtc->fb)
@@ -7088,7 +7084,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
/* Disable the irq before mode object teardown, for the irq might
* enqueue unpin/hotplug work. */
drm_irq_uninstall(dev);
-
if (taskqueue_cancel(dev_priv->tq, &dev_priv->hotplug_task, NULL))
taskqueue_drain(dev_priv->tq, &dev_priv->hotplug_task);
if (taskqueue_cancel(dev_priv->tq, &dev_priv->rps_task, NULL))
@@ -7127,11 +7122,9 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
*/
int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
{
- struct drm_i915_private *dev_priv;
device_t bridge_dev;
u16 gmch_ctrl;
- dev_priv = dev->dev_private;
bridge_dev = intel_gtt_get_bridge_device();
gmch_ctrl = pci_read_config(bridge_dev, INTEL_GMCH_CTRL, 2);
if (state)