aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-10-19 06:19:32 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-21 14:08:39 -0400
commit549f7365820a212a1cfd0871d377b1ad0d1e5723 (patch)
treedbd39c10b32b35b762b083a358b7fc4c09783d5b
parente36c1cd7292efcb8daca26cd6331481736544742 (diff)
drm/i915: Enable SandyBridge blitter ring
Based on an original patch by Zhenyu Wang, this initializes the BLT ring for SandyBridge and enables support for user execbuffers. Cc: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c2
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c55
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c6
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c64
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c92
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h2
-rw-r--r--include/drm/i915_drm.h6
11 files changed, 175 insertions, 63 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index f9e3295f0457..d521de3e0680 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -80,6 +80,8 @@ static int i915_capabilities(struct seq_file *m, void *data)
80 B(has_overlay); 80 B(has_overlay);
81 B(overlay_needs_physical); 81 B(overlay_needs_physical);
82 B(supports_tv); 82 B(supports_tv);
83 B(has_bsd_ring);
84 B(has_blt_ring);
83#undef B 85#undef B
84 86
85 return 0; 87 return 0;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1ffeb1c5e7c4..1851ca4087f9 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -133,6 +133,7 @@ static int i915_dma_cleanup(struct drm_device * dev)
133 mutex_lock(&dev->struct_mutex); 133 mutex_lock(&dev->struct_mutex);
134 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); 134 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
135 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); 135 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
136 intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring);
136 mutex_unlock(&dev->struct_mutex); 137 mutex_unlock(&dev->struct_mutex);
137 138
138 /* Clear the HWS virtual address at teardown */ 139 /* Clear the HWS virtual address at teardown */
@@ -763,6 +764,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
763 case I915_PARAM_HAS_BSD: 764 case I915_PARAM_HAS_BSD:
764 value = HAS_BSD(dev); 765 value = HAS_BSD(dev);
765 break; 766 break;
767 case I915_PARAM_HAS_BLT:
768 value = HAS_BLT(dev);
769 break;
766 default: 770 default:
767 DRM_DEBUG_DRIVER("Unknown parameter %d\n", 771 DRM_DEBUG_DRIVER("Unknown parameter %d\n",
768 param->param); 772 param->param);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c3decb2fef4b..90f9c3e3fee3 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -158,12 +158,14 @@ static const struct intel_device_info intel_sandybridge_d_info = {
158 .gen = 6, 158 .gen = 6,
159 .need_gfx_hws = 1, .has_hotplug = 1, 159 .need_gfx_hws = 1, .has_hotplug = 1,
160 .has_bsd_ring = 1, 160 .has_bsd_ring = 1,
161 .has_blt_ring = 1,
161}; 162};
162 163
163static const struct intel_device_info intel_sandybridge_m_info = { 164static const struct intel_device_info intel_sandybridge_m_info = {
164 .gen = 6, .is_mobile = 1, 165 .gen = 6, .is_mobile = 1,
165 .need_gfx_hws = 1, .has_hotplug = 1, 166 .need_gfx_hws = 1, .has_hotplug = 1,
166 .has_bsd_ring = 1, 167 .has_bsd_ring = 1,
168 .has_blt_ring = 1,
167}; 169};
168 170
169static const struct pci_device_id pciidlist[] = { /* aka */ 171static 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 817d8be6ff49..a9a0e220176e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -216,6 +216,7 @@ struct intel_device_info {
216 u8 overlay_needs_physical : 1; 216 u8 overlay_needs_physical : 1;
217 u8 supports_tv : 1; 217 u8 supports_tv : 1;
218 u8 has_bsd_ring : 1; 218 u8 has_bsd_ring : 1;
219 u8 has_blt_ring : 1;
219}; 220};
220 221
221enum no_fbc_reason { 222enum no_fbc_reason {
@@ -255,6 +256,7 @@ typedef struct drm_i915_private {
255 struct pci_dev *bridge_dev; 256 struct pci_dev *bridge_dev;
256 struct intel_ring_buffer render_ring; 257 struct intel_ring_buffer render_ring;
257 struct intel_ring_buffer bsd_ring; 258 struct intel_ring_buffer bsd_ring;
259 struct intel_ring_buffer blt_ring;
258 uint32_t next_seqno; 260 uint32_t next_seqno;
259 261
260 drm_dma_handle_t *status_page_dmah; 262 drm_dma_handle_t *status_page_dmah;
@@ -1300,6 +1302,7 @@ static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg,
1300#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) 1302#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6)
1301 1303
1302#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) 1304#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring)
1305#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring)
1303#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) 1306#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
1304 1307
1305#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) 1308#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5041ebe3fdf9..c3398d396419 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1800,6 +1800,7 @@ void i915_gem_reset(struct drm_device *dev)
1800 1800
1801 i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring); 1801 i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring);
1802 i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring); 1802 i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring);
1803 i915_gem_reset_ring_lists(dev_priv, &dev_priv->blt_ring);
1803 1804
1804 /* Remove anything from the flushing lists. The GPU cache is likely 1805 /* Remove anything from the flushing lists. The GPU cache is likely
1805 * to be lost on reset along with the data, so simply move the 1806 * to be lost on reset along with the data, so simply move the
@@ -1922,6 +1923,7 @@ i915_gem_retire_requests(struct drm_device *dev)
1922 1923
1923 i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); 1924 i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
1924 i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); 1925 i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
1926 i915_gem_retire_requests_ring(dev, &dev_priv->blt_ring);
1925} 1927}
1926 1928
1927static void 1929static void
@@ -1944,7 +1946,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
1944 1946
1945 if (!dev_priv->mm.suspended && 1947 if (!dev_priv->mm.suspended &&
1946 (!list_empty(&dev_priv->render_ring.request_list) || 1948 (!list_empty(&dev_priv->render_ring.request_list) ||
1947 !list_empty(&dev_priv->bsd_ring.request_list))) 1949 !list_empty(&dev_priv->bsd_ring.request_list) ||
1950 !list_empty(&dev_priv->blt_ring.request_list)))
1948 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); 1951 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
1949 mutex_unlock(&dev->struct_mutex); 1952 mutex_unlock(&dev->struct_mutex);
1950} 1953}
@@ -2063,6 +2066,10 @@ i915_gem_flush(struct drm_device *dev,
2063 i915_gem_flush_ring(dev, file_priv, 2066 i915_gem_flush_ring(dev, file_priv,
2064 &dev_priv->bsd_ring, 2067 &dev_priv->bsd_ring,
2065 invalidate_domains, flush_domains); 2068 invalidate_domains, flush_domains);
2069 if (flush_rings & RING_BLT)
2070 i915_gem_flush_ring(dev, file_priv,
2071 &dev_priv->blt_ring,
2072 invalidate_domains, flush_domains);
2066 } 2073 }
2067} 2074}
2068 2075
@@ -2182,7 +2189,8 @@ i915_gpu_idle(struct drm_device *dev)
2182 2189
2183 lists_empty = (list_empty(&dev_priv->mm.flushing_list) && 2190 lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
2184 list_empty(&dev_priv->render_ring.active_list) && 2191 list_empty(&dev_priv->render_ring.active_list) &&
2185 list_empty(&dev_priv->bsd_ring.active_list)); 2192 list_empty(&dev_priv->bsd_ring.active_list) &&
2193 list_empty(&dev_priv->blt_ring.active_list));
2186 if (lists_empty) 2194 if (lists_empty)
2187 return 0; 2195 return 0;
2188 2196
@@ -2195,6 +2203,10 @@ i915_gpu_idle(struct drm_device *dev)
2195 if (ret) 2203 if (ret)
2196 return ret; 2204 return ret;
2197 2205
2206 ret = i915_ring_idle(dev, &dev_priv->blt_ring);
2207 if (ret)
2208 return ret;
2209
2198 return 0; 2210 return 0;
2199} 2211}
2200 2212
@@ -3609,14 +3621,29 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
3609 DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", 3621 DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
3610 (int) args->buffers_ptr, args->buffer_count, args->batch_len); 3622 (int) args->buffers_ptr, args->buffer_count, args->batch_len);
3611#endif 3623#endif
3612 if (args->flags & I915_EXEC_BSD) { 3624 switch (args->flags & I915_EXEC_RING_MASK) {
3625 case I915_EXEC_DEFAULT:
3626 case I915_EXEC_RENDER:
3627 ring = &dev_priv->render_ring;
3628 break;
3629 case I915_EXEC_BSD:
3613 if (!HAS_BSD(dev)) { 3630 if (!HAS_BSD(dev)) {
3614 DRM_ERROR("execbuf with wrong flag\n"); 3631 DRM_ERROR("execbuf with invalid ring (BSD)\n");
3615 return -EINVAL; 3632 return -EINVAL;
3616 } 3633 }
3617 ring = &dev_priv->bsd_ring; 3634 ring = &dev_priv->bsd_ring;
3618 } else { 3635 break;
3619 ring = &dev_priv->render_ring; 3636 case I915_EXEC_BLT:
3637 if (!HAS_BLT(dev)) {
3638 DRM_ERROR("execbuf with invalid ring (BLT)\n");
3639 return -EINVAL;
3640 }
3641 ring = &dev_priv->blt_ring;
3642 break;
3643 default:
3644 DRM_ERROR("execbuf with unknown ring: %d\n",
3645 (int)(args->flags & I915_EXEC_RING_MASK));
3646 return -EINVAL;
3620 } 3647 }
3621 3648
3622 if (args->buffer_count < 1) { 3649 if (args->buffer_count < 1) {
@@ -4482,10 +4509,18 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
4482 goto cleanup_render_ring; 4509 goto cleanup_render_ring;
4483 } 4510 }
4484 4511
4512 if (HAS_BLT(dev)) {
4513 ret = intel_init_blt_ring_buffer(dev);
4514 if (ret)
4515 goto cleanup_bsd_ring;
4516 }
4517
4485 dev_priv->next_seqno = 1; 4518 dev_priv->next_seqno = 1;
4486 4519
4487 return 0; 4520 return 0;
4488 4521
4522cleanup_bsd_ring:
4523 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
4489cleanup_render_ring: 4524cleanup_render_ring:
4490 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); 4525 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
4491cleanup_pipe_control: 4526cleanup_pipe_control:
@@ -4501,6 +4536,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
4501 4536
4502 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); 4537 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
4503 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); 4538 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
4539 intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring);
4504 if (HAS_PIPE_CONTROL(dev)) 4540 if (HAS_PIPE_CONTROL(dev))
4505 i915_gem_cleanup_pipe_control(dev); 4541 i915_gem_cleanup_pipe_control(dev);
4506} 4542}
@@ -4532,10 +4568,12 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
4532 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 4568 BUG_ON(!list_empty(&dev_priv->mm.active_list));
4533 BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); 4569 BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
4534 BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list)); 4570 BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list));
4571 BUG_ON(!list_empty(&dev_priv->blt_ring.active_list));
4535 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); 4572 BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
4536 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 4573 BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
4537 BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); 4574 BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
4538 BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list)); 4575 BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list));
4576 BUG_ON(!list_empty(&dev_priv->blt_ring.request_list));
4539 mutex_unlock(&dev->struct_mutex); 4577 mutex_unlock(&dev->struct_mutex);
4540 4578
4541 ret = drm_irq_install(dev); 4579 ret = drm_irq_install(dev);
@@ -4594,6 +4632,8 @@ i915_gem_load(struct drm_device *dev)
4594 INIT_LIST_HEAD(&dev_priv->render_ring.request_list); 4632 INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
4595 INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list); 4633 INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
4596 INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list); 4634 INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
4635 INIT_LIST_HEAD(&dev_priv->blt_ring.active_list);
4636 INIT_LIST_HEAD(&dev_priv->blt_ring.request_list);
4597 for (i = 0; i < 16; i++) 4637 for (i = 0; i < 16; i++)
4598 INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); 4638 INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
4599 INIT_DELAYED_WORK(&dev_priv->mm.retire_work, 4639 INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
@@ -4857,7 +4897,8 @@ i915_gpu_is_active(struct drm_device *dev)
4857 4897
4858 lists_empty = list_empty(&dev_priv->mm.flushing_list) && 4898 lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
4859 list_empty(&dev_priv->render_ring.active_list) && 4899 list_empty(&dev_priv->render_ring.active_list) &&
4860 list_empty(&dev_priv->bsd_ring.active_list); 4900 list_empty(&dev_priv->bsd_ring.active_list) &&
4901 list_empty(&dev_priv->blt_ring.active_list);
4861 4902
4862 return !lists_empty; 4903 return !lists_empty;
4863} 4904}
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 70db2f1ee369..43a4013f53fa 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -166,7 +166,8 @@ i915_gem_evict_everything(struct drm_device *dev)
166 lists_empty = (list_empty(&dev_priv->mm.inactive_list) && 166 lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
167 list_empty(&dev_priv->mm.flushing_list) && 167 list_empty(&dev_priv->mm.flushing_list) &&
168 list_empty(&dev_priv->render_ring.active_list) && 168 list_empty(&dev_priv->render_ring.active_list) &&
169 list_empty(&dev_priv->bsd_ring.active_list)); 169 list_empty(&dev_priv->bsd_ring.active_list) &&
170 list_empty(&dev_priv->blt_ring.active_list));
170 if (lists_empty) 171 if (lists_empty)
171 return -ENOSPC; 172 return -ENOSPC;
172 173
@@ -184,7 +185,8 @@ i915_gem_evict_everything(struct drm_device *dev)
184 lists_empty = (list_empty(&dev_priv->mm.inactive_list) && 185 lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
185 list_empty(&dev_priv->mm.flushing_list) && 186 list_empty(&dev_priv->mm.flushing_list) &&
186 list_empty(&dev_priv->render_ring.active_list) && 187 list_empty(&dev_priv->render_ring.active_list) &&
187 list_empty(&dev_priv->bsd_ring.active_list)); 188 list_empty(&dev_priv->bsd_ring.active_list) &&
189 list_empty(&dev_priv->blt_ring.active_list));
188 BUG_ON(!lists_empty); 190 BUG_ON(!lists_empty);
189 191
190 return 0; 192 return 0;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f94cd7ffd74d..237b8bdb5994 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -293,6 +293,19 @@ static void i915_handle_rps_change(struct drm_device *dev)
293 return; 293 return;
294} 294}
295 295
296static void notify_ring(struct drm_device *dev,
297 struct intel_ring_buffer *ring)
298{
299 struct drm_i915_private *dev_priv = dev->dev_private;
300 u32 seqno = ring->get_seqno(dev, ring);
301 ring->irq_gem_seqno = seqno;
302 trace_i915_gem_request_complete(dev, seqno);
303 wake_up_all(&ring->irq_queue);
304 dev_priv->hangcheck_count = 0;
305 mod_timer(&dev_priv->hangcheck_timer,
306 jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
307}
308
296static irqreturn_t ironlake_irq_handler(struct drm_device *dev) 309static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
297{ 310{
298 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 311 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -300,7 +313,6 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
300 u32 de_iir, gt_iir, de_ier, pch_iir; 313 u32 de_iir, gt_iir, de_ier, pch_iir;
301 u32 hotplug_mask; 314 u32 hotplug_mask;
302 struct drm_i915_master_private *master_priv; 315 struct drm_i915_master_private *master_priv;
303 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
304 u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; 316 u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
305 317
306 if (IS_GEN6(dev)) 318 if (IS_GEN6(dev))
@@ -332,17 +344,12 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
332 READ_BREADCRUMB(dev_priv); 344 READ_BREADCRUMB(dev_priv);
333 } 345 }
334 346
335 if (gt_iir & GT_PIPE_NOTIFY) { 347 if (gt_iir & GT_PIPE_NOTIFY)
336 u32 seqno = render_ring->get_seqno(dev, render_ring); 348 notify_ring(dev, &dev_priv->render_ring);
337 render_ring->irq_gem_seqno = seqno;
338 trace_i915_gem_request_complete(dev, seqno);
339 wake_up_all(&dev_priv->render_ring.irq_queue);
340 dev_priv->hangcheck_count = 0;
341 mod_timer(&dev_priv->hangcheck_timer,
342 jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
343 }
344 if (gt_iir & bsd_usr_interrupt) 349 if (gt_iir & bsd_usr_interrupt)
345 wake_up_all(&dev_priv->bsd_ring.irq_queue); 350 notify_ring(dev, &dev_priv->bsd_ring);
351 if (HAS_BLT(dev) && gt_iir & GT_BLT_USER_INTERRUPT)
352 notify_ring(dev, &dev_priv->blt_ring);
346 353
347 if (de_iir & DE_GSE) 354 if (de_iir & DE_GSE)
348 intel_opregion_gse_intr(dev); 355 intel_opregion_gse_intr(dev);
@@ -881,6 +888,8 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
881 wake_up_all(&dev_priv->render_ring.irq_queue); 888 wake_up_all(&dev_priv->render_ring.irq_queue);
882 if (HAS_BSD(dev)) 889 if (HAS_BSD(dev))
883 wake_up_all(&dev_priv->bsd_ring.irq_queue); 890 wake_up_all(&dev_priv->bsd_ring.irq_queue);
891 if (HAS_BLT(dev))
892 wake_up_all(&dev_priv->blt_ring.irq_queue);
884 } 893 }
885 894
886 queue_work(dev_priv->wq, &dev_priv->error_work); 895 queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -941,7 +950,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
941 unsigned long irqflags; 950 unsigned long irqflags;
942 int irq_received; 951 int irq_received;
943 int ret = IRQ_NONE; 952 int ret = IRQ_NONE;
944 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
945 953
946 atomic_inc(&dev_priv->irq_received); 954 atomic_inc(&dev_priv->irq_received);
947 955
@@ -1018,18 +1026,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
1018 READ_BREADCRUMB(dev_priv); 1026 READ_BREADCRUMB(dev_priv);
1019 } 1027 }
1020 1028
1021 if (iir & I915_USER_INTERRUPT) { 1029 if (iir & I915_USER_INTERRUPT)
1022 u32 seqno = render_ring->get_seqno(dev, render_ring); 1030 notify_ring(dev, &dev_priv->render_ring);
1023 render_ring->irq_gem_seqno = seqno;
1024 trace_i915_gem_request_complete(dev, seqno);
1025 wake_up_all(&dev_priv->render_ring.irq_queue);
1026 dev_priv->hangcheck_count = 0;
1027 mod_timer(&dev_priv->hangcheck_timer,
1028 jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
1029 }
1030
1031 if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) 1031 if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
1032 wake_up_all(&dev_priv->bsd_ring.irq_queue); 1032 notify_ring(dev, &dev_priv->bsd_ring);
1033 1033
1034 if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { 1034 if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
1035 intel_prepare_page_flip(dev, 0); 1035 intel_prepare_page_flip(dev, 0);
@@ -1358,6 +1358,12 @@ void i915_hangcheck_elapsed(unsigned long data)
1358 missed_wakeup = true; 1358 missed_wakeup = true;
1359 } 1359 }
1360 1360
1361 if (dev_priv->blt_ring.waiting_gem_seqno &&
1362 waitqueue_active(&dev_priv->blt_ring.irq_queue)) {
1363 wake_up_all(&dev_priv->blt_ring.irq_queue);
1364 missed_wakeup = true;
1365 }
1366
1361 if (missed_wakeup) 1367 if (missed_wakeup)
1362 DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); 1368 DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
1363 return; 1369 return;
@@ -1443,8 +1449,12 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
1443 I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); 1449 I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
1444 (void) I915_READ(DEIER); 1450 (void) I915_READ(DEIER);
1445 1451
1446 if (IS_GEN6(dev)) 1452 if (IS_GEN6(dev)) {
1447 render_mask = GT_PIPE_NOTIFY | GT_GEN6_BSD_USER_INTERRUPT; 1453 render_mask =
1454 GT_PIPE_NOTIFY |
1455 GT_GEN6_BSD_USER_INTERRUPT |
1456 GT_BLT_USER_INTERRUPT;
1457 }
1448 1458
1449 dev_priv->gt_irq_mask_reg = ~render_mask; 1459 dev_priv->gt_irq_mask_reg = ~render_mask;
1450 dev_priv->gt_irq_enable_reg = render_mask; 1460 dev_priv->gt_irq_enable_reg = render_mask;
@@ -1454,6 +1464,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
1454 if (IS_GEN6(dev)) { 1464 if (IS_GEN6(dev)) {
1455 I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); 1465 I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
1456 I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT); 1466 I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT);
1467 I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT);
1457 } 1468 }
1458 1469
1459 I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); 1470 I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
@@ -1523,9 +1534,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
1523 u32 error_mask; 1534 u32 error_mask;
1524 1535
1525 DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue); 1536 DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue);
1526
1527 if (HAS_BSD(dev)) 1537 if (HAS_BSD(dev))
1528 DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue); 1538 DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
1539 if (HAS_BLT(dev))
1540 DRM_INIT_WAITQUEUE(&dev_priv->blt_ring.irq_queue);
1529 1541
1530 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; 1542 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
1531 1543
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 557f27134d05..c52e209321c1 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -263,6 +263,7 @@
263#define RENDER_RING_BASE 0x02000 263#define RENDER_RING_BASE 0x02000
264#define BSD_RING_BASE 0x04000 264#define BSD_RING_BASE 0x04000
265#define GEN6_BSD_RING_BASE 0x12000 265#define GEN6_BSD_RING_BASE 0x12000
266#define BLT_RING_BASE 0x22000
266#define RING_TAIL(base) ((base)+0x30) 267#define RING_TAIL(base) ((base)+0x30)
267#define RING_HEAD(base) ((base)+0x34) 268#define RING_HEAD(base) ((base)+0x34)
268#define RING_START(base) ((base)+0x38) 269#define RING_START(base) ((base)+0x38)
@@ -2561,6 +2562,7 @@
2561#define GT_USER_INTERRUPT (1 << 0) 2562#define GT_USER_INTERRUPT (1 << 0)
2562#define GT_BSD_USER_INTERRUPT (1 << 5) 2563#define GT_BSD_USER_INTERRUPT (1 << 5)
2563#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12) 2564#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12)
2565#define GT_BLT_USER_INTERRUPT (1 << 22)
2564 2566
2565#define GTISR 0x44010 2567#define GTISR 0x44010
2566#define GTIMR 0x44014 2568#define GTIMR 0x44014
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 8da5ff790da3..a8f408fe4e71 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -383,9 +383,9 @@ static int init_bsd_ring(struct drm_device *dev,
383} 383}
384 384
385static u32 385static u32
386bsd_ring_add_request(struct drm_device *dev, 386ring_add_request(struct drm_device *dev,
387 struct intel_ring_buffer *ring, 387 struct intel_ring_buffer *ring,
388 u32 flush_domains) 388 u32 flush_domains)
389{ 389{
390 u32 seqno; 390 u32 seqno;
391 391
@@ -418,18 +418,18 @@ bsd_ring_put_user_irq(struct drm_device *dev,
418} 418}
419 419
420static u32 420static u32
421bsd_ring_get_seqno(struct drm_device *dev, 421ring_status_page_get_seqno(struct drm_device *dev,
422 struct intel_ring_buffer *ring) 422 struct intel_ring_buffer *ring)
423{ 423{
424 return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 424 return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
425} 425}
426 426
427static int 427static int
428bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, 428ring_dispatch_gem_execbuffer(struct drm_device *dev,
429 struct intel_ring_buffer *ring, 429 struct intel_ring_buffer *ring,
430 struct drm_i915_gem_execbuffer2 *exec, 430 struct drm_i915_gem_execbuffer2 *exec,
431 struct drm_clip_rect *cliprects, 431 struct drm_clip_rect *cliprects,
432 uint64_t exec_offset) 432 uint64_t exec_offset)
433{ 433{
434 uint32_t exec_start; 434 uint32_t exec_start;
435 exec_start = (uint32_t) exec_offset + exec->batch_start_offset; 435 exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
@@ -441,7 +441,6 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
441 return 0; 441 return 0;
442} 442}
443 443
444
445static int 444static int
446render_ring_dispatch_gem_execbuffer(struct drm_device *dev, 445render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
447 struct intel_ring_buffer *ring, 446 struct intel_ring_buffer *ring,
@@ -758,11 +757,11 @@ static const struct intel_ring_buffer bsd_ring = {
758 .init = init_bsd_ring, 757 .init = init_bsd_ring,
759 .set_tail = ring_set_tail, 758 .set_tail = ring_set_tail,
760 .flush = bsd_ring_flush, 759 .flush = bsd_ring_flush,
761 .add_request = bsd_ring_add_request, 760 .add_request = ring_add_request,
762 .get_seqno = bsd_ring_get_seqno, 761 .get_seqno = ring_status_page_get_seqno,
763 .user_irq_get = bsd_ring_get_user_irq, 762 .user_irq_get = bsd_ring_get_user_irq,
764 .user_irq_put = bsd_ring_put_user_irq, 763 .user_irq_put = bsd_ring_put_user_irq,
765 .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, 764 .dispatch_gem_execbuffer = ring_dispatch_gem_execbuffer,
766}; 765};
767 766
768 767
@@ -789,10 +788,10 @@ static void gen6_bsd_ring_set_tail(struct drm_device *dev,
789 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); 788 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
790} 789}
791 790
792static void gen6_bsd_ring_flush(struct drm_device *dev, 791static void gen6_ring_flush(struct drm_device *dev,
793 struct intel_ring_buffer *ring, 792 struct intel_ring_buffer *ring,
794 u32 invalidate_domains, 793 u32 invalidate_domains,
795 u32 flush_domains) 794 u32 flush_domains)
796{ 795{
797 intel_ring_begin(dev, ring, 4); 796 intel_ring_begin(dev, ring, 4);
798 intel_ring_emit(dev, ring, MI_FLUSH_DW); 797 intel_ring_emit(dev, ring, MI_FLUSH_DW);
@@ -803,11 +802,11 @@ static void gen6_bsd_ring_flush(struct drm_device *dev,
803} 802}
804 803
805static int 804static int
806gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, 805gen6_ring_dispatch_gem_execbuffer(struct drm_device *dev,
807 struct intel_ring_buffer *ring, 806 struct intel_ring_buffer *ring,
808 struct drm_i915_gem_execbuffer2 *exec, 807 struct drm_i915_gem_execbuffer2 *exec,
809 struct drm_clip_rect *cliprects, 808 struct drm_clip_rect *cliprects,
810 uint64_t exec_offset) 809 uint64_t exec_offset)
811{ 810{
812 uint32_t exec_start; 811 uint32_t exec_start;
813 812
@@ -831,12 +830,42 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
831 .size = 32 * PAGE_SIZE, 830 .size = 32 * PAGE_SIZE,
832 .init = init_bsd_ring, 831 .init = init_bsd_ring,
833 .set_tail = gen6_bsd_ring_set_tail, 832 .set_tail = gen6_bsd_ring_set_tail,
834 .flush = gen6_bsd_ring_flush, 833 .flush = gen6_ring_flush,
835 .add_request = bsd_ring_add_request, 834 .add_request = ring_add_request,
836 .get_seqno = bsd_ring_get_seqno, 835 .get_seqno = ring_status_page_get_seqno,
837 .user_irq_get = bsd_ring_get_user_irq, 836 .user_irq_get = bsd_ring_get_user_irq,
838 .user_irq_put = bsd_ring_put_user_irq, 837 .user_irq_put = bsd_ring_put_user_irq,
839 .dispatch_gem_execbuffer = gen6_bsd_ring_dispatch_gem_execbuffer, 838 .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer,
839};
840
841/* Blitter support (SandyBridge+) */
842
843static void
844blt_ring_get_user_irq(struct drm_device *dev,
845 struct intel_ring_buffer *ring)
846{
847 /* do nothing */
848}
849static void
850blt_ring_put_user_irq(struct drm_device *dev,
851 struct intel_ring_buffer *ring)
852{
853 /* do nothing */
854}
855
856static const struct intel_ring_buffer gen6_blt_ring = {
857 .name = "blt ring",
858 .id = RING_BLT,
859 .mmio_base = BLT_RING_BASE,
860 .size = 32 * PAGE_SIZE,
861 .init = init_ring_common,
862 .set_tail = ring_set_tail,
863 .flush = gen6_ring_flush,
864 .add_request = ring_add_request,
865 .get_seqno = ring_status_page_get_seqno,
866 .user_irq_get = blt_ring_get_user_irq,
867 .user_irq_put = blt_ring_put_user_irq,
868 .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer,
840}; 869};
841 870
842int intel_init_render_ring_buffer(struct drm_device *dev) 871int intel_init_render_ring_buffer(struct drm_device *dev)
@@ -866,3 +895,12 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
866 895
867 return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); 896 return intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
868} 897}
898
899int intel_init_blt_ring_buffer(struct drm_device *dev)
900{
901 drm_i915_private_t *dev_priv = dev->dev_private;
902
903 dev_priv->blt_ring = gen6_blt_ring;
904
905 return intel_init_ring_buffer(dev, &dev_priv->blt_ring);
906}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 5b37ff3a6949..9e81ff3b39cd 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -22,6 +22,7 @@ struct intel_ring_buffer {
22 enum intel_ring_id { 22 enum intel_ring_id {
23 RING_RENDER = 0x1, 23 RING_RENDER = 0x1,
24 RING_BSD = 0x2, 24 RING_BSD = 0x2,
25 RING_BLT = 0x4,
25 } id; 26 } id;
26 u32 mmio_base; 27 u32 mmio_base;
27 unsigned long size; 28 unsigned long size;
@@ -124,6 +125,7 @@ u32 intel_ring_get_seqno(struct drm_device *dev,
124 125
125int intel_init_render_ring_buffer(struct drm_device *dev); 126int intel_init_render_ring_buffer(struct drm_device *dev);
126int intel_init_bsd_ring_buffer(struct drm_device *dev); 127int intel_init_bsd_ring_buffer(struct drm_device *dev);
128int intel_init_blt_ring_buffer(struct drm_device *dev);
127 129
128u32 intel_ring_get_active_head(struct drm_device *dev, 130u32 intel_ring_get_active_head(struct drm_device *dev,
129 struct intel_ring_buffer *ring); 131 struct intel_ring_buffer *ring);
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index e41c74facb6a..8c641bed9bbd 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -286,6 +286,7 @@ typedef struct drm_i915_irq_wait {
286#define I915_PARAM_HAS_PAGEFLIPPING 8 286#define I915_PARAM_HAS_PAGEFLIPPING 8
287#define I915_PARAM_HAS_EXECBUF2 9 287#define I915_PARAM_HAS_EXECBUF2 9
288#define I915_PARAM_HAS_BSD 10 288#define I915_PARAM_HAS_BSD 10
289#define I915_PARAM_HAS_BLT 11
289 290
290typedef struct drm_i915_getparam { 291typedef struct drm_i915_getparam {
291 int param; 292 int param;
@@ -627,8 +628,11 @@ struct drm_i915_gem_execbuffer2 {
627 __u32 num_cliprects; 628 __u32 num_cliprects;
628 /** This is a struct drm_clip_rect *cliprects */ 629 /** This is a struct drm_clip_rect *cliprects */
629 __u64 cliprects_ptr; 630 __u64 cliprects_ptr;
631#define I915_EXEC_RING_MASK (7<<0)
632#define I915_EXEC_DEFAULT (0<<0)
630#define I915_EXEC_RENDER (1<<0) 633#define I915_EXEC_RENDER (1<<0)
631#define I915_EXEC_BSD (1<<1) 634#define I915_EXEC_BSD (2<<0)
635#define I915_EXEC_BLT (3<<0)
632 __u64 flags; 636 __u64 flags;
633 __u64 rsvd1; 637 __u64 rsvd1;
634 __u64 rsvd2; 638 __u64 rsvd2;