summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 748041aa84df..9b406e424a6f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1422,8 +1422,16 @@ err_unref:
static int intel_init_ring_buffer(struct drm_device *dev,
struct intel_engine_cs *ring)
{
+ struct intel_ringbuffer *ringbuf = ring->buffer;
int ret;
+ if (ringbuf == NULL) {
+ ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
+ if (!ringbuf)
+ return -ENOMEM;
+ ring->buffer = ringbuf;
+ }
+
ring->dev = dev;
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
@@ -1435,18 +1443,18 @@ static int intel_init_ring_buffer(struct drm_device *dev,
if (I915_NEED_GFX_HWS(dev)) {
ret = init_status_page(ring);
if (ret)
- return ret;
+ goto error;
} else {
BUG_ON(ring->id != RCS);
ret = init_phys_status_page(ring);
if (ret)
- return ret;
+ goto error;
}
ret = allocate_ring_buffer(ring);
if (ret) {
DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret);
- return ret;
+ goto error;
}
/* Workaround an erratum on the i830 which causes a hang if
@@ -1459,9 +1467,18 @@ static int intel_init_ring_buffer(struct drm_device *dev,
ret = i915_cmd_parser_init_ring(ring);
if (ret)
- return ret;
+ goto error;
+
+ ret = ring->init(ring);
+ if (ret)
+ goto error;
+
+ return 0;
- return ring->init(ring);
+error:
+ kfree(ringbuf);
+ ring->buffer = NULL;
+ return ret;
}
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
@@ -1488,6 +1505,9 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
cleanup_status_page(ring);
i915_cmd_parser_fini_ring(ring);
+
+ kfree(ring->buffer);
+ ring->buffer = NULL;
}
static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
@@ -2022,15 +2042,24 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+ struct intel_ringbuffer *ringbuf = ring->buffer;
int ret;
+ if (ringbuf == NULL) {
+ ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
+ if (!ringbuf)
+ return -ENOMEM;
+ ring->buffer = ringbuf;
+ }
+
ring->name = "render ring";
ring->id = RCS;
ring->mmio_base = RENDER_RING_BASE;
if (INTEL_INFO(dev)->gen >= 6) {
/* non-kms not supported on gen6+ */
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_ringbuf;
}
/* Note: gem is not supported on gen5/ilk without kms (the corresponding
@@ -2074,16 +2103,24 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
if (ring->virtual_start == NULL) {
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_ringbuf;
}
if (!I915_NEED_GFX_HWS(dev)) {
ret = init_phys_status_page(ring);
if (ret)
- return ret;
+ goto err_vstart;
}
return 0;
+
+err_vstart:
+ iounmap(ring->virtual_start);
+err_ringbuf:
+ kfree(ringbuf);
+ ring->buffer = NULL;
+ return ret;
}
int intel_init_bsd_ring_buffer(struct drm_device *dev)