summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-05-15 13:04:46 -0700
committerEric Anholt <eric@anholt.net>2015-06-04 14:15:36 -0700
commitc142c62b580d988adf2baa40e5f09302f3a0f9d9 (patch)
treee2b3707f98748fedac7c7bdb06ebee7f2e09d052
parente624e229ca70b4285da4063bd6261639e3df37d6 (diff)
downloadlinux-c142c62b580d988adf2baa40e5f09302f3a0f9d9.tar.gz
drm/vc4: Make sure we clean up GEM if probe fails.
We often return -EPROBE_DEFER from the various components, and we would have left a bunch of GEM stuff running and allocated. Cleans up a boot-time warning about how we leaked the 256k of overflow_mem. Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c35
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h2
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c21
-rw-r--r--drivers/gpu/drm/vc4/vc4_irq.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c13
6 files changed, 75 insertions, 4 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index ba91b7c17ab1..62e8a0c27a39 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -25,6 +25,23 @@ static struct {
u32 size_cached;
} bo_stats;
+static void
+vc4_bo_stats_dump(void)
+{
+ DRM_INFO("num bos allocated: %d\n",
+ bo_stats.num_allocated);
+ DRM_INFO("size bos allocated: %dkb\n",
+ bo_stats.size_allocated / 1024);
+ DRM_INFO("num bos used: %d\n",
+ bo_stats.num_allocated - bo_stats.num_cached);
+ DRM_INFO("size bos used: %dkb\n",
+ (bo_stats.size_allocated - bo_stats.size_cached) / 1024);
+ DRM_INFO("num bos cached: %d\n",
+ bo_stats.num_cached);
+ DRM_INFO("size bos cached: %dkb\n",
+ bo_stats.size_cached / 1024);
+}
+
static uint32_t
bo_page_index(size_t size)
{
@@ -88,7 +105,7 @@ vc4_get_cache_list_for_size(struct drm_device *dev, size_t size)
return &vc4->bo_cache.size_list[page_index];
}
-static void
+void
vc4_bo_cache_purge(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -273,6 +290,22 @@ vc4_bo_cache_init(struct drm_device *dev)
(unsigned long) dev);
}
+void
+vc4_bo_cache_destroy(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ del_timer(&vc4->bo_cache.time_timer);
+ cancel_work_sync(&vc4->bo_cache.time_work);
+
+ vc4_bo_cache_purge(dev);
+
+ if (bo_stats.num_allocated) {
+ DRM_ERROR("Destroying BO cache while BOs still allocated:\n");
+ vc4_bo_stats_dump();
+ }
+}
+
struct drm_gem_object *
vc4_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
{
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 471f6bcaee95..8d32dca645ad 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -78,8 +78,10 @@ vc4_drm_load(struct drm_device *dev, unsigned long flags)
vc4_gem_init(dev);
ret = component_bind_all(dev->dev, dev);
- if (ret)
+ if (ret) {
+ vc4_gem_destroy(dev);
return ret;
+ }
vc4_kms_load(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fa14c801b1a4..57b889e072ef 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -353,6 +353,7 @@ void vc4_disable_vblank(struct drm_device *dev, int crtc_id);
/* vc4_bo.c */
void vc4_bo_cache_init(struct drm_device *dev);
+void vc4_bo_cache_destroy(struct drm_device *dev);
void vc4_free_object(struct drm_gem_object *gem_obj);
struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size);
int vc4_dumb_create(struct drm_file *file_priv,
@@ -377,6 +378,7 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
/* vc4_gem.c */
void vc4_gem_init(struct drm_device *dev);
+void vc4_gem_destroy(struct drm_device *dev);
int vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int vc4_wait_seqno_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index c2561ea1cdb3..3cec0eb16a12 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -634,3 +634,24 @@ vc4_gem_init(struct drm_device *dev)
vc4_bo_cache_init(dev);
}
+
+void
+vc4_gem_destroy(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ /* Waiting for exec to finish would need to be done before
+ * unregistering V3D.
+ */
+ WARN_ON(vc4->emit_seqno != vc4->finished_seqno);
+
+ /* V3D should already have disabled its interrupt and cleared
+ * the overflow allocation registers. Now free the object.
+ */
+ if (vc4->overflow_mem) {
+ drm_gem_object_unreference_unlocked(&vc4->overflow_mem->base.base);
+ vc4->overflow_mem = NULL;
+ }
+
+ vc4_bo_cache_destroy(dev);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index c2f539c3b6c6..df9c4c86fa34 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -167,13 +167,13 @@ vc4_irq_uninstall(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
- cancel_work_sync(&vc4->overflow_mem_work);
-
V3D_WRITE(V3D_INTENA, 0);
V3D_WRITE(V3D_INTDIS, 0);
/* Clear any pending interrupts we might have left. */
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
+
+ cancel_work_sync(&vc4->overflow_mem_work);
}
/** Reinitializes interrupt registers when a GPU reset is performed. */
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index 9321fa2a2f23..2ac27c9944f1 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -200,6 +200,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
return -EINVAL;
}
+ /* Reset the binner overflow address/size at setup, to be sure
+ * we don't reuse an old one.
+ */
+ V3D_WRITE(V3D_BPOA, 0);
+ V3D_WRITE(V3D_BPOS, 0);
+
vc4_v3d_init_hw(drm);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
@@ -219,6 +225,13 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
drm_irq_uninstall(drm);
+ /* Disable the binner's overflow memory address, so the next
+ * driver probe (if any) doesn't try to reuse our old
+ * allocation.
+ */
+ V3D_WRITE(V3D_BPOA, 0);
+ V3D_WRITE(V3D_BPOS, 0);
+
vc4->v3d = NULL;
}