[Intel-gfx] [PATCH] drm/i915: new blitter ring support from Sandybridge
Zhenyu Wang
zhenyuw at linux.intel.com
Tue Oct 12 10:13:51 CEST 2010
This adds new ring for blitter engine starting from Sandybridge.
Patch is against 2.6.36-rc kernel. As I haven't been able to find
out all regressions on drm-intel-next yet, which made KMS totally fail
on SNB now. I just base on current upstream tip, so I can see the testing
result.
Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 10 ++
drivers/gpu/drm/i915/i915_dma.c | 5 +
drivers/gpu/drm/i915/i915_drv.c | 2 +
drivers/gpu/drm/i915/i915_drv.h | 5 +
drivers/gpu/drm/i915/i915_gem.c | 65 +++++++++++++--
drivers/gpu/drm/i915/i915_gem_evict.c | 85 +++++++++++++++++--
drivers/gpu/drm/i915/i915_irq.c | 26 +++++-
drivers/gpu/drm/i915/i915_reg.h | 11 ++-
drivers/gpu/drm/i915/intel_ringbuffer.c | 139 +++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 1 +
include/drm/i915_drm.h | 2 +
11 files changed, 333 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5e43d70..eb82af9 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -43,6 +43,7 @@
#define ACTIVE_LIST 1
#define FLUSHING_LIST 2
#define INACTIVE_LIST 3
+#define BLIT_LIST 4
static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv)
{
@@ -80,6 +81,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
lock = &dev_priv->mm.active_list_lock;
head = &dev_priv->render_ring.active_list;
break;
+ case BLIT_LIST:
+ seq_printf(m, "BLIT:\n");
+ head = &dev_priv->blit_ring.active_list;
+ break;
case INACTIVE_LIST:
seq_printf(m, "Inactive:\n");
head = &dev_priv->mm.inactive_list;
@@ -242,6 +247,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
I915_READ(GTIIR));
seq_printf(m, "Graphics Interrupt mask: %08x\n",
I915_READ(GTIMR));
+ if (HAS_BLIT_SPLIT(dev)) {
+ seq_printf(m, "Blitter Interrupt mask: %08x\n",
+ I915_READ(GEN6_BLITTER_IMR));
+ }
}
seq_printf(m, "Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
@@ -826,6 +835,7 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
+ {"i915_gem_blit_active", i915_gem_object_list_info, 0, (void *) BLIT_LIST},
{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
{"i915_gem_request", i915_gem_request_info, 0},
{"i915_gem_seqno", i915_gem_seqno_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c74e4e8..b060a35 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -135,6 +135,8 @@ static int i915_dma_cleanup(struct drm_device * dev)
intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
if (HAS_BSD(dev))
intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+ if (HAS_BLIT_SPLIT(dev))
+ intel_cleanup_ring_buffer(dev, &dev_priv->blit_ring);
mutex_unlock(&dev->struct_mutex);
/* Clear the HWS virtual address at teardown */
@@ -765,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_BSD:
value = HAS_BSD(dev);
break;
+ case I915_PARAM_HAS_BLIT_SPLIT:
+ value = HAS_BLIT_SPLIT(dev);
+ break;
default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6dbe14c..0c08404 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -136,11 +136,13 @@ static const struct intel_device_info intel_ironlake_m_info = {
static const struct intel_device_info intel_sandybridge_d_info = {
.gen = 6, .is_i965g = 1, .is_i9xx = 1,
.need_gfx_hws = 1, .has_hotplug = 1,
+ .has_blit_split = 1,
};
static const struct intel_device_info intel_sandybridge_m_info = {
.gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1,
.need_gfx_hws = 1, .has_hotplug = 1,
+ .has_blit_split = 1,
};
static const struct pci_device_id pciidlist[] = { /* aka */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index af4a263..3a98bea 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -212,6 +212,7 @@ struct intel_device_info {
u8 has_pipe_cxsr : 1;
u8 has_hotplug : 1;
u8 cursor_needs_physical : 1;
+ u8 has_blit_split : 1;
};
enum no_fbc_reason {
@@ -244,6 +245,7 @@ typedef struct drm_i915_private {
struct pci_dev *bridge_dev;
struct intel_ring_buffer render_ring;
struct intel_ring_buffer bsd_ring;
+ struct intel_ring_buffer blit_ring;
uint32_t next_seqno;
drm_dma_handle_t *status_page_dmah;
@@ -292,6 +294,7 @@ typedef struct drm_i915_private {
u32 flush_rings;
#define FLUSH_RENDER_RING 0x1
#define FLUSH_BSD_RING 0x2
+#define FLUSH_BLIT_RING 0x3
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
@@ -1191,6 +1194,8 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev))
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
+#define HAS_BLIT_SPLIT(dev) (INTEL_INFO(dev)->has_blit_split)
+
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
* rows, which changed the alignment requirements and fence programming.
*/
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 90b1d67..276f456 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1797,6 +1797,8 @@ i915_gem_retire_requests(struct drm_device *dev)
i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
if (HAS_BSD(dev))
i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
+ if (HAS_BLIT_SPLIT(dev))
+ i915_gem_retire_requests_ring(dev, &dev_priv->blit_ring);
}
void
@@ -1815,7 +1817,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
if (!dev_priv->mm.suspended &&
(!list_empty(&dev_priv->render_ring.request_list) ||
(HAS_BSD(dev) &&
- !list_empty(&dev_priv->bsd_ring.request_list))))
+ !list_empty(&dev_priv->bsd_ring.request_list)) ||
+ (HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.request_list))))
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
mutex_unlock(&dev->struct_mutex);
}
@@ -1851,13 +1854,11 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
ring->user_irq_get(dev, ring);
if (interruptible)
ret = wait_event_interruptible(ring->irq_queue,
- i915_seqno_passed(
- ring->get_gem_seqno(dev, ring), seqno)
+ i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)
|| atomic_read(&dev_priv->mm.wedged));
else
wait_event(ring->irq_queue,
- i915_seqno_passed(
- ring->get_gem_seqno(dev, ring), seqno)
+ i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)
|| atomic_read(&dev_priv->mm.wedged));
ring->user_irq_put(dev, ring);
@@ -1910,6 +1911,11 @@ i915_gem_flush(struct drm_device *dev,
dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring,
invalidate_domains,
flush_domains);
+
+ if (HAS_BLIT_SPLIT(dev))
+ dev_priv->blit_ring.flush(dev, &dev_priv->blit_ring,
+ invalidate_domains,
+ flush_domains);
}
/**
@@ -2032,7 +2038,8 @@ i915_gpu_idle(struct drm_device *dev)
lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
list_empty(&dev_priv->render_ring.active_list) &&
(!HAS_BSD(dev) ||
- list_empty(&dev_priv->bsd_ring.active_list)));
+ list_empty(&dev_priv->bsd_ring.active_list)) &&
+ (!HAS_BLIT_SPLIT(dev) || list_empty(&dev_priv->blit_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
if (lists_empty)
@@ -2057,6 +2064,16 @@ i915_gpu_idle(struct drm_device *dev)
return ret;
}
+ if (HAS_BLIT_SPLIT(dev)) {
+ seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+ &dev_priv->blit_ring);
+ if (seqno2 == 0)
+ return -ENOMEM;
+
+ ret = i915_wait_request(dev, seqno2, &dev_priv->blit_ring);
+ if (ret)
+ return ret;
+ }
return ret;
}
@@ -3034,6 +3051,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
dev_priv->flush_rings |= FLUSH_RENDER_RING;
else if (obj_priv->ring == &dev_priv->bsd_ring)
dev_priv->flush_rings |= FLUSH_BSD_RING;
+ else if (obj_priv->ring == &dev_priv->blit_ring)
+ dev_priv->flush_rings |= FLUSH_BLIT_RING;
}
dev->invalidate_domains |= invalidate_domains;
@@ -3573,6 +3592,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
ring = &dev_priv->bsd_ring;
+ } else if (args->flags & I915_EXEC_BLIT){
+ if (!HAS_BLIT_SPLIT(dev)) {
+ DRM_ERROR("wrong ring for blit!\n");
+ return -EINVAL;
+ }
+ ring = &dev_priv->blit_ring;
} else {
ring = &dev_priv->render_ring;
}
@@ -3780,6 +3805,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
(void)i915_add_request(dev, file_priv,
dev->flush_domains,
&dev_priv->bsd_ring);
+ if (dev_priv->flush_rings & FLUSH_BLIT_RING)
+ (void)i915_add_request(dev, file_priv,
+ dev->flush_domains,
+ &dev_priv->blit_ring);
+
}
for (i = 0; i < args->buffer_count; i++) {
@@ -4398,7 +4428,8 @@ i915_gem_idle(struct drm_device *dev)
if (dev_priv->mm.suspended ||
(dev_priv->render_ring.gem_object == NULL) ||
(HAS_BSD(dev) &&
- dev_priv->bsd_ring.gem_object == NULL)) {
+ dev_priv->bsd_ring.gem_object == NULL) ||
+ (HAS_BLIT_SPLIT(dev) && !dev_priv->blit_ring.gem_object)) {
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -4529,10 +4560,20 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
goto cleanup_render_ring;
}
+ if (HAS_BLIT_SPLIT(dev)) {
+ dev_priv->blit_ring = blit_ring;
+ ret = intel_init_ring_buffer(dev, &dev_priv->blit_ring);
+ if (ret)
+ goto cleanup_bsd_ring;
+ }
+
dev_priv->next_seqno = 1;
return 0;
+cleanup_bsd_ring:
+ if (HAS_BSD(dev))
+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
cleanup_render_ring:
intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
cleanup_pipe_control:
@@ -4549,6 +4590,8 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
if (HAS_BSD(dev))
intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+ if (HAS_BLIT_SPLIT(dev))
+ intel_cleanup_ring_buffer(dev, &dev_priv->blit_ring);
if (HAS_PIPE_CONTROL(dev))
i915_gem_cleanup_pipe_control(dev);
}
@@ -4580,12 +4623,14 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
spin_lock(&dev_priv->mm.active_list_lock);
BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
+ BUG_ON(HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.active_list));
spin_unlock(&dev_priv->mm.active_list_lock);
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
+ BUG_ON(HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.request_list));
mutex_unlock(&dev->struct_mutex);
ret = drm_irq_install(dev);
@@ -4645,6 +4690,10 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
}
+ if (HAS_BLIT_SPLIT(dev)) {
+ INIT_LIST_HEAD(&dev_priv->blit_ring.active_list);
+ INIT_LIST_HEAD(&dev_priv->blit_ring.request_list);
+ }
for (i = 0; i < 16; i++)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
@@ -4894,6 +4943,8 @@ i915_gpu_is_active(struct drm_device *dev)
list_empty(&dev_priv->render_ring.active_list);
if (HAS_BSD(dev))
lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
+ if (HAS_BLIT_SPLIT(dev))
+ lists_empty &= list_empty(&dev_priv->blit_ring.active_list);
spin_unlock(&dev_priv->mm.active_list_lock);
return !lists_empty;
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 5c428fa..88eed61 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -34,17 +34,87 @@
static struct drm_i915_gem_object *
i915_gem_next_active_object(struct drm_device *dev,
struct list_head **render_iter,
- struct list_head **bsd_iter)
+ struct list_head **bsd_iter,
+ struct list_head **blit_iter)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *render_obj = NULL, *bsd_obj = NULL;
+ struct drm_i915_gem_object *blit_obj = NULL;
if (*render_iter != &dev_priv->render_ring.active_list)
render_obj = list_entry(*render_iter,
struct drm_i915_gem_object,
list);
- if (HAS_BSD(dev)) {
+ /* It's true that chip has splitted blit also has BSD. */
+ if (HAS_BLIT_SPLIT(dev)) {
+ u32 render_seq, blit_seq, bsd_seq;
+
+ if (*blit_iter != &dev_priv->blit_ring.active_list)
+ blit_obj = list_entry(*blit_iter,
+ struct drm_i915_gem_object,
+ list);
+
+ if (*bsd_iter != &dev_priv->bsd_ring.active_list)
+ bsd_obj = list_entry(*bsd_iter,
+ struct drm_i915_gem_object,
+ list);
+
+ /* last_rendering_seqno never could be 0 */
+
+ if (!render_obj)
+ render_seq = 0;
+ else
+ render_seq = render_obj->last_rendering_seqno;
+
+ if (!blit_obj)
+ blit_seq = 0;
+ else
+ blit_seq = blit_obj->last_rendering_seqno;
+
+ if (!bsd_obj)
+ bsd_seq = 0;
+ else
+ bsd_seq = bsd_obj->last_rendering_seqno;
+
+ /* any two null return the third */
+ if (render_seq == blit_seq)
+ return bsd_obj;
+ else if (render_seq == bsd_seq)
+ return blit_obj;
+ else if (blit_seq == bsd_seq)
+ return render_obj;
+
+ /* then only 1 null possible */
+ if (!render_seq) {
+ if (blit_seq < bsd_seq)
+ return blit_obj;
+ else
+ return bsd_obj;
+ }
+ if (!blit_seq) {
+ if (render_seq < bsd_seq)
+ return render_obj;
+ else
+ return bsd_obj;
+ }
+ if (!bsd_seq) {
+ if (blit_seq < render_seq)
+ return blit_obj;
+ else
+ return render_obj;
+ }
+
+ /* all three */
+ if (render_seq < bsd_seq && render_seq < blit_seq)
+ return render_obj;
+ if (bsd_seq < render_seq && bsd_seq < blit_seq)
+ return bsd_obj;
+ if (blit_seq < bsd_seq && blit_seq < render_seq)
+ return blit_obj;
+ return NULL; /* shut up gcc */
+
+ } else if (HAS_BSD(dev)) {
if (*bsd_iter != &dev_priv->bsd_ring.active_list)
bsd_obj = list_entry(*bsd_iter,
struct drm_i915_gem_object,
@@ -83,10 +153,11 @@ mark_free(struct drm_i915_gem_object *obj_priv,
return drm_mm_scan_add_block(obj_priv->gtt_space);
}
-#define i915_for_each_active_object(OBJ, R, B) \
+#define i915_for_each_active_object(OBJ, R, B, BLIT) \
*(R) = dev_priv->render_ring.active_list.next; \
*(B) = dev_priv->bsd_ring.active_list.next; \
- while (((OBJ) = i915_gem_next_active_object(dev, (R), (B))) != NULL)
+ *(BLIT) = dev_priv->blit_ring.active_list.next; \
+ while (((OBJ) = i915_gem_next_active_object(dev, (R), (B),(BLIT))) != NULL)
int
i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment)
@@ -94,7 +165,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
drm_i915_private_t *dev_priv = dev->dev_private;
struct list_head eviction_list, unwind_list;
struct drm_i915_gem_object *obj_priv;
- struct list_head *render_iter, *bsd_iter;
+ struct list_head *render_iter, *bsd_iter, *blit_iter;
int ret = 0;
i915_gem_retire_requests(dev);
@@ -137,7 +208,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
}
/* Now merge in the soon-to-be-expired objects... */
- i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) {
+ i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter, &blit_iter) {
/* Does the object require an outstanding flush? */
if (obj_priv->base.write_domain || obj_priv->pin_count)
continue;
@@ -154,7 +225,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
if (mark_free(obj_priv, &unwind_list))
goto found;
}
- i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) {
+ i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter, &blit_iter) {
if (! obj_priv->base.write_domain || obj_priv->pin_count)
continue;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 744225e..34be1b9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -312,6 +312,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
u32 de_iir, gt_iir, de_ier, pch_iir;
struct drm_i915_master_private *master_priv;
struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+ struct intel_ring_buffer *blit_ring = &dev_priv->blit_ring;
/* disable master interrupt before clearing iir */
de_ier = I915_READ(DEIER);
@@ -345,6 +346,15 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
if (gt_iir & GT_BSD_USER_INTERRUPT)
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+ if (HAS_BLIT_SPLIT(dev) && (gt_iir & GT_BLIT_USER_INTERRUPT)) {
+ u32 seqno = blit_ring->get_gem_seqno(dev, blit_ring);
+ blit_ring->irq_gem_seqno = seqno;
+ trace_i915_gem_request_complete(dev, seqno);
+ DRM_WAKEUP(&dev_priv->blit_ring.irq_queue);
+ dev_priv->hangcheck_count = 0;
+ mod_timer(&dev_priv->hangcheck_timer,
+ jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+ }
if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev);
@@ -1367,6 +1377,12 @@ void i915_hangcheck_elapsed(unsigned long data)
missed_wakeup = true;
}
+ if (HAS_BLIT_SPLIT(dev) && dev_priv->blit_ring.waiting_gem_seqno &&
+ waitqueue_active(&dev_priv->blit_ring.irq_queue)) {
+ DRM_WAKEUP(&dev_priv->blit_ring.irq_queue);
+ missed_wakeup = true;
+ }
+
if (missed_wakeup)
DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
return;
@@ -1436,17 +1452,18 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
(void) I915_READ(DEIER);
- /* Gen6 only needs render pipe_control now */
if (IS_GEN6(dev))
- render_mask = GT_PIPE_NOTIFY;
+ render_mask = GT_PIPE_NOTIFY | GT_BLIT_USER_INTERRUPT;
dev_priv->gt_irq_mask_reg = ~render_mask;
dev_priv->gt_irq_enable_reg = render_mask;
I915_WRITE(GTIIR, I915_READ(GTIIR));
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
- if (IS_GEN6(dev))
+ if (IS_GEN6(dev)) {
I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
+ I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT);
+ }
I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
(void) I915_READ(GTIER);
@@ -1510,6 +1527,9 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
if (HAS_BSD(dev))
DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
+ if (HAS_BLIT_SPLIT(dev))
+ DRM_INIT_WAITQUEUE(&dev_priv->blit_ring.irq_queue);
+
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
if (HAS_PCH_SPLIT(dev))
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4f5e155..209c15b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -192,6 +192,7 @@
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
#define MI_STORE_DWORD_INDEX_SHIFT 2
#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1)
+#define MI_FLUSH_DW MI_INSTR(0x26, 2)
#define MI_BATCH_BUFFER MI_INSTR(0x30, 1)
#define MI_BATCH_NON_SECURE (1)
#define MI_BATCH_NON_SECURE_I965 (1<<8)
@@ -476,6 +477,14 @@
#define BSD_RING_ACTHD 0x04074
#define BSD_HWS_PGA 0x04080
+/* Blit ring */
+#define BLIT_RING_TAIL 0x22030
+#define BLIT_RING_HEAD 0x22034
+#define BLIT_RING_START 0x22038
+#define BLIT_RING_CTL 0x2203c
+#define BLIT_RING_ACTHD 0x22074
+#define BLIT_HWS_PGA 0x24080
+
/*
* Framebuffer compression (915+ only)
*/
@@ -2516,7 +2525,7 @@
#define GT_SYNC_STATUS (1 << 2)
#define GT_USER_INTERRUPT (1 << 0)
#define GT_BSD_USER_INTERRUPT (1 << 5)
-
+#define GT_BLIT_USER_INTERRUPT (1 << 22)
#define GTISR 0x44010
#define GTIMR 0x44014
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index cb3508f..dac1c61 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -488,6 +488,109 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
return 0;
}
+/* blit */
+static void blit_setup_status_page(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ I915_WRITE(BLIT_HWS_PGA, ring->status_page.gfx_addr);
+ I915_READ(BLIT_HWS_PGA);
+}
+
+void blit_ring_flush(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ u32 invalidate_domains,
+ u32 flush_domains)
+{
+ intel_ring_begin(dev, ring, 4);
+ intel_ring_emit(dev, ring, MI_FLUSH_DW);
+ intel_ring_emit(dev, ring, 0);
+ intel_ring_emit(dev, ring, 0);
+ intel_ring_emit(dev, ring, 0);
+ intel_ring_advance(dev, ring);
+}
+
+static inline unsigned int blit_ring_get_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BLIT_RING_HEAD) & HEAD_ADDR;
+}
+
+static inline unsigned int blit_ring_get_tail(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BLIT_RING_TAIL) & TAIL_ADDR;
+}
+
+static inline unsigned int blit_ring_get_active_head(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ return I915_READ(BLIT_RING_ACTHD);
+}
+
+static inline void blit_ring_advance_ring(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ I915_WRITE(BLIT_RING_TAIL, ring->tail);
+}
+
+static u32 blit_ring_add_request(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_file *file_priv,
+ u32 flush_domains)
+{
+ u32 seqno;
+
+ seqno = i915_gem_get_seqno(dev);
+
+ intel_ring_begin(dev, ring, 4);
+ intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
+ intel_ring_emit(dev, ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+ intel_ring_emit(dev, ring, seqno);
+ intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
+ intel_ring_advance(dev, ring);
+
+ DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
+
+ return seqno;
+}
+
+static void blit_ring_get_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ /* do nothing */
+}
+static void blit_ring_put_user_irq(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ /* do nothing */
+}
+
+static u32 blit_ring_get_gem_seqno(struct drm_device *dev,
+ struct intel_ring_buffer *ring)
+{
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static int blit_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+ struct intel_ring_buffer *ring,
+ struct drm_i915_gem_execbuffer2 *exec,
+ struct drm_clip_rect *cliprects,
+ uint64_t exec_offset)
+{
+ uint32_t exec_start;
+ exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+ intel_ring_begin(dev, ring, 2);
+ intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
+ (2 << 6) | MI_BATCH_NON_SECURE_I965);
+ intel_ring_emit(dev, ring, exec_start);
+ intel_ring_advance(dev, ring);
+ return 0;
+}
static int
render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
@@ -866,3 +969,39 @@ struct intel_ring_buffer bsd_ring = {
.status_page = {NULL, 0, NULL},
.map = {0,}
};
+
+struct intel_ring_buffer blit_ring = {
+ .name = "blit ring",
+ .regs = {
+ .ctl = BLIT_RING_CTL,
+ .head = BLIT_RING_HEAD,
+ .tail = BLIT_RING_TAIL,
+ .start = BLIT_RING_START
+ },
+ .ring_flag = I915_EXEC_BLIT,
+ .size = 32 * PAGE_SIZE,
+ .alignment = PAGE_SIZE,
+ .virtual_start = NULL,
+ .dev = NULL,
+ .gem_object = NULL,
+ .head = 0,
+ .tail = 0,
+ .space = 0,
+ .user_irq_refcount = 0,
+ .irq_gem_seqno = 0,
+ .waiting_gem_seqno = 0,
+ .setup_status_page = blit_setup_status_page,
+ .init = init_ring_common,
+ .get_head = blit_ring_get_head,
+ .get_tail = blit_ring_get_tail,
+ .get_active_head = blit_ring_get_active_head,
+ .advance_ring = blit_ring_advance_ring,
+ .flush = blit_ring_flush,
+ .add_request = blit_ring_add_request,
+ .get_gem_seqno = blit_ring_get_gem_seqno,
+ .user_irq_get = blit_ring_get_user_irq,
+ .user_irq_put = blit_ring_put_user_irq,
+ .dispatch_gem_execbuffer = blit_ring_dispatch_gem_execbuffer,
+ .status_page = {NULL, 0, NULL},
+ .map = {0,}
+};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 525e7d3..d6d8a7b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -127,5 +127,6 @@ u32 intel_ring_get_seqno(struct drm_device *dev,
extern struct intel_ring_buffer render_ring;
extern struct intel_ring_buffer bsd_ring;
+extern struct intel_ring_buffer blit_ring;
#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index e41c74f..087879d 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -286,6 +286,7 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_PAGEFLIPPING 8
#define I915_PARAM_HAS_EXECBUF2 9
#define I915_PARAM_HAS_BSD 10
+#define I915_PARAM_HAS_BLIT_SPLIT 11
typedef struct drm_i915_getparam {
int param;
@@ -629,6 +630,7 @@ struct drm_i915_gem_execbuffer2 {
__u64 cliprects_ptr;
#define I915_EXEC_RENDER (1<<0)
#define I915_EXEC_BSD (1<<1)
+#define I915_EXEC_BLIT (1<<2)
__u64 flags;
__u64 rsvd1;
__u64 rsvd2;
--
1.7.0.4
More information about the Intel-gfx
mailing list