diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-19 06:19:32 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-21 14:08:39 -0400 |
commit | 549f7365820a212a1cfd0871d377b1ad0d1e5723 (patch) | |
tree | dbd39c10b32b35b762b083a358b7fc4c09783d5b /drivers/gpu | |
parent | e36c1cd7292efcb8daca26cd6331481736544742 (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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 64 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 92 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 2 |
10 files changed, 170 insertions, 62 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 | ||
163 | static const struct intel_device_info intel_sandybridge_m_info = { | 164 | static 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 | ||
169 | static const struct pci_device_id pciidlist[] = { /* aka */ | 171 | 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 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 | ||
221 | enum no_fbc_reason { | 222 | enum 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 | ||
1927 | static void | 1929 | static 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 | ||
4522 | cleanup_bsd_ring: | ||
4523 | intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); | ||
4489 | cleanup_render_ring: | 4524 | cleanup_render_ring: |
4490 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); | 4525 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); |
4491 | cleanup_pipe_control: | 4526 | cleanup_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 | ||
296 | static 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 | |||
296 | static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | 309 | static 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 | ||
385 | static u32 | 385 | static u32 |
386 | bsd_ring_add_request(struct drm_device *dev, | 386 | ring_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 | ||
420 | static u32 | 420 | static u32 |
421 | bsd_ring_get_seqno(struct drm_device *dev, | 421 | ring_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 | ||
427 | static int | 427 | static int |
428 | bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | 428 | ring_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 | |||
445 | static int | 444 | static int |
446 | render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | 445 | render_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 | ||
792 | static void gen6_bsd_ring_flush(struct drm_device *dev, | 791 | static 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 | ||
805 | static int | 804 | static int |
806 | gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | 805 | gen6_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 | |||
843 | static void | ||
844 | blt_ring_get_user_irq(struct drm_device *dev, | ||
845 | struct intel_ring_buffer *ring) | ||
846 | { | ||
847 | /* do nothing */ | ||
848 | } | ||
849 | static void | ||
850 | blt_ring_put_user_irq(struct drm_device *dev, | ||
851 | struct intel_ring_buffer *ring) | ||
852 | { | ||
853 | /* do nothing */ | ||
854 | } | ||
855 | |||
856 | static 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 | ||
842 | int intel_init_render_ring_buffer(struct drm_device *dev) | 871 | int 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 | |||
899 | int 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 | ||
125 | int intel_init_render_ring_buffer(struct drm_device *dev); | 126 | int intel_init_render_ring_buffer(struct drm_device *dev); |
126 | int intel_init_bsd_ring_buffer(struct drm_device *dev); | 127 | int intel_init_bsd_ring_buffer(struct drm_device *dev); |
128 | int intel_init_blt_ring_buffer(struct drm_device *dev); | ||
127 | 129 | ||
128 | u32 intel_ring_get_active_head(struct drm_device *dev, | 130 | u32 intel_ring_get_active_head(struct drm_device *dev, |
129 | struct intel_ring_buffer *ring); | 131 | struct intel_ring_buffer *ring); |